Monday, January 9, 2012

MKHBC-8-R1 homebrew 6502 based computer - coding in 'C', CC65 compiler.


Today I configured environment to compile 'C' programs for my platform. I use my favorite cc65 compiler. The documentation contains nice comprehensive tutorial how to configure compiler to target your specific 6502 based hardware platform. Using that tutorial I created my ctr0.s assembler file - to be added to custom library - that defines start up code for custom platform:


; ---------------------------------------------------------------------------
;
; File:        crt0.s
; Author:    Marek Karcz
;
; Original work: cc65 documentation/customization tutorial
;
; Purpose:
;
;     Startup code for cc65 (MKHBC-8-R1 version, to run under MKHBCOS,
;     M.O.S. derivative).
;
; Revision history:
;
; 2012-01-10:
;    Initial revision.
;
; ---------------------------------------------------------------------------

.export   _init, _exit
.import   _main

.export   __STARTUP__ : absolute = 1        ; Mark as startup
.import   __RAM_START__, __RAM_SIZE__       ; Linker generated

.import    copydata, zerobss, initlib, donelib

.include  "zeropage.inc"

; ---------------------------------------------------------------------------
; Place the startup code in a special segment

.segment  "STARTUP"

; ---------------------------------------------------------------------------
; A little light 6502 housekeeping

; This is the entry point of compiled and linked program when ran under
; M.O.S. Look in the map file for beginning of STARTUP segment.
; Provide that address to 'x' command (remember to use lower letters).

_init:    
        ; NOTE: This part is already done by MKHBCOS
          ;LDX     #$FF                 ; Initialize stack pointer to $01FF
          ;TXS
          ;CLD                          ; Clear decimal mode

; ---------------------------------------------------------------------------
; Set cc65 argument stack pointer
; Must run, otherwise stack pointer will point to $ffff.

          LDA     #<(__RAM_START__ + __RAM_SIZE__)
          STA     sp
          LDA     #>(__RAM_START__ + __RAM_SIZE__)
          STA     sp+1

; ---------------------------------------------------------------------------
; Initialize memory storage

;        NOTE: I have no idea why, but with this code enabled, programs
;                do not work under MKHBCOS.

          ;JSR     zerobss              ; Clear BSS segment
          ;JSR     copydata             ; Initialize DATA segment
          ;JSR     initlib              ; Run constructors

; ---------------------------------------------------------------------------
; Call main()

          JSR     _main

; ---------------------------------------------------------------------------
; Back from main (this is also the _exit entry):  force a software break

_exit:    ;JSR     donelib              ; Run destructors
          ;BRK
          rts


I did not figure out yet everything (see commented code and comments), however this setup works for my simple "Hello World" program:

/*
 *
 * File: hello.c
 * Purpose: Hello World program to run under MKHBCOS
 *          (M.O.S. derivative).
 * Author: Marek Karcz
 *
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

extern void mos_puts(char *s);

char hello[] = "Hello World!\n\r";

void my_puts (char *s)
{
    mos_puts(s);
}

int main (void)
{
    my_puts(hello);
    mos_puts("It sure feels good to code in 'C' for g'old MOS 6502!\n\r");

    return 0;
}


...one more:

;------------------------------------------------------------------
;
; File:     puts.s
; Author:    Marek Karcz
; Purpose:    Implement's mos_puts procedure (MKHBCOS's Puts) to be
;            called from C programs (cc65).
;
; Revision history:
;    2012-01-10:
;        Initial revision.
;
;------------------------------------------------------------------

; M.O.S. API defines

.define     mos_StrPtr        $E0
.define     mos_CallPuts    $FFF6

.setcpu    "6502"
.import ldaxysp
.import incsp2

; code

.export _mos_puts

.segment "CODE"

.proc _mos_puts: near

.segment "CODE"

    ldy #$01
    jsr ldaxysp
    sta mos_StrPtr
    stx mos_StrPtr+1
    jsr mos_CallPuts
    jsr incsp2
    rts

.endproc

   
I built everything with this batch script:


cl65 -t none --cpu 6502 --config mkhbcoslib.cfg -l -m hello.map hello.c puts.s mkhbcos.lib
bin2hex -f hello -o hello_prg.txt -w 1024 -x 1039
pause prompt


...and uploaded to my computer. Moment of anxiety.... and....


Success!

That's it for today. Thank you for reading.

M.K.