1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-25 17:29:50 +00:00
cc65/libsrc/nes/crt0.s
uz 8216bf1d6a Force an import of the special symbol __STARTUP__ in the C compiler when
main() is encountered. Define this symbol in the startup code. This will
automatically force linking of the startup code which can then reside inside
the standard library as any other object file.


git-svn-id: svn://svn.cc65.org/cc65/trunk@3988 b7a2c559-68d2-44c3-8de9-860c34a00d81
2009-07-31 12:05:42 +00:00

190 lines
5.3 KiB
ArmAsm

;
; Startup code for cc65 (NES version)
;
; by Groepaz/Hitmen <groepaz@gmx.net>
; based on code by Ullrich von Bassewitz <uz@cc65.org>
;
.export _exit
.export __STARTUP__ : absolute = 1 ; Mark as startup
.import initlib, donelib, callmain
.import push0, _main, zerobss, copydata
.import ppubuf_flush
; Linker generated symbols
.import __RAM_START__, __RAM_SIZE__
.import __SRAM_START__, __SRAM_SIZE__
.import __ROM0_START__, __ROM0_SIZE__
.import __STARTUP_LOAD__,__STARTUP_RUN__, __STARTUP_SIZE__
.import __CODE_LOAD__,__CODE_RUN__, __CODE_SIZE__
.import __RODATA_LOAD__,__RODATA_RUN__, __RODATA_SIZE__
.include "zeropage.inc"
.include "nes.inc"
; ------------------------------------------------------------------------
; 16 bytes INES header
.segment "HEADER"
; +--------+------+------------------------------------------+
; | Offset | Size | Content(s) |
; +--------+------+------------------------------------------+
; | 0 | 3 | 'NES' |
; | 3 | 1 | $1A |
; | 4 | 1 | 16K PRG-ROM page count |
; | 5 | 1 | 8K CHR-ROM page count |
; | 6 | 1 | ROM Control Byte #1 |
; | | | %####vTsM |
; | | | | ||||+- 0=Horizontal mirroring |
; | | | | |||| 1=Vertical mirroring |
; | | | | |||+-- 1=SRAM enabled |
; | | | | ||+--- 1=512-byte trainer present |
; | | | | |+---- 1=Four-screen mirroring |
; | | | | | |
; | | | +--+----- Mapper # (lower 4-bits) |
; | 7 | 1 | ROM Control Byte #2 |
; | | | %####0000 |
; | | | | | |
; | | | +--+----- Mapper # (upper 4-bits) |
; | 8-15 | 8 | $00 |
; | 16-.. | | Actual 16K PRG-ROM pages (in linear |
; | ... | | order). If a trainer exists, it precedes |
; | ... | | the first PRG-ROM page. |
; | ..-EOF | | CHR-ROM pages (in ascending order). |
; +--------+------+------------------------------------------+
.byte $4e,$45,$53,$1a ; "NES"^Z
.byte 2 ; ines prg - Specifies the number of 16k prg banks.
.byte 1 ; ines chr - Specifies the number of 8k chr banks.
.byte %00000011 ; ines mir - Specifies VRAM mirroring of the banks.
.byte %00000000 ; ines map - Specifies the NES mapper used.
.byte 0,0,0,0,0,0,0,0 ; 8 zeroes
; ------------------------------------------------------------------------
; Place the startup code in a special segment.
.segment "STARTUP"
start:
; setup the CPU and System-IRQ
sei
cld
ldx #0
stx VBLANK_FLAG
stx ringread
stx ringwrite
stx ringcount
txs
lda #$20
@l: sta ringbuff,x
sta ringbuff+$0100,x
sta ringbuff+$0200,x
inx
bne @l
; Clear the BSS data
jsr zerobss
; initialize data
jsr copydata
; setup the stack
lda #<(__SRAM_START__ + __SRAM_SIZE__)
sta sp
lda #>(__SRAM_START__ + __SRAM_SIZE__)
sta sp+1 ; Set argument stack ptr
; Call module constructors
jsr initlib
; Push arguments and call main()
jsr callmain
; Call module destructors. This is also the _exit entry.
_exit: jsr donelib ; Run module destructors
; Reset the NES
jmp start
; ------------------------------------------------------------------------
; System V-Blank Interupt
; updates PPU Memory (buffered)
; updates VBLANK_FLAG and tickcount
; ------------------------------------------------------------------------
nmi: pha
tya
pha
txa
pha
lda #1
sta VBLANK_FLAG
inc tickcount
bne @s
inc tickcount+1
@s: jsr ppubuf_flush
; reset the video counter
lda #$20
sta PPU_VRAM_ADDR2
lda #$00
sta PPU_VRAM_ADDR2
; reset scrolling
sta PPU_VRAM_ADDR1
sta PPU_VRAM_ADDR1
pla
tax
pla
tay
pla
; Interrupt exit
irq2:
irq1:
timerirq:
irq:
rti
; ------------------------------------------------------------------------
; hardware vectors
; ------------------------------------------------------------------------
.segment "VECTORS"
.word irq2 ; $fff4 ?
.word irq1 ; $fff6 ?
.word timerirq ; $fff8 ?
.word nmi ; $fffa vblank nmi
.word start ; $fffc reset
.word irq ; $fffe irq / brk
; ------------------------------------------------------------------------
; character data
; ------------------------------------------------------------------------
.segment "CHARS"
.include "neschar.inc"