aboutsummaryrefslogtreecommitdiff
path: root/bank3.s
blob: 9a1fce117cf389c5f9f064b379ad25f5bad9f23d (plain)
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_32_pages:
; copy 8192 bytes from $8000-$9fff to (destptr).
; on exit, destptr points to the next 8192 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_32_pages:
 ldx #$20
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_32_pages

 lda #1    ; bank 1...
 sta CCNTL ; ...select it
 jsr copy_32_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 "bank 3 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)