1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
|
;
; Oliver Schmidt, 2009-09-15
;
; Startup code for cc65 (Apple2 version)
;
.export _exit, done, return
.export __STARTUP__ : absolute = 1 ; Mark as startup
.import initlib, donelib
.import zerobss, callmain
.import __ONCE_LOAD__, __ONCE_SIZE__ ; Linker generated
.import __LC_START__, __LC_LAST__ ; Linker generated
.include "zeropage.inc"
.include "apple2.inc"
; ------------------------------------------------------------------------
.segment "STARTUP"
; ProDOS TechRefMan, chapter 5.2.1:
; "For maximum interrupt efficiency, a system program should not
; use more than the upper 3/4 of the stack."
ldx #$FF
txs ; Init stack pointer
; Save space by putting some of the start-up code in the ONCE segment,
; which can be re-used by the BSS segment, the heap and the C stack.
jsr init
; Clear the BSS data.
jsr zerobss
; Push the command-line arguments; and, call main().
jsr callmain
; Avoid a re-entrance of donelib. This is also the exit() entry.
_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 the module destructors.
jsr donelib
; Restore the original RESET vector.
exit: ldx #$02
: lda rvsave,x
sta SOFTEV,x
dex
bpl :-
; Copy back the zero-page stuff.
ldx #zpspace-1
: lda zpsave,x
sta sp,x
dex
bpl :-
; ProDOS TechRefMan, chapter 5.2.1:
; "System programs should set the stack pointer to $FF at the
; warm-start entry point."
ldx #$FF
txs ; Re-init stack pointer
; We're done
jmp done
; ------------------------------------------------------------------------
.segment "ONCE"
; Save the zero-page locations that we need.
init: ldx #zpspace-1
: lda sp,x
sta zpsave,x
dex
bpl :-
; Save the original RESET vector.
ldx #$02
: lda SOFTEV,x
sta rvsave,x
dex
bpl :-
; Check for ProDOS.
ldy $BF00 ; MLI call entry point
cpy #$4C ; Is MLI present? (JMP opcode)
bne basic
; Check the 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 the ProDOS dispatcher instead.
lda #<quit
ldx #>quit
sta done+1
stx done+2
; No BASIC.SYSTEM; so, use the addr of the ProDOS system global page.
lda #<$BF00
ldx #>$BF00
bne :+ ; Branch always
; Get the highest available mem addr from the BASIC interpreter.
basic: lda HIMEM
ldx HIMEM+1
; Set up the C stack.
: sta sp
stx sp+1
; ProDOS TechRefMan, chapter 5.3.5:
; "Your system program should place in the RESET vector the
; address of a routine that ... closes the files."
ldx #<_exit
lda #>_exit
jsr reset ; Setup RESET vector
; Call the module constructors.
jsr initlib
; Switch in LC bank 2 for W/O.
bit $C081
bit $C081
; Set the source start address.
; Aka __LC_LOAD__ iff segment LC exists.
lda #<(__ONCE_LOAD__ + __ONCE_SIZE__)
ldy #>(__ONCE_LOAD__ + __ONCE_SIZE__)
sta $9B
sty $9C
; Set the source last address.
; Aka __LC_LOAD__ + __LC_SIZE__ iff segment LC exists.
lda #<((__ONCE_LOAD__ + __ONCE_SIZE__) + (__LC_LAST__ - __LC_START__))
ldy #>((__ONCE_LOAD__ + __ONCE_SIZE__) + (__LC_LAST__ - __LC_START__))
sta $96
sty $97
; Set the destination last address.
; Aka __LC_RUN__ + __LC_SIZE__ iff segment LC exists.
lda #<__LC_LAST__
ldy #>__LC_LAST__
sta $94
sty $95
; Call into Applesoft Block Transfer Up -- which handles zero-
; sized blocks well -- to move the content of the LC memory area.
jsr $D39A ; BLTU2
; Switch in LC bank 2 for R/O and return.
bit $C080
rts
; ------------------------------------------------------------------------
.code
; Set up the RESET vector.
reset: stx SOFTEV
sta SOFTEV+1
eor #$A5
sta PWREDUP
return: rts
; Quit to the 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
; Final jump when we're done
done: jmp DOSWARM ; Potentially patched at runtime
; ------------------------------------------------------------------------
.segment "INIT"
zpsave: .res zpspace
rvsave: .res 3
|