]> git.sur5r.net Git - cc65/blob - libsrc/nes/crt0.s
Moved more files with cleanup
[cc65] / libsrc / nes / crt0.s
1 ;
2 ; Startup 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 ; This must be the *first* file on the linker command line
8 ;
9
10         .export         _exit
11         .import         initlib, donelib
12         .import         push0, _main, zerobss
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         .import         __DATA_LOAD__,__DATA_RUN__, __DATA_SIZE__
23
24         .include        "zeropage.inc"
25         .include        "nes.inc"
26
27
28 ; ------------------------------------------------------------------------
29 ; 16 bytes INES header
30
31 .segment        "HEADER"
32
33 ;    +--------+------+------------------------------------------+
34 ;    | Offset | Size | Content(s)                               |
35 ;    +--------+------+------------------------------------------+
36 ;    |   0    |  3   | 'NES'                                    |
37 ;    |   3    |  1   | $1A                                      |
38 ;    |   4    |  1   | 16K PRG-ROM page count                   |
39 ;    |   5    |  1   | 8K CHR-ROM page count                    |
40 ;    |   6    |  1   | ROM Control Byte #1                      |
41 ;    |        |      |   %####vTsM                              |
42 ;    |        |      |    |  ||||+- 0=Horizontal mirroring      |
43 ;    |        |      |    |  ||||   1=Vertical mirroring        |
44 ;    |        |      |    |  |||+-- 1=SRAM enabled              |
45 ;    |        |      |    |  ||+--- 1=512-byte trainer present  |
46 ;    |        |      |    |  |+---- 1=Four-screen mirroring     |
47 ;    |        |      |    |  |                                  |
48 ;    |        |      |    +--+----- Mapper # (lower 4-bits)     |
49 ;    |   7    |  1   | ROM Control Byte #2                      |
50 ;    |        |      |   %####0000                              |
51 ;    |        |      |    |  |                                  |
52 ;    |        |      |    +--+----- Mapper # (upper 4-bits)     |
53 ;    |  8-15  |  8   | $00                                      |
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 ;    +--------+------+------------------------------------------+
59
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
66
67
68 ; ------------------------------------------------------------------------
69 ; Create an empty LOWCODE segment to avoid linker warnings
70
71 .segment        "LOWCODE"
72
73 ; ------------------------------------------------------------------------
74 ; Place the startup code in a special segment.
75
76 .segment        "STARTUP"
77
78 start:
79
80 ; setup the CPU and System-IRQ
81
82         sei
83         cld
84         ldx     #0
85         stx     VBLANK_FLAG
86
87         stx     ringread
88         stx     ringwrite
89         stx     ringcount
90
91         txs
92
93         lda     #$20
94 @l:     sta     ringbuff,x
95         sta     ringbuff+$0100,x
96         sta     ringbuff+$0200,x
97         inx
98         bne     @l
99
100 ; Clear the BSS data
101
102         jsr     zerobss
103
104 ; Copy the .data segment to RAM
105
106         lda     #<(__ROM0_START__ + __STARTUP_SIZE__+ __CODE_SIZE__+ __RODATA_SIZE__)
107         sta     ptr1
108         lda     #>(__ROM0_START__ + __STARTUP_SIZE__+ __CODE_SIZE__+ __RODATA_SIZE__)
109         sta     ptr1+1
110         lda     #<(__DATA_RUN__)
111         sta     ptr2
112         lda     #>(__DATA_RUN__)
113         sta     ptr2+1
114
115         ldx     #>(__DATA_SIZE__)
116
117 @l2:    beq     @s1             ; no more full pages
118
119         ; copy one page
120         ldy     #0
121 @l1:    lda     (ptr1),y
122         sta     (ptr2),y
123         iny
124         bne     @l1
125
126         inc     ptr1+1
127         inc     ptr2+1
128         dex
129         bne     @l2
130
131         ; copy remaining bytes
132 @s1:
133
134         ; copy one page
135         ldy     #0
136 @l3:    lda     (ptr1),y
137         sta     (ptr2),y
138         iny
139         cpy     #<(__DATA_SIZE__)
140         bne     @l3
141
142 ; setup the stack
143
144         lda     #<(__SRAM_START__ + __SRAM_SIZE__)
145         sta     sp
146         lda     #>(__SRAM_START__ + __SRAM_SIZE__)
147         sta     sp+1            ; Set argument stack ptr
148
149 ; Call module constructors
150
151         jsr     initlib
152
153 ; Push arguments and call main()
154
155         jsr     callmain
156
157 ; Call module destructors. This is also the _exit entry.
158
159 _exit:  jsr     donelib         ; Run module destructors
160
161 ; Reset the NES
162
163         jmp start
164
165 ; ------------------------------------------------------------------------
166 ; System V-Blank Interupt
167 ; updates PPU Memory (buffered)
168 ; updates VBLANK_FLAG and tickcount
169 ; ------------------------------------------------------------------------
170
171 nmi:    pha
172         tya
173         pha
174         txa
175         pha
176
177         lda     #1
178         sta     VBLANK_FLAG
179
180         inc     tickcount
181         bne     @s
182         inc     tickcount+1
183
184 @s:     jsr     ppubuf_flush
185
186         ; reset the video counter
187         lda     #$20
188         sta     PPU_VRAM_ADDR2
189         lda     #$00
190         sta     PPU_VRAM_ADDR2
191
192         ; reset scrolling
193         sta     PPU_VRAM_ADDR1
194         sta     PPU_VRAM_ADDR1
195
196         pla
197         tax
198         pla
199         tay
200         pla
201
202 ; Interrupt exit
203
204 irq2:
205 irq1:
206 timerirq:
207 irq:
208         rti
209
210 ; ------------------------------------------------------------------------
211 ; hardware vectors
212 ; ------------------------------------------------------------------------
213
214 .segment "VECTORS"
215
216         .word   irq2        ; $fff4 ?
217         .word   irq1        ; $fff6 ?
218         .word   timerirq    ; $fff8 ?
219         .word   nmi         ; $fffa vblank nmi
220         .word   start       ; $fffc reset
221         .word   irq         ; $fffe irq / brk
222
223 ; ------------------------------------------------------------------------
224 ; character data
225 ; ------------------------------------------------------------------------
226
227 .segment "CHARS"
228
229         .incbin "nes/neschar.bin"
230
231