]> git.sur5r.net Git - cc65/blobdiff - libsrc/apple2/crt0.s
don't use constructor to setup runtime stack
[cc65] / libsrc / apple2 / crt0.s
index 4be1d0eb7f05bb3b61fa3053da7b0b4530ceceb9..53b8043ca3f8ae312dbd1afcb71bdefeb309a182 100644 (file)
@@ -1,27 +1,32 @@
 ;
-; Startup code for cc65 (Apple2 version)
+; Oliver Schmidt, 15.09.2009
 ;
-; This must be the *first* file on the linker command line
+; Startup code for cc65 (Apple2 version)
 ;
 
-        .export         _exit
+        .export         _exit, done, return
+        .export         __STARTUP__ : absolute = 1      ; Mark as startup
         .import         zerobss
         .import        initlib, donelib
         .import        callmain, callirq
-        .import         COUT
-        .import                __STARTUP_LOAD__, __BSS_LOAD__  ; Linker generated
+        .import                __RAM_START__ , __RAM_LAST__    ; Linker generated
+        .import         __MOVE_START__, __MOVE_LAST__  ; Linker generated
+        .import         __LC_START__  , __LC_LAST__    ; Linker generated
+        .import                __ZPSAVE_RUN__, __INIT_SIZE__   ; Linker generated
         .import                __INTERRUPTOR_COUNT__           ; Linker generated
 
         .include        "zeropage.inc"
         .include        "apple2.inc"
-        .include        "mli.inc"
+
+        .linecont      +
 
 ; ------------------------------------------------------------------------
 
         .segment        "EXEHDR"
 
-        .addr           __STARTUP_LOAD__                ; Start address
-        .word           __BSS_LOAD__ - __STARTUP_LOAD__        ; Size
+        .addr           __RAM_START__                  ; Start address
+        .word           __ZPSAVE_RUN__ - __RAM_START__ + \
+                       __MOVE_LAST__  - __MOVE_START__ ; Size
 
 ; ------------------------------------------------------------------------
 
         ldx     #$FF
         txs                            ; Init stack pointer
 
-        ; Delegate all further processing to keep STARTUP small
+       ; Switch in LC bank 2 for W/O
+       bit     $C081
+       bit     $C081
+
+       ; Set source start address
+       lda     #<(__ZPSAVE_RUN__ + __INIT_SIZE__)
+       ldy     #>(__ZPSAVE_RUN__ + __INIT_SIZE__)
+       sta     $9B
+       sty     $9C
+
+       ; Set source last address
+       lda     #<(__ZPSAVE_RUN__ + __INIT_SIZE__ + __LC_LAST__ - __LC_START__)
+       ldy     #>(__ZPSAVE_RUN__ + __INIT_SIZE__ + __LC_LAST__ - __LC_START__)
+       sta     $96
+       sty     $97
+
+       ; Set destination last address
+       lda     #<__LC_LAST__
+       ldy     #>__LC_LAST__
+       sta     $94
+       sty     $95
+
+       ; Call into Applesoft Block Transfer Utility - which handles zero
+       ; sized blocks well - to move content of the LC memory area
+       jsr     $D396           ; BLTU + 3
+
+       ; Set source start address
+       lda     #<__ZPSAVE_RUN__
+       ldy     #>__ZPSAVE_RUN__
+       sta     $9B
+       sty     $9C
+
+       ; Set source last address
+       lda     #<(__ZPSAVE_RUN__ + __INIT_SIZE__)
+       ldy     #>(__ZPSAVE_RUN__ + __INIT_SIZE__)
+       sta     $96
+       sty     $97
+
+       ; Set destination last address
+       lda     #<__RAM_LAST__
+       ldy     #>__RAM_LAST__
+       sta     $94
+       sty     $95
+
+       ; Call into Applesoft Block Transfer Utility - which handles moving
+       ; overlapping blocks upwards well - to move the INIT segment
+       jsr     $D396           ; BLTU + 3
+
+        ; Delegate all further processing to keep the STARTUP segment small
         jsr     init
 
         ; Avoid re-entrance of donelib. This is also the _exit entry
@@ -41,18 +94,21 @@ _exit:  ldx     #<exit
         lda     #>exit
         jsr     reset          ; Setup RESET vector
 
+        ; Switch in ROM in case it wasn't already switched in by a RESET
+       bit     $C082
+
         ; Call module destructors
         jsr     donelib
 
         ; Check for valid interrupt vector table entry number
-        lda     intnum
+        lda     int_num
         beq     exit
 
         ; Deallocate interrupt vector table entry
-        dec     params         ; Adjust parameter count
-        jsr     ENTRY
+        dec     i_param                ; Adjust parameter count
+        jsr     $BF00          ; MLI call entry point
         .byte   $41            ; Dealloc interrupt
-        .addr   params
+        .addr   i_param
 
         ; Restore the original RESET vector
 exit:   ldx     #$02
@@ -74,8 +130,8 @@ exit:   ldx     #$02
         ldx     #$FF
         txs                     ; Re-init stack pointer
 
-        ; Back to DOS
-        jmp     DOSWARM
+        ; We're done
+        jmp     (done)
 
 ; ------------------------------------------------------------------------
 
@@ -88,6 +144,9 @@ init:   ldx     #zpspace-1
         dex
         bpl     :-
 
+        ; Clear the BSS data
+        jsr     zerobss
+
         ; Save the original RESET vector
         ldx     #$02
 :       lda     SOFTEV,x
@@ -101,29 +160,48 @@ init:   ldx     #zpspace-1
         ldx     #<_exit
         lda     #>_exit
         jsr     reset          ; Setup RESET vector
-                
-        ; Clear the BSS data
-        jsr     zerobss
 
-        ; Setup the stack
-        lda     HIMEM
-        sta     sp
-        lda     HIMEM+1
-        sta     sp+1                   ; Set argument stack ptr
+        ; Check for ProDOS
+        ldy     $BF00          ; MLI call entry point
+        cpy     #$4C           ; Is MLI present? (JMP opcode)
+        bne     basic
+        
+        ; Check ProDOS system bit map
+        lda     $BF6F           ; protection for pages $B8 - $BF
+        cmp     #%00000001      ; exactly system global page is protected
+        bne     basic
+
+        ; No BASIC.SYSTEM so quit to ProDOS dispatcher instead
+        lda     #<quit
+        ldx     #>quit
+        sta     done
+        stx     done+1
+        
+        ; No BASIC.SYSTEM so use addr of ProDOS system global page
+        lda     #<$BF00
+        ldx     #>$BF00
+        bne     :+              ; Branch always
+
+        ; Get highest available mem addr from BASIC interpreter
+basic:  lda     HIMEM
+        ldx     HIMEM+1
+
+        ; Setup the C stack
+:       sta     sp
+        stx     sp+1
 
         ; Check for interruptors
         lda     #<__INTERRUPTOR_COUNT__
         beq     :+
 
         ; Check for ProDOS
-        lda     ENTRY
-        cmp     #$4C           ; Is MLI present? (JMP opcode)
+        cpy     #$4C           ; Is MLI present? (JMP opcode)
         bne     prterr
 
         ; Allocate interrupt vector table entry
-        jsr     ENTRY
+        jsr     $BF00          ; MLI call entry point
         .byte   $40            ; Alloc interrupt
-        .addr   params
+        .addr   i_param
         bcs     prterr
 
        ; Enable interrupts as old ProDOS versions (i.e. 1.1.1)
@@ -133,13 +211,16 @@ init:   ldx     #zpspace-1
         ; Call module constructors
 :       jsr     initlib
 
+       ; Switch in LC bank 2 for R/O
+       bit     $C080
+
         ; Push arguments and call main()
         jmp     callmain
 
         ; Print error message and return
 prterr: ldx     #msglen-1
 :       lda     errmsg,x
-        jsr     COUT
+        jsr     $FDED          ; COUT
         dex
         bpl     :-
         rts
@@ -166,7 +247,7 @@ msglen = * - errmsg
 
         ; ProDOS TechRefMan, chapter 6.2:
         ; "Each installed routine must begin with a CLD instruction."
-intrpt: cld
+intptr: cld
 
         ; Call interruptors and check for success
         jsr     callirq
@@ -184,25 +265,49 @@ intrpt: cld
 :       sec
         rts
 
-; ------------------------------------------------------------------------
-
-        .code
-
         ; Setup RESET vector
 reset:  stx     SOFTEV
         sta     SOFTEV+1
         eor     #$A5
         sta     PWREDUP
-        rts
+return: rts
+
+        ; Quit to ProDOS dispatcher
+quit:   jsr     $BF00           ; MLI call entry point
+        .byte   $65             ; Quit
+        .word   q_param
 
+; ------------------------------------------------------------------------
+
+        .rodata
+
+        ; MLI parameter list for quit        
+q_param:.byte   $04            ; param_count
+        .byte   $00            ; quit_type
+        .word   $0000          ; reserved
+        .byte   $00            ; reserved
+        .word   $0000          ; reserved
+       
 ; ------------------------------------------------------------------------
 
         .data
 
+        ; MLI parameter list for (de)alloc interrupt
+i_param:.byte   $02            ; param_count
+int_num:.byte   $00            ; int_num
+        .addr   intptr         ; int_code
+
+        ; Location to jump to when we're done
+done:   .addr   DOSWARM
+
+; ------------------------------------------------------------------------
+
+        .segment        "ZPSAVE"
+
 zpsave: .res    zpspace
 
-rvsave: .res    3
+; ------------------------------------------------------------------------
+
+        .bss
 
-params: .byte   $02            ; Parameter count
-intnum: .byte   $00            ; Interrupt number
-        .addr   intrpt         ; Interrupt handler
\ No newline at end of file
+rvsave: .res    3