]> git.sur5r.net Git - cc65/blob - libsrc/nes/crt0.s
New module eeprom.s
[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, callmain
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 ; Place the startup code in a special segment.
70
71 .segment        "STARTUP"
72
73 start:
74
75 ; setup the CPU and System-IRQ
76
77         sei
78         cld
79         ldx     #0
80         stx     VBLANK_FLAG
81
82         stx     ringread
83         stx     ringwrite
84         stx     ringcount
85
86         txs
87
88         lda     #$20
89 @l:     sta     ringbuff,x
90         sta     ringbuff+$0100,x
91         sta     ringbuff+$0200,x
92         inx
93         bne     @l
94
95 ; Clear the BSS data
96
97         jsr     zerobss
98
99 ; Copy the .data segment to RAM
100
101         lda     #<(__ROM0_START__ + __STARTUP_SIZE__+ __CODE_SIZE__+ __RODATA_SIZE__)
102         sta     ptr1
103         lda     #>(__ROM0_START__ + __STARTUP_SIZE__+ __CODE_SIZE__+ __RODATA_SIZE__)
104         sta     ptr1+1
105         lda     #<(__DATA_RUN__)
106         sta     ptr2
107         lda     #>(__DATA_RUN__)
108         sta     ptr2+1
109
110         ldx     #>(__DATA_SIZE__)
111
112 @l2:    beq     @s1             ; no more full pages
113
114         ; copy one page
115         ldy     #0
116 @l1:    lda     (ptr1),y
117         sta     (ptr2),y
118         iny
119         bne     @l1
120
121         inc     ptr1+1
122         inc     ptr2+1
123         dex
124         bne     @l2
125
126         ; copy remaining bytes
127 @s1:
128
129         ; copy one page
130         ldy     #0
131 @l3:    lda     (ptr1),y
132         sta     (ptr2),y
133         iny
134         cpy     #<(__DATA_SIZE__)
135         bne     @l3
136
137 ; setup the stack
138
139         lda     #<(__SRAM_START__ + __SRAM_SIZE__)
140         sta     sp
141         lda     #>(__SRAM_START__ + __SRAM_SIZE__)
142         sta     sp+1            ; Set argument stack ptr
143
144 ; Call module constructors
145
146         jsr     initlib
147
148 ; Push arguments and call main()
149
150         jsr     callmain
151
152 ; Call module destructors. This is also the _exit entry.
153
154 _exit:  jsr     donelib         ; Run module destructors
155
156 ; Reset the NES
157
158         jmp start
159
160 ; ------------------------------------------------------------------------
161 ; System V-Blank Interupt
162 ; updates PPU Memory (buffered)
163 ; updates VBLANK_FLAG and tickcount
164 ; ------------------------------------------------------------------------
165
166 nmi:    pha
167         tya
168         pha
169         txa
170         pha
171
172         lda     #1
173         sta     VBLANK_FLAG
174
175         inc     tickcount
176         bne     @s
177         inc     tickcount+1
178
179 @s:     jsr     ppubuf_flush
180
181         ; reset the video counter
182         lda     #$20
183         sta     PPU_VRAM_ADDR2
184         lda     #$00
185         sta     PPU_VRAM_ADDR2
186
187         ; reset scrolling
188         sta     PPU_VRAM_ADDR1
189         sta     PPU_VRAM_ADDR1
190
191         pla
192         tax
193         pla
194         tay
195         pla
196
197 ; Interrupt exit
198
199 irq2:
200 irq1:
201 timerirq:
202 irq:
203         rti
204
205 ; ------------------------------------------------------------------------
206 ; hardware vectors
207 ; ------------------------------------------------------------------------
208
209 .segment "VECTORS"
210
211         .word   irq2        ; $fff4 ?
212         .word   irq1        ; $fff6 ?
213         .word   timerirq    ; $fff8 ?
214         .word   nmi         ; $fffa vblank nmi
215         .word   start       ; $fffc reset
216         .word   irq         ; $fffe irq / brk
217
218 ; ------------------------------------------------------------------------
219 ; character data
220 ; ------------------------------------------------------------------------
221
222 .segment "CHARS"
223
224         .include        "neschar.inc"
225
226