arch z80
include "msx.oc"
msx:link-as-rom main _
module device {
proc init(!) {
msx:set-vdp-mode 0b0000_0000 0b1110_0000
clear_namtab(!)
clear_spratr(!)
clear_chrtab(!)
HL@assets:chrdat . load_chrdat(HL => !)
msx:update-hook msx:H_TIMI timi
return
}
proc timi() {
push/pop AF {
A - A -> [msx:SCNCNT] -> [msx:INTCNT] // skip default key scan
device:read_keys(=> B ! C)
}
return
}
proc read_keys(=> B ! C) {
@5 . msx:snsmat(A => A) // Z Y X W - - - -
A >* 4 & 0x0F -> B
@8 . msx:snsmat(A => A) // RIGHT DOWN UP LEFT - - - -
A & 0xF0 | B -not -> B // RIGHT DOWN UP LEFT Z Y X W
@[key_states] ^ B -> [key_changes]
@B -> [key_states]
return
}
proc wait_key_x() {
never-return loop {
msx:wait
@[key_changes] -bit? 1; if !=? {
@[key_states] -bit? 1; return-if !=?
}
}
}
proc clear_namtab(!) {
msx:set-vdp-write-addr msx:T32NAM/INI
msx:fill-vdp-data/wide ' ' (256 * 3)
return
}
proc clear_spratr(!) {
msx:set-vdp-write-addr msx:T32ATR/INI
msx:fill-vdp-data 209 128
return
}
proc clear_chrtab(!) {
msx:set-vdp-write-addr msx:T32CGP/INI
A - A . { msx:fill-vdp-data/wide _ (256 * 24) }
return
}
proc load_chrdat(HL => !) {
msx:set-vdp-write-addr msx:T32CGP/INI
msx:write-vdp-data/wide _ (256 * 4)
return
}
proc load_namdat(HL => !) {
msx:set-vdp-write-addr msx:T32NAM/INI
msx:write-vdp-data/wide _ (256 * 3)
return
}
section bss
data key_changes = byte * 1
data key_states = byte * 1
}
module assets {
section rodata
align 256
chrdat: incbin "./chr.dat"
namdat: incbin "./nam.dat"
}
module main {
data sbuf = byte * 24 : bss
macro scene=>(addr) {
SP <- msx:STACK_ADDR
goto %=addr
}
proc main(!) {
SP <- msx:STACK_ADDR
device:init(!)
fallthrough
}
proc init_game_states(!) {
memset sbuf 0 24
HL@assets:namdat . device:load_namdat(HL => !)
fallthrough
}
proc main_game_loop(!) {
msx:wait-vsync
msx:write-vdp-data/rect sbuf msx:t32nam(12 16) 8 3 32
@[device:key_changes] -> E
@[device:key_states] -> D
@D -? 0b0010_1010; if ==? {
scene=> stop
}
B <- 8
loop {
C <- '-'
E >> 1; if carry? {
C <- '+'
}
C -> [HL@(sbuf + 8 - 1) . HL+B(=> HL)]
C <- '-'
D >> 1; if carry? {
data keys = byte [0x18, 0x19, 0x1a, 0x1b, 'Z', 'Y', 'X', 'W'] : rodata
C <- [HL@(keys - 1) . HL+B(=> HL)]
}
C -> [HL@(sbuf - 1) . HL+B(=> HL)]
} while/B-
HL@[msx:JIFFY] . DE@(sbuf + 18) . itoa16(HL DE => !)
recur
}
proc stop(!) {
data message = byte [
"********"
"* *"
"* STOP *"
"* *"
"********"
] : rodata
msx:wait-vsync
msx:write-vdp-data/rect message msx:t32nam(12 10) 8 5 32
device:wait_key_x()
scene=> init_game_states
}
proc HL+B(=> HL) {
@L + B -> L; return-if not-carry?
H ++
return
}
proc itoa16(HL DE => !) {
BC@-10000 . count(BC => HL DE)
BC@-1000 . count(BC => HL DE)
BC@-100 . count(BC => HL DE)
BC@-10 . count(BC => HL DE)
@L + '0' -> [DE]
return
proc count(BC => HL DE) {
A <- ('0' - 1)
loop {
A ++
HL + BC
} while carry?
HL -$ BC
A -> [DE]; DE ++
return
}
}
}