1;
2; Start-up code for cc65 (NES version)
3;
4; by Groepaz/Hitmen <groepaz@gmx.net>
5; based on code by Ullrich von Bassewitz <uz@cc65.org>
6;
7
8        .export         _exit
9        .export         __STARTUP__ : absolute = 1      ; Mark as startup
10
11        .import         initlib, donelib, callmain
12        .import         push0, _main, zerobss, copydata
13        .import         ppubuf_flush
14
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
23; ------------------------------------------------------------------------
24; Character data
25; ------------------------------------------------------------------------
26        .forceimport    NESfont
27
28        .include        "zeropage.inc"
29        .include        "nes.inc"
30
31
32; ------------------------------------------------------------------------
33; 16-byte INES header
34
35.segment        "HEADER"
36
37;    +--------+------+------------------------------------------+
38;    | Offset | Size | Content(s)                               |
39;    +--------+------+------------------------------------------+
40;    |   0    |  3   | 'NES'                                    |
41;    |   3    |  1   | $1A                                      |
42;    |   4    |  1   | 16K PRG-ROM page count                   |
43;    |   5    |  1   | 8K CHR-ROM page count                    |
44;    |   6    |  1   | ROM Control Byte #1                      |
45;    |        |      |   %####vTsM                              |
46;    |        |      |    |  ||||+- 0=Horizontal mirroring      |
47;    |        |      |    |  ||||   1=Vertical mirroring        |
48;    |        |      |    |  |||+-- 1=SRAM enabled              |
49;    |        |      |    |  ||+--- 1=512-byte trainer present  |
50;    |        |      |    |  |+---- 1=Four-screen mirroring     |
51;    |        |      |    |  |                                  |
52;    |        |      |    +--+----- Mapper # (lower 4-bits)     |
53;    |   7    |  1   | ROM Control Byte #2                      |
54;    |        |      |   %####0000                              |
55;    |        |      |    |  |                                  |
56;    |        |      |    +--+----- Mapper # (upper 4-bits)     |
57;    |  8-15  |  8   | $00                                      |
58;    | 16-..  |      | Actual 16K PRG-ROM pages (in linear      |
59;    |  ...   |      | order). If a trainer exists, it precedes |
60;    |  ...   |      | the first PRG-ROM page.                  |
61;    | ..-EOF |      | CHR-ROM pages (in ascending order).      |
62;    +--------+------+------------------------------------------+
63
64        .byte   $4e,$45,$53,$1a ; "NES"^Z
65        .byte   2               ; ines prg  - Specifies the number of 16k prg banks.
66        .byte   1               ; ines chr  - Specifies the number of 8k chr banks.
67        .byte   %00000011       ; ines mir  - Specifies VRAM mirroring of the banks.
68        .byte   %00000000       ; ines map  - Specifies the NES mapper used.
69        .byte   0,0,0,0,0,0,0,0 ; 8 zeroes
70
71
72; ------------------------------------------------------------------------
73; Place the startup code in a special segment.
74
75.segment        "STARTUP"
76
77start:
78
79; Set up the CPU and System-IRQ.
80
81        sei
82        cld
83        ldx     #0
84        stx     VBLANK_FLAG
85
86        stx     ringread
87        stx     ringwrite
88        stx     ringcount
89
90        txs
91
92        lda     #$20
93@l:     sta     ringbuff,x
94        sta     ringbuff+$0100,x
95        sta     ringbuff+$0200,x
96        inx
97        bne     @l
98
99; Clear the BSS data.
100
101        jsr     zerobss
102
103; Initialize the data.
104        jsr     copydata
105
106; Set up the stack.
107
108        lda     #<(__SRAM_START__ + __SRAM_SIZE__)
109        ldx     #>(__SRAM_START__ + __SRAM_SIZE__)
110        sta     sp
111        stx     sp+1            ; Set argument stack ptr
112
113; Call the module constructors.
114
115        jsr     initlib
116
117; Push the command-line arguments; and, call main().
118
119        jsr     callmain
120
121; Call the module destructors. This is also the exit() entry.
122
123_exit:  jsr     donelib         ; Run module destructors
124
125; Reset the NES.
126
127        jmp start
128
129; ------------------------------------------------------------------------
130; System V-Blank Interrupt
131; Updates PPU Memory (buffered).
132; Updates VBLANK_FLAG and tickcount.
133; ------------------------------------------------------------------------
134
135nmi:    pha
136        tya
137        pha
138        txa
139        pha
140
141        lda     #1
142        sta     VBLANK_FLAG
143
144        inc     tickcount
145        bne     @s
146        inc     tickcount+1
147
148@s:     jsr     ppubuf_flush
149
150        ; Reset the video counter.
151        lda     #$20
152        sta     PPU_VRAM_ADDR2
153        lda     #$00
154        sta     PPU_VRAM_ADDR2
155
156        ; Reset scrolling.
157        sta     PPU_VRAM_ADDR1
158        sta     PPU_VRAM_ADDR1
159
160        pla
161        tax
162        pla
163        tay
164        pla
165
166; Interrupt exit
167
168irq:
169        rti
170
171
172; ------------------------------------------------------------------------
173; Hardware vectors
174; ------------------------------------------------------------------------
175
176.segment "VECTORS"
177
178        .word   nmi         ; $fffa vblank nmi
179        .word   start       ; $fffc reset
180        .word   irq         ; $fffe irq / brk
181