gbdk-2020 | GameBoy Development Kit |
| download: https://git.y1.nz/archives/gbdk.tar.gz | |
| README | Files | Log | Refs | LICENSE |
gbdk-lib/libc/targets/sm83/ap/crt0.s
1 .include "global.s"
2
3 ;; ****************************************
4 ;; Beginning of module
5 ;; BANKED: checked
6 .title "Runtime"
7 .module Runtime
8 .area _HEADER (ABS)
9
10 ;; RST vectors
11 ; .org 0x00 ; Trap, utilized by crash_handler.h
12
13 ; .org 0x08 ; --profile handler utilized by emu_debug.h
14
15 ; .org 0x10 ; empty
16
17 ; .org 0x18 ; empty
18
19 .org 0x20 ; RST 0x20 == call HL
20 .call_hl::
21 JP (HL)
22
23 .org 0x28 ; zero up to 256 bytes in C pointed by HL
24 .MemsetSmall::
25 LD (HL+),A
26 DEC C
27 RET Z
28 LD (HL+),A
29 DEC C
30 JR NZ,.MemsetSmall
31 ret
32
33 .org 0x30 ; copy up to 256 bytes in C from DE to HL
34 .MemcpySmall::
35 LD A, (DE)
36 LD (HL+), A
37 INC DE
38 DEC C
39 JR NZ,.MemcpySmall
40 RET
41
42 ; .org 0x38 ; crash handler utilized by crash_handler.h
43
44 ;; Hardware interrupt vectors
45 .org 0x40 ; VBL
46 .int_VBL:
47 PUSH AF
48 PUSH HL
49 LD HL,#.int_0x40
50 JP .int
51
52 ; .org 0x48 ; LCD
53
54 ; .org 0x50 ; TIM
55
56 ; .org 0x58 ; SIO
57
58 ; .org 0x60 ; JOY
59
60 ; .org 0x70
61 ;; space for drawing.s bit table
62
63 .org 0x80
64 .int::
65 PUSH BC
66 PUSH DE
67 1$:
68 LD A,(HL+)
69 OR (HL)
70 JR Z,.int_tail
71 PUSH HL
72 LD A,(HL-)
73 LD L,(HL)
74 LD H,A
75 RST 0x20 ; .call_hl
76 POP HL
77 INC HL
78 JR 1$
79 _wait_int_handler::
80 ADD SP,#4
81 .int_tail:
82 POP DE
83 POP BC
84 POP HL
85
86 ;; we return at least at the beginning of mode 2
87 WAIT_STAT
88
89 POP AF
90 RETI
91
92 ;; VBlank default interrupt routine
93 __standard_VBL_handler::
94 .std_vbl:
95 LD HL,#.sys_time
96 INC (HL)
97 JR NZ,2$
98 INC HL
99 INC (HL)
100 2$:
101 LD A, #1
102 LDH (.vbl_done),A
103
104 JP .refresh_OAM
105
106 _refresh_OAM::
107 WAIT_STAT
108 LD A, #>_shadow_OAM
109 JP .refresh_OAM_DMA
110
111 .clear_WRAM:
112 XOR A
113 LD BC, #l__DATA
114 LD HL, #s__DATA
115 CALL .memset_simple
116
117 LD A, #>_shadow_OAM
118 LDH (__shadow_OAM_base), A
119 LD H, A
120 XOR A
121 LD L, A
122 LD C, #(40 << 2) ; 40 entries 4 bytes each
123 JP .MemsetSmall
124
125 _set_interrupts::
126 DI
127 LDH (.IE),A
128 XOR A
129 EI
130 LDH (.IFL),A ; Clear pending interrupts
131 RET
132
133 ;; Copy OAM data to OAM RAM
134 .start_refresh_OAM:
135 LDH A,(__shadow_OAM_base)
136 OR A
137 RET Z
138 .start_refresh_OAM_DMA:
139 LDH (.DMA),A ; Put A into DMA registers
140 LD A,#0x28 ; We need to wait 160 ns
141 1$:
142 DEC A
143 JR NZ,1$
144 RET
145 .end_refresh_OAM:
146
147 .org .MODE_TABLE
148 ;; Jump table for modes
149 RET
150
151 ;; GameBoy Header
152 .org 0x100
153 .header:
154 JR .code_start
155
156 ;; Nintendo logo
157 .org 0x104
158 .byte 0x01,0x10,0xCE,0xEF,0x00,0x00,0x44,0xAA
159 .byte 0x00,0x74,0x00,0x18,0x11,0x95,0x00,0x34
160 .byte 0x00,0x1A,0x00,0xD5,0x00,0x22,0x00,0x69
161 .byte 0x6F,0xF6,0xF7,0x73,0x09,0x90,0xE1,0x10
162 .byte 0x44,0x40,0x9A,0x90,0xD5,0xD0,0x44,0x30
163 .byte 0xA9,0x21,0x5D,0x48,0x22,0xE0,0xF8,0x60
164
165 ;; Title of the game
166 .org 0x134
167 .asciz "Title"
168
169 .org 0x144
170 .byte 0,0,0
171
172 ;; Cartridge type is ROM only
173 .org 0x147
174 .byte 0
175
176 ;; ROM size is 32kB
177 .org 0x148
178 .byte 0
179
180 ;; RAM size is 0kB
181 .org 0x149
182 .byte 0
183
184 ;; Maker ID
185 .org 0x14A
186 .byte 0x00,0x00
187
188 ;; Version number
189 .org 0x14C
190 .byte 0x01
191
192 ;; Complement check
193 .org 0x14D
194 .byte 0x00
195
196 ;; Checksum
197 .org 0x14E
198 .byte 0x00,0x00
199
200 ;; ****************************************
201 .org 0x150
202
203 ;; soft reset: falldown to .code_start
204 .reset::
205 _reset::
206 LD A, (__is_GBA)
207 LD B, A
208 LD A, (__cpu)
209
210 ;; Initialization code
211 .code_start::
212 DI ; Disable interrupts
213 LD D, A ; Store CPU type in D
214 LD E, B
215 ;; Initialize the stack
216 LD SP, #.STACK
217
218 PUSH DE
219 ;; Turn the screen off
220 CALL .display_off
221 ;; Clear the static storage
222 CALL .clear_WRAM
223 POP DE
224
225 ;; Store CPU type
226 LD A, D
227 LD (__cpu), A
228 CP #.CGB_TYPE
229 JR NZ, 1$
230 LD A, E
231 AND #0x01
232 LD (__is_GBA), A
233 1$:
234 XOR A
235
236 ; LD (.mode),A ; Clearing (.mode) is performed when clearing RAM
237
238 ;; Initialize the display
239 LDH (.SCY),A
240 LDH (.SCX),A
241 LDH (.STAT),A
242 LDH (.WY),A
243 LD A,#0x07
244 LDH (.WX),A
245
246 ;; Copy refresh_OAM routine to HRAM
247 LD DE,#.start_refresh_OAM ; source
248 LD HL,#.refresh_OAM ; dest
249 LD C,#(.end_refresh_OAM - .start_refresh_OAM) ; size
250 RST 0x30 ; call .MemcpySmall
251
252 ;; Clear the OAM by calling refresh_OAM
253 CALL .refresh_OAM
254
255 ;; Install interrupt routines
256 LD DE,#.std_vbl
257 CALL .add_VBL
258
259 ;; Standard color palettes
260 LD A,#0b11100100 ; Grey 3 = 11 (Black)
261 ; Grey 2 = 10 (Dark grey)
262 ; Grey 1 = 01 (Light grey)
263 ; Grey 0 = 00 (Transparent)
264 LDH (.BGP),A
265 LDH (.OBP0),A
266 LD A,#0b00011011
267 LDH (.OBP1),A
268
269 ;; Turn the screen on
270 LD A,#(LCDCF_ON | LCDCF_WIN9C00 | LCDCF_WINOFF | LCDCF_BG8800 | LCDCF_BG9800 | LCDCF_OBJ8 | LCDCF_OBJOFF | LCDCF_BGOFF)
271 LDH (.LCDC),A
272
273 LD A,#.VBL_IFLAG ; switch on VBlank interrupt only
274 LDH (.IE),A
275
276 XOR A
277 LDH (.IFL),A
278
279 LD HL,#.sys_time
280 LD (HL+),A
281 LD (HL),A
282
283 LDH (.NR52),A ; Turn sound off
284
285 INC A
286 LDH (__current_bank),A ; current bank is 1 at startup
287
288 CALL gsinit
289
290 EI ; Enable interrupts
291
292 ;; Call the main function
293 CALL _main
294 _exit::
295 99$:
296 HALT
297 NOP
298 JR 99$ ; Wait forever
299
300 ;; Wait for VBL interrupt to be finished
301 .wait_vbl_done::
302 _wait_vbl_done::
303 _vsync::
304 ;; Check if the screen is on
305 LDH A,(.LCDC)
306 AND #LCDCF_ON
307 RET Z ; Return if screen is off
308 XOR A
309 LDH (.vbl_done),A ; Clear any previous sets of vbl_done
310 1$:
311 HALT ; Wait for any interrupt
312 NOP ; HALT sometimes skips the next instruction
313 LDH A,(.vbl_done) ; Was it a VBlank interrupt?
314 ;; Warning: we may lose a VBlank interrupt, if it occurs now
315 OR A
316 JR Z,1$ ; No: back to sleep!
317 RET
318
319 ;; Remove interrupt routine in DE from the VBL interrupt list
320 ;; falldown to .remove_int
321 _remove_VBL::
322 .remove_VBL::
323 LD HL,#.int_0x40
324
325 ;; Remove interrupt DE from interrupt list HL if it exists
326 ;; Abort if a 0000 is found (end of list)
327 .remove_int::
328 1$:
329 LD A,(HL+)
330 LD C,A
331 LD A,(HL+)
332 LD B,A
333 OR C
334 RET Z ; No interrupt found
335
336 LD A,E
337 CP C
338 JR NZ,1$
339 LD A,D
340 CP B
341 JR NZ,1$
342
343 LD B,H
344 LD C,L
345 DEC BC
346 DEC BC
347
348 ;; Now do a memcpy from here until the end of the list
349 2$:
350 LD A,(HL+)
351 LD (BC),A
352 INC BC
353 LD D,A
354 LD A,(HL+)
355 LD (BC),A
356 INC BC
357 OR D
358 JR NZ, 2$
359 RET
360
361 ;; Add interrupt routine in BC to the VBL interrupt list
362 ;; falldown to .add_int
363 _add_VBL::
364 .add_VBL::
365 LD HL,#.int_0x40
366
367 ;; Add interrupt routine in BC to the interrupt list in HL
368 .add_int::
369 1$:
370 LD A,(HL+)
371 OR (HL)
372 JR Z,2$
373 INC HL
374 JR 1$
375 2$:
376 LD A,D
377 LD (HL-),A
378 LD (HL),E
379 RET
380
381 ;; ****************************************
382
383 ;; Ordering of segments for the linker
384 ;; Code that really needs to be in bank 0
385 .area _HOME
386 ;; Similar to _HOME
387 .area _BASE
388 ;; Code
389 .area _CODE
390 ;; #pragma bank 0 workaround
391 .area _CODE_0
392 ;; Constant data
393 .area _LIT
394 ; ;; since _CODE_1 area base address is pre-defined in the linker from 0x4000,
395 ; ;; that moves initializer code and tables out of bank 0
396 ; .area _CODE_1
397 ;; Constant data, used to init _DATA
398 .area _INITIALIZER
399 ;; Code, used to init _DATA
400 .area _GSINIT
401 .area _GSFINAL
402 ;; Uninitialised ram data
403 .area _DATA
404 .area _BSS
405 ;; Initialised in ram data
406 .area _INITIALIZED
407 ;; For malloc
408 .area _HEAP
409 .area _HEAP_END
410 ;; High RAM area
411 .area _HRAM
412
413 .area _DATA
414 __cpu::
415 .ds 0x01 ; GB type (GB, PGB, CGB)
416 __is_GBA::
417 .ds 0x01 ; detect GBA
418 .mode::
419 .ds 0x01 ; Current mode
420 .sys_time::
421 _sys_time::
422 .ds 0x02 ; System time in VBL units
423 .int_0x40::
424 .blkw 0x06 ; 5 interrupt handlers: 1 built-in + 4 user-defined
425
426 .area _HRAM
427 .refresh_OAM::
428 .ds (.start_refresh_OAM_DMA - .start_refresh_OAM)
429 .refresh_OAM_DMA:
430 .ds (.end_refresh_OAM - .start_refresh_OAM_DMA)
431
432 .bndry 0x10
433
434 __current_bank::
435 .ds 0x01 ; Current bank
436 .vbl_done:
437 __vbl_done::
438 .ds 0x01 ; Is VBL interrupt finished?
439 __shadow_OAM_base::
440 .ds 0x01
441
442 ;; Runtime library
443 .area _GSINIT
444
445 gsinit::
446 ;; initialize static storage variables
447 LD BC, #l__INITIALIZER
448 LD HL, #s__INITIALIZER
449 LD DE, #s__INITIALIZED
450 CALL .memcpy_simple
451
452 .area _GSFINAL
453
454 RET
455
456 .area _HOME
457
458 ;; fills memory at HL of length BC with A, clobbers DE
459 .memset_simple::
460 LD E, A
461 LD A, B
462 OR C
463 RET Z
464 LD (HL), E
465 DEC BC
466 LD D, H
467 LD E, L
468 INC DE
469
470 ;; copies BC bytes from HL into DE
471 .memcpy_simple::
472 LD A, B
473 OR C
474 RET Z
475
476 SRL B
477 RR C
478 JR NC,3$
479 LD A, (HL+)
480 LD (DE), A
481 INC DE
482 3$:
483 INC B
484 INC C
485 JR 2$
486 1$:
487 LD A, (HL+)
488 LD (DE), A
489 INC DE
490 LD A, (HL+)
491 LD (DE), A
492 INC DE
493 2$:
494 DEC C
495 JR NZ,1$
496 DEC B
497 JR NZ,1$
498 4$:
499 RET
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.