cc65/libsrc/nes/crt0.s

181 lines
5.4 KiB
ArmAsm

;
; Start-up 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__
; ------------------------------------------------------------------------
; Character data
; ------------------------------------------------------------------------
.forceimport NESfont
.include "zeropage.inc"
.include "nes.inc"
; ------------------------------------------------------------------------
; 16-byte 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:
; Set up 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 the data.
jsr copydata
; Set up the stack.
lda #<(__SRAM_START__ + __SRAM_SIZE__)
ldx #>(__SRAM_START__ + __SRAM_SIZE__)
sta sp
stx sp+1 ; Set argument stack ptr
; Call the module constructors.
jsr initlib
; Push the command-line arguments; and, call main().
jsr callmain
; Call the module destructors. This is also the exit() entry.
_exit: jsr donelib ; Run module destructors
; Reset the NES.
jmp start
; ------------------------------------------------------------------------
; System V-Blank Interrupt
; 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
irq:
rti
; ------------------------------------------------------------------------
; Hardware vectors
; ------------------------------------------------------------------------
.segment "VECTORS"
.word nmi ; $fffa vblank nmi
.word start ; $fffc reset
.word irq ; $fffe irq / brk