Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Simplified MSXlib cartridge header, entry point and initialization
; =============================================================================
; MSX cartridge (ROM) header, entry point and initialization
; =============================================================================
IF (CFG_INIT_ROM_SIZE < 32)
org $4000, $4000 + (CFG_INIT_ROM_SIZE * $0400) - 1
ELSE
org $4000, $bfff
ENDIF ; IF (CFG_INIT_ROM_SIZE < 32)
; -----------------------------------------------------------------------------
; Cartridge header
CARTRIDGE_HEADER:
db "AB" ; ROM Catridge ID ("AB")
dw CARTRIDGE_INIT ; INIT
dw $0000 ; STATEMENT
dw $0000 ; DEVICE
dw $0000 ; TEXT
ds $4010 - $, $00 ; Reserved
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; Cartridge entry point
; System initialization: stack pointer, slots, RAM, CPU, VDP, PSG, etc.
CARTRIDGE_INIT:
; Ensures interrupt mode
di
im 1
; Initializes stack pointer
ld sp, $f380 ; (as suggested by the MSX2 Technical Handbook)
; Cancels the existing hooks (several BIOS routines re-enable interruptions)
ld a, $c9 ; opcode for "RET"
ld [HKEYI], a
ld [HTIMI], a
; CPU: Ensures Z80 mode
ld a, [MSXID3]
cp 3 ; 3 = MSX turbo R
jr nz, .CPU_OK
; MSX turbo R: switches to Z80 mode
ld a, $80 ; also disables the LED
call CHGCPU
.CPU_OK:
IF CFG_INIT_ROM_SIZE > 16
IF CFG_INIT_ROM_SIZE <= 32
; Is the game running on RAM? (e.g.: ROM Loader)
ld a, $18 ; opcode for "JR nn"
ld [.JR_NC], a ; Replaces "JR NC,nn" by "JR nn" (if RAM)
scf
.JR_NC:
jr nc, .ROM_OK ; yes
; No:
ENDIF ; IF CFG_INIT_ROM_SIZE <= 32
; Reads the primary slot of the page 1
call RSLREG ; a = 33221100
rrca
rrca
and $03 ; a = xxxxxxPP
ld c, a ; c = xxxxxxPP
; Reads the expanded slot flag
ld hl, EXPTBL ; EXPTBL + a => EXPTBL for slot of page 1
add a, l
ld l, a
ld a, [hl]
and $80 ; a = Exxxxxxx
; Defines slot ID (1/2)
or c ; a = ExxxxxPP
ld c, a ; c = ExxxxxPP
; Reads the secondary slot selection register
inc l ; hl += 4 => = SLTTBL for slot of page 1
inc l
inc l
inc l
ld a, [hl]
and $0c ; a = xxxxSSxx
; Define slot ID (2/2)
or c ; a = ExxxSSPP
IF CFG_INIT_ROM_SIZE > 32
; Saves the slot of the cartridge
push af ; (Reserves a byte at the bottom of the stack
inc sp ; to avoid accidental overwriting)
ENDIF
; Enables page 2 cartridge slot/subslot at start
ld h, $80 ; Bit 6 and 7: page 2 ($8000)
call ENASLT
.ROM_OK:
ENDIF ; IF CFG_INIT_ROM_SIZE > 16
IFDEF CFG_INIT_16KB_RAM
; RAM: checks availability of 16kB
ld hl, ram_start
ld de, [BOTTOM]
call DCOMPR
jr nc, .RAM_OK ; yes (BOTTOM is less or equal than ram_start)
; no: screen 1 and warning text
call INIT32
ld hl, .TXT
ld de, NAMTBL + (SCR_WIDTH-.TXT_SIZE)/2 + 11*SCR_WIDTH
ld bc, 17
call LDIRVM
; halts the execution
di
halt
; RAM check warning text
.TXT:
db "16KB RAM REQUIRED"
.TXT_SIZE: equ $ - .TXT
.RAM_OK:
ENDIF ; CFG_INIT_16KB_RAM
xor a
; screen ,,0
ld [CLIKSW], a
; VDP: color 15,0,0
ld [BAKCLR], a
ld [BDRCLR], a
dec a
ld [FORCLR], a
; screen 2
call INIGRP
; screen ,2
call DISSCR
ld hl, RG1SAV
set 1, [hl] ; (first call to ENASCR will actually apply to the VDP)
; Zeroes all the used RAM
ld hl, ram_start
ld de, ram_start +1
ld bc, ram_end - ram_start -1
ld [hl], l ; l = $00
ldir
; PSG: silence
call GICINI
; Initializes the replayer
; call REPLAYER.RESET ; (if REPLAYER.RESET exists)
; Frame rate related variables
ld a, [MSXID1]
bit 7, a ; 0=60Hz, 1=50Hz
ld hl, 5 << 8 + 50 ; frame rate and frames per tenth for 50Hz
jr nz, .HL_OK
ld hl, 6 << 8 + 60 ; frame rate and frames per tenth for 60Hz
.HL_OK:
ld [frame_rate], hl
; Installs the H.TIMI hook in the interruption
di
ld a, $c3 ; opcode for "JP nn"
ld [HTIMI], a
ld hl, HOOK
ld [HTIMI +1], hl
ei
; Skips to the game entry point
jp INIT
; -----------------------------------------------------------------------------
IF CFG_INIT_ROM_SIZE > 32
; -----------------------------------------------------------------------------
; 48kB ROM: Declares routines to set the page 0 slot/subslot and restore the bios
SET_PAGE0:
; Restores the BIOS (selects and enables the Main ROM slot/subslot in page 0)
; Caller is responsible of disabling interruptions before invoking this routine
; touches: a, bc, d
.BIOS:
ld a, [MNROM]
jr .DO_SET_PAGE0
; Selects and enables the cartridge slot/sublot in page 0
; Caller is responsible of enabling interruptions after invoking this routine
; touches: a, bc, d
.CARTRIDGE:
; Retrieves the slot of the cartridge from the bottom of the stack
ld a, [$f380 - 1]
; jr .DO_SET_PAGE0 ; falls through
; Selects and permanently enables the requested slot in page 0
; param a: slot ID (ExxxSSPP)
; touches: a, bc, d
.DO_SET_PAGE0:
ld b, a ; b = ExxxSSPP
and $03 ; a = 000000PP
ld c, a ; c = 000000PP
; Computes the primary slot selection register
in a, [PPI.A] ; a = P3P2P1P0
and $fc ; a = P3P2P100
or c ; a = P3P2P1PP
; Is the slot expanded?
bit 7, b
jr z, .SET_PRIMARY ; no
; yes
ld d, a ; (preserves primary slot selection register value)
; Selects primary slot in page 3 first (for $FFFF to refer to that slot)
rrc c
rrc c ; c = PP000000
ld a, d ; a = P3P2P1PP
and $3f ; a = 00P2P1PP
or c ; a = PPP2P1PP
out [PPI.A], a
; Selects secondary slot in page 0
ld a, b ; a = 1xxxSSPP
and $0c ; a = 0000SS00
rrca
rrca ; a = 000000SS
ld b, a ; b = 000000SS
ld a, [$ffff]
cpl ; a = S3S2S1S0
and $fc ; a = S3S2S100
or b ; b = S3S2S1SS
ld [$ffff], a
; Selects primary slot in page 0
ld a, d ; (restores primary slot selection register value)
.SET_PRIMARY:
out [PPI.A], a
ret
; -----------------------------------------------------------------------------
ENDIF ; IF CFG_INIT_ROM_SIZE > 32
; EOF
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment