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
|
; bank 3 of the cartridge image, to be built with -t none.
; this bank is the fixed bank, always mapped at $a000-$bfff, in
; the "left cartridge" area.
.macpack atari ; for scrcode (screen code) macro
.include "atari.inc"
; zero page temporaries
destptr = FR0
srcptr = FR1
; where the romable_taimain code was org'ed.
codedest = $0400
; address of the font, which lives in bank 3 of the cart.
font = $9c00
; cc65's atari.inc fails to define this standard Atari label.
CCNTL = $d500
; cart_trailer is my name for what the OS calls CARTLOC.
; cc65's atari.inc doesn't define it either.
cart_trailer = $bffa
.org $a000 ; left cartridge
screendata:
; uncompressed title screen bitmap, $1700 bytes
.incbin "titledata.dat"
;.out .sprintf("next byte after titledata is %x", *)
; message to print when someone tries to boot the cart
; in a 16K Atari.
mem_msg:
scrcode "Need at least 32K"
mem_msg_len = * - mem_msg - 1
; copy_31_pages:
; copy 7936 bytes from $8000-$9dff to (destptr).
; on exit, destptr points to the next 7936 byte chunk.
; copy_x_pages:
; as above, but accepts number of pages to copy in X register.
; copy_pages:
; as copy_x_pages, but the caller must set up srcptr as well
; as the X reg.
copy_31_pages:
ldx #$1f
copy_x_pages:
lda #$0
sta srcptr
lda #$80
sta srcptr+1
copy_pages:
ldy #0
@copypage:
lda (srcptr),y
sta (destptr),y
dey
bne @copypage
inc srcptr+1
inc destptr+1
dex
bne @copypage
init:
rts
memory_error:
lda #$20 ; red BG
sta COLOR2
ldy #mem_msg_len
@mloop:
lda mem_msg,y
sta (SAVMSC),y
dey
bpl @mloop
@hang:
bmi @hang
.out .sprintf("fudge factor: %d bytes", $b744-*)
.res $b744-*, $ff ; fudge factor, keep the DL from crossing a 1K boundary
; newtitle.s is the display list and menu code. CART_TARGET is used
; for conditional assembly (to make it work from ROM).
CART_TARGET = 1
.include "newtitle.s"
cartstart:
lda RAMTOP
cmp #$80
beq mem_ok
jmp memory_error
mem_ok:
; turn off ANTIC DMA to speed up copying to RAM
lda #0
sta SDMCTL
sta DMACTL
; copy code to RAM
lda #<codedest
sta destptr
lda #>codedest
sta destptr+1
; banks 0 and 1 are full of code (minus the top page), bank 2
; is partially full. At some point, bank 2 might disappear, if
; I can shrink the code down to fit in 0 and 1 only.
lda #0 ; bank 0...
sta CCNTL ; ...select it
jsr copy_31_pages
lda #1 ; bank 1...
sta CCNTL ; ...select it
jsr copy_31_pages
; tail end of the code is stored in this bank.
lda #<code_tail
sta srcptr
lda #>code_tail
sta srcptr+1
ldx #(>code_tail_size)+1
jsr copy_pages
; bank 2 contains our font, RODATA, and some code (HIGHCODE seg) that
; runs from ROM rather than being copied to RAM. It stays enabled the
; entire time the game is running.
lda #2 ; bank 2...
sta CCNTL ; ...select it
lda #1
sta COLDST ; System Reset = reboot
jsr start ; 'start' is from newtitle.s
jsr codedest ; run the game (romable_taimain)
jmp cartstart ; redisplay title screen if "play again? N"
code_tail:
.incbin "splitrom.raw.2"
code_tail_size = * - code_tail + 1
.out .sprintf("code_tail_size $%x (%d pages)", code_tail_size, (>code_tail_size)+1)
.if * > cart_trailer
.fatal "bank7 code too large"
.else
.out .sprintf("=> %d bytes free in bank 3, at %x", cart_trailer - *, *)
.endif
; fill with 1 bits until the cart trailer
.res cart_trailer - *, $ff
; trailer (some docs called it a 'header' but, eh, it doesn't come at
; the head of the cart...)
; see Mapping the Atari's entry for 'Cartridge B' or the Tech Ref Manual
; for a description of this.
.word cartstart ; entry point
.byte 0 ; 0 = cartridge present
.byte 4 ; init and run the cart, don't boot the disk, non-diagnostic
.word init ; init address (just an RTS)
|