2 ; Startup code for cc65 (NES version)
4 ; by Groepaz/Hitmen <groepaz@gmx.net>
5 ; based on code by Ullrich von Bassewitz <uz@cc65.org>
7 ; This must be the *first* file on the linker command line
11 .import initlib, donelib
12 .import push0, _main, zerobss
15 ; Linker generated symbols
16 .import __RAM_START__, __RAM_SIZE__
17 .import __SRAM_START__, __SRAM_SIZE__
18 .import __ROM0_START__, __ROM0_SIZE__
19 .import __STARTUP_LOAD__,__STARTUP_RUN__, __STARTUP_SIZE__
20 .import __CODE_LOAD__,__CODE_RUN__, __CODE_SIZE__
21 .import __RODATA_LOAD__,__RODATA_RUN__, __RODATA_SIZE__
22 .import __DATA_LOAD__,__DATA_RUN__, __DATA_SIZE__
24 .include "zeropage.inc"
28 ; ------------------------------------------------------------------------
29 ; 16 bytes INES header
33 ; +--------+------+------------------------------------------+
34 ; | Offset | Size | Content(s) |
35 ; +--------+------+------------------------------------------+
38 ; | 4 | 1 | 16K PRG-ROM page count |
39 ; | 5 | 1 | 8K CHR-ROM page count |
40 ; | 6 | 1 | ROM Control Byte #1 |
42 ; | | | | ||||+- 0=Horizontal mirroring |
43 ; | | | | |||| 1=Vertical mirroring |
44 ; | | | | |||+-- 1=SRAM enabled |
45 ; | | | | ||+--- 1=512-byte trainer present |
46 ; | | | | |+---- 1=Four-screen mirroring |
48 ; | | | +--+----- Mapper # (lower 4-bits) |
49 ; | 7 | 1 | ROM Control Byte #2 |
52 ; | | | +--+----- Mapper # (upper 4-bits) |
54 ; | 16-.. | | Actual 16K PRG-ROM pages (in linear |
55 ; | ... | | order). If a trainer exists, it precedes |
56 ; | ... | | the first PRG-ROM page. |
57 ; | ..-EOF | | CHR-ROM pages (in ascending order). |
58 ; +--------+------+------------------------------------------+
60 .byte $4e,$45,$53,$1a ; "nes\n"
61 .byte 2 ; ines prg - Specifies the number of 16k prg banks.
62 .byte 1 ; ines chr - Specifies the number of 8k chr banks.
63 .byte %00000011 ; ines mir - Specifies VRAM mirroring of the banks.
64 .byte %00000000 ; ines map - Specifies the NES mapper used.
65 .byte 0,0,0,0,0,0,0,0 ; 8 zeroes
68 ; ------------------------------------------------------------------------
69 ; Create an empty LOWCODE segment to avoid linker warnings
73 ; ------------------------------------------------------------------------
74 ; Place the startup code in a special segment.
80 ; setup the CPU and System-IRQ
104 ; Copy the .data segment to RAM
106 lda #<(__ROM0_START__ + __STARTUP_SIZE__+ __CODE_SIZE__+ __RODATA_SIZE__)
108 lda #>(__ROM0_START__ + __STARTUP_SIZE__+ __CODE_SIZE__+ __RODATA_SIZE__)
115 ldx #>(__DATA_SIZE__)
117 @l2: beq @s1 ; no more full pages
131 ; copy remaining bytes
139 cpy #<(__DATA_SIZE__)
144 lda #<(__SRAM_START__ + __SRAM_SIZE__)
146 lda #>(__SRAM_START__ + __SRAM_SIZE__)
147 sta sp+1 ; Set argument stack ptr
149 ; Call module constructors
153 ; Push arguments and call main()
157 ; Call module destructors. This is also the _exit entry.
159 _exit: jsr donelib ; Run module destructors
165 ; ------------------------------------------------------------------------
166 ; System V-Blank Interupt
167 ; updates PPU Memory (buffered)
168 ; updates VBLANK_FLAG and _tickcount
169 ; ------------------------------------------------------------------------
186 ; reset the video counter
210 ; ------------------------------------------------------------------------
212 ; ------------------------------------------------------------------------
218 .word timerirq ; $fff8 ?
219 .word nmi ; $fffa vblank nmi
220 .word start ; $fffc reset
221 .word irq ; $fffe irq / brk
223 ; ------------------------------------------------------------------------
225 ; ------------------------------------------------------------------------
229 .incbin "nes/neschar.bin"