1
0
mirror of https://github.com/cc65/cc65.git synced 2024-11-19 21:32:19 +00:00
cc65/libsrc/nes/crt0.s
Marshall Ward 09495519c0 NES memory map amend (16k prg, 8k chr default)
The configuration file and runtime (crt0.s) provided for the default NES
ROM layout (2x16k PRG, 8k CHR) incorrectly added interrupts (IRQ1, IRQ2,
TIMERIRQ) which are not supported by the NES hardware.  For example, see
the NESdev wiki, which makes no reference to these interrupts.

    https://wiki.nesdev.com/w/index.php/CPU_memory_map

The VECTORS region was also incorrectly set to 0xFFF6, which would have
left the 0xFFF4 normally unspecified.  This did not result in any error,
however, since cc65 simply placed ROMV directly after ROM0 regardless of
start address.

(This layout may be due to a copy-and-paste from the PC-Engine
configuration, whose interrupt registers start at 0xFFF6, begins with
the three interrupts listed above, followed by NMI and START, and does
not end with a final IRQ interrupt.)

Despite the absence of any actual error, since START is still placed at
0xFFFC, this patch removes the nonexistent interrupts and also correctly
aligns the ROM0 and ROMV regions.  It also has the (admittedly very
minor) benefit of freeing up 6 additional bytes for ROM0.
2016-12-24 08:32:54 +11:00

184 lines
5.4 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:
; 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
; ------------------------------------------------------------------------
; character data
; ------------------------------------------------------------------------
.segment "CHARS"
.include "neschar.inc"