forked from ArtemioUrbina/huc
/
bare-startup.asm
386 lines (287 loc) · 10.4 KB
/
bare-startup.asm
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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
; ***************************************************************************
; ***************************************************************************
;
; bare-startup.asm
;
; The basic PC Engine HuCARD startup code that runs at boot/reset.
;
; Copyright John Brandwood 2021-2022.
;
; Distributed under the Boost Software License, Version 1.0.
; (See accompanying file LICENSE_1_0.txt or copy at
; http://www.boost.org/LICENSE_1_0.txt)
;
; ***************************************************************************
; ***************************************************************************
;
; This is the initialization code in the 1st bank, and it is responsible for
; setting up a consistant runtime environment for the developer's program,
; so that the developer can concentrate on writing the program itself.
;
; The idea is that when a program is loaded, the first 40KB of it is mapped
; as $4000..$DFFF, and initialization starts at $E000, with the developer's
; program getting control after initialization, with a jump to "bare_main".
;
; The initializtion sets up a small kernel of code that provides interrupt
; handling that mimics a subset of the System Card's behavior, designed to
; act in the same way on HuCARD and CD-ROM, with either the System Card in
; MPR7, or with an overlay in MPR7.
;
; The kernel handles reading the joypad/mouse, and it offers handler hooks
; for running the developer's interrupt code. On CD-ROM systems, it also
; handles the loading and running of subsequent overlay programs.
;
; On HuCARD, the kernel itself runs in MPR7; while on CD-ROM systems it is
; run from RAM in MPR1, so that overlay programs are independant from each
; other, and can be written in different programming languages.
;
;
; We're running on a HuCARD, so the initialization is simple!
;
; The PC Engine's memory map is set to ...
;
; MPR0 = bank $FF : PCE hardware
; MPR1 = bank $F8 : PCE RAM with Stack & ZP
; MPR2 = bank $00 : HuCard ROM
; MPR3 = bank $01 : HuCard ROM
; MPR4 = bank $02 : HuCard ROM
; MPR5 = bank $03 : HuCard ROM
; MPR6 = bank $04 : HuCard ROM
; MPR7 = bank $00 : HuCard ROM
;
; ***************************************************************************
; ***************************************************************************
.nolist
;
; Sanity Check, this is only for HuCARD!
;
.if CDROM
.fail You cannot build for CD-ROM with bare-startup.asm!
.endif CDROM
;
; Support development for the SuperGrafx?
;
; This enables SGX hardware support in certain library functions.
;
.ifndef SUPPORT_SGX
SUPPORT_SGX = 0 ; (0 or 1)
.endif
; Include the equates for the basic PCE hardware.
include "pceas.inc"
include "pcengine.inc"
.list
.mlist
BASE_BANK = 0
.code
.bank BASE_BANK
; ***************************************************************************
; ***************************************************************************
;
; RESET VECTORS (when running in MPR7, either as a HuCard, or a CD overlay)
;
.if USING_NEWPROC ; If the ".proc" trampolines
__trampolineptr = $FFF5 ; are in MPR7, tell PCEAS to
.endif ; put them below the vectors.
; Hardware reset and interrupt vectors.
.org $FFF6
dw bare_irq2 ; IRQ2 (from CD/ADPCM)
dw bare_irq1 ; IRQ1 (from VDC)
dw bare_timer_irq ; TIMER (from CPU)
dw bare_nmi_irq ; NMI (unused)
dw bare_hw_reset ; RESET (HuCARD)
.org $E000 ; This will run in MPR7.
; ***************************************************************************
; ***************************************************************************
;
; Useful constants, needed by joypad library code, and used by many others.
;
const_FFFF: dw $FFFF ; Useful constant for TAI.
const_0000: dw $0000 ; Useful constant for TAI.
bit_mask: db $01,$02,$04,$08,$10,$20,$40,$80
; ***************************************************************************
; ***************************************************************************
;
; Normal HuCard hardware-reset code, executed in MPR7.
;
; This does the basic PCE startup that every HuCard (including
; a System Card) needs to do, and then it remaps memory to be
; compatible with the "CORE(not TM)" CD overlay program start.
;
bare_hw_reset: sei ; Disable interrupts.
csh ; Set high-speed mode.
cld
ldx #$FF ; Initialize stack pointer.
txs
txa ; MPR0 = $FF : PCE hardware
tam0 ; MPR1 = $F8 : PCE RAM
lda #$F8
tam1
stz TIMER_CR ; HW reset already does these,
stz IRQ_ACK ; but this may be a reset from
stz IRQ_MSK ; software (i.e. joypad).
tai const_0000, $2000, 8192 ; Clear RAM.
tma7 ; Not bank 0 if a TED2!
tam2 ; Set CD-ROM overlay memory map,
inc a ; 1st 5 banks in MPR2-MPR6.
tam3
inc a
tam4
inc a
tam5
inc a
tam6
lda #%11111 ; Enable joypad soft-reset.
sta joyena
jsr bare_clr_hooks ; Reset default hooks.
lda VDC_SR ; Purge any overdue VBL.
stz irq_cnt ; Make it easy to check.
cli ; Restore interrupts.
jmp bare_main ; Start the game's code.
; ***************************************************************************
; ***************************************************************************
;
; bare_irq2 - Minimal interrupt handler compatible with System Card.
; bare_irq1 - Minimal interrupt handler compatible with System Card.
; bare_timer_irq - Minimal interrupt handler compatible with System Card.
; bare_nmi_irq - Minimal interrupt handler compatible with System Card.
;
; Note that it takes 8 cycles to respond to an IRQ.
;
; All of the game's actual interrupt handling itself is done in the "hook"
; functions so that everything works the same if the System Card is banked
; into MPR7 when an interrupt occurs.
;
; ***************************************************************************
; ***************************************************************************
;
; Bit settings for irq_vec ...
;
; 7 : 1 to skip BIOS hsync processsing
; 6 : 1 to call [hsync_hook]
; 5 : 1 to skip BIOS vsync processsing
; 4 : 1 to call [vsync_hook]
;
; 3 : 1 to jump [nmi_hook]
; 2 : 1 to jump [timer_hook]
; 1 : 1 to jump [irq1_hook]
; 0 : 1 to jump [irq2_hook]
;
; ***************************************************************************
; ***************************************************************************
bare_irq2: bbs0 <irq_vec, .hook ; 8 cycles if taken.
rti ; No IRQ2 hardware on HuCard.
.hook: jmp [irq2_hook] ; 7 cycles.
;
bare_irq1: bbs1 <irq_vec, .hook ; 8 cycles if taken.
bit VDC_SR ; Clear VDC interrupt.
rti
.hook: jmp [irq1_hook] ; 7 cycles.
;
bare_timer_irq: bbs2 <irq_vec, .hook ; 8 cycles if taken.
stz IRQ_ACK ; Clear timer interrupt.
rti
.hook: jmp [timer_hook] ; 7 cycles.
;
bare_nmi_irq: rti ; No NMI on the PC Engine!
; ***************************************************************************
; ***************************************************************************
;
; bare_clr_hooks - Reset default "CORE(not TM)" interrupt-handling hooks.
;
bare_clr_hooks: php ; Preserve interrupt state.
sei ; Disable interrupts.
lda #<bare_sw_reset ; Set up the soft-reset hook.
sta reset_hook + 0
lda #>bare_sw_reset
sta reset_hook + 1
lda #<irq1_handler ; Set up the IRQ1 hook.
sta irq1_hook + 0
lda #>irq1_handler
sta irq1_hook + 1
lda #%10100010 ; Disable System Card IRQ1
sta <irq_vec ; processing and take over.
plp ; Restore interrupt state.
rts
; ***************************************************************************
; ***************************************************************************
;
; bare_sw_reset - Default HuCARD handler for a joypad "soft-reset".
;
bare_sw_reset: sei ; Disable interrupts.
jmp [$FFFE] ; Jump to the HuCARD reset.
; ***************************************************************************
; ***************************************************************************
;
; irq1_handler - Basic "CORE(not TM)" IRQ1 handler to use as the "irq1_hook".
;
; Doing the IRQ1 handler processing in this hook means that things operate
; the same whether the System Card or an Overlay is paged into MPR7.
;
irq1_handler: pha ; Save all registers.
phx
phy
lda VDC_SR ; Acknowledge the VDC's IRQ.
sta <vdc_sr ; Remember what caused it.
; HSYNC ?
.check_hsync: bbr2 <vdc_sr, .check_vsync ; Is this an HSYNC interrupt?
bbr6 <irq_vec, .check_vsync ; Is a driver registered?
bsr .user_hsync ; Call game's HSYNC code.
; END OF HSYNC HANDLER
; VSYNC ?
.check_vsync: bbr5 <vdc_sr, .exit_irq1 ; Is this a VBLANK interrupt?
lda #VDC_CR ; Update the VDC's Control
sta VDC_AR ; Register.
lda <vdc_crl
sta VDC_DL
inc irq_cnt ; Mark that a VBLANK occurred.
bbr4 <irq_vec, .skip_hookv ; Is a driver registered?
bsr .user_vsync ; Call game's VBLANK code.
.skip_hookv: cli ; Allow HSYNC and TIMER IRQ.
call read_joypads ; Update joypad state.
; END OF VSYNC HANDLER
.exit_irq1:
lda <vdc_reg ; Restore VDC_AR in case we
sta VDC_AR ; changed it.
ply ; Restore all registers.
plx
pla
rti ; Return from interrupt.
.user_hsync: jmp [hsync_hook]
.user_vsync: jmp [vsync_hook]
; ***************************************************************************
; ***************************************************************************
;
; The DATA_BANK location needs to be set as early as possible so that library
; code is able to put data in there before the total overall size of the code
; is known.
;
; By default, DATA_BANK is the next bank after the CORE_BANK.
;
; RESERVE_BANKS allows developers to reserve some banks between the BASE_BANK
; and the DATA_BANK that they can use however they wish.
;
; One use for RESERVE_BANKS is to create empty space that PCEAS can use when
; it relocates procedures. This provides a way for a developer to group code
; together at the start of memory, and leave the maximum number of banks for
; loading dynamic data from CD-ROM.
;
; RESERVE_BANKS is normally defined in each project's "core-config.inc".
;
.ifndef RESERVE_BANKS
RESERVE_BANKS = 0
.endif RESERVE_BANKS
DATA_BANK = BASE_BANK + 1 + RESERVE_BANKS
.zp
.org $2000
_temp ds 2 ; Use within any ASM routine.
_bank ds 1 ; Use within any ASM routine.
base_zp1st = $F8:2003 ; 1st free user address.
base_zpend = $F8:20EC
base_ram1st = $F8:22D0 ; After the System Card!
.bss
.org base_ram1st
.data
.bank DATA_BANK
.org $6000
.opt d+ ; Force DATA labels to MPR3.
.code