arch z80
include "msx.oc"
include "msx/romram.oc"
optimize flow
msx:link-as-rom main _
module device {
section bss ={
align 256
data sprite-attributes = [32][4]byte
}
proc init() {
msx:set-vdp-mode 0b0000_0000 0b0110_0010
msx:set-vdp-register 7 0xf1
init-background()
init-sprite()
msx:update-hook msx:H_TIMI timi
return
}
proc timi() {
push/pop AF {
// sync sprite attributes
msx:set-vdp-write-addr msx:T32ATR/INI
msx:write-vdp-data sprite-attributes sizeof(sprite-attributes)
}
return
}
proc init-background() {
msx:set-vdp-write-addr msx:T32COL/INI
msx:fill-vdp-data 0xf0 32
msx:set-vdp-write-addr msx:T32NAM/INI
msx:fill-vdp-data/wide ' ' (256 * 3)
return
}
proc init-sprite() {
msx:set-vdp-write-addr msx:T32PAT/INI
msx:write-vdp-data assets:pat sizeof(assets:pat)
return
}
proc rand(=> A) {
A <- R
return
}
}
struct unit {
y byte
x byte
pat byte
color byte
_unused byte
count byte
next word
}
module main {
data current = word @ <reserved>
section bss ={
align 256
data units = [32]unit
}
proc main() {
romram:boot
device:init()
DE <- units
BC <- asword(32 2)
loop {
push/pop BC {
@C -> [(template + unit.color)]
HL@template . BC@sizeof(template) . {LDIR}
data template = unit { 64 128 0 0 0 0 action:move/random } : rodata
}
C ++ -bit? 4; if not-zero? {
C <- 2
}
} while/B-
fallthrough
}
proc main/loop() {
msx:wait-vsync
HL <- units; *patch* current word
L <- 0
loop {
@L -> [current]
IX <- [current]
DE<-*HL; L -set 2 // y, x, ...
[HL] -- // count
C <- [HL]; L ++
HL<-*HL
call/HL()
HL <- [current]
DE->*HL; L ++; L -set 2 // y, x, ...
BC->*HL; L ++ // next
} while not-zero?
update-sprite-attributes(!)
recur
}
proc call/HL() { goto/HL }
proc update-sprite-attributes(!) {
data switch = byte @ <reserved>
data next = word @ <reserved>
DE <- device:sprite-attributes
HL <- units; *patch* next word
A <- opcode("CP 0")
BC <- asword(32 (sizeof(unit) * 7 - 4))
*patch* switch; once {
JR _END
A <- opcode("JR 0")
C <- (sizeof(unit) * 11 - 4)
}
A -> [switch]
loop {
push/pop BC { memcpy _ _ 4 }
@L + C -> L
} while/B-
A - C - 4 -> [next]
return
}
}
module action {
macro suspend=>() {
suspend()
}
proc suspend() {
BC -pop; return
}
proc set-state(A) {
A -> [IX unit.pat]
A . device:rand(=> A) & 0b1111 + 17 -> [IX unit.count]
return
}
proc move/random() {
A . device:rand(=> A) & 0b111 <* 1
HL <- tab . {HL+A}
HL<-*HL
goto/HL
data tab = word [
move/0
move/1
move/2
move/3
move/4
move/5
move/6
move/7
]
}
proc move/0() {
A - A . set-state(A)
never-return loop {
E -- -reset 7
suspend=>
C -zero?; goto-if zero? move/random
}
}
proc move/1() {
@8 . set-state(A)
never-return loop {
D ++
E -- -reset 7
suspend=>
C -zero?; goto-if zero? move/random
}
}
proc move/2() {
@8 . set-state(A)
never-return loop {
D ++
suspend=>
C -zero?; goto-if zero? move/random
}
}
proc move/3() {
@8 . set-state(A)
never-return loop {
D ++
E ++ -reset 7
suspend=>
C -zero?; goto-if zero? move/random
}
}
proc move/4() {
A - A . set-state(A)
never-return loop {
E ++ -reset 7
suspend=>
C -zero?; goto-if zero? move/random
}
}
proc move/5() {
@4 . set-state(A)
never-return loop {
D --
E ++ -reset 7
suspend=>
C -zero?; goto-if zero? move/random
}
}
proc move/6() {
@4 . set-state(A)
never-return loop {
D --
suspend=>
C -zero?; goto-if zero? move/random
}
}
proc move/7() {
@4 . set-state(A)
never-return loop {
D --
E -- -reset 7
suspend=>
C -zero?; goto-if zero? move/random
}
}
}
module assets {
data pat = byte [
0x01 0x01 0x03 0x03 0x06 0x06 0x0c 0x0c 0x08 0x18 0x18 0x30 0x30 0x7f 0x7f 0x00
0x80 0x80 0xc0 0xc0 0x60 0x60 0x30 0x30 0x10 0x18 0x18 0x0c 0x0c 0xfe 0xfe 0x00
0x01 0x01 0x03 0x02 0x06 0x04 0x04 0x0c 0x08 0x18 0x18 0x10 0x30 0x27 0x7f 0x78
0x80 0x80 0xc0 0x40 0x60 0x20 0x30 0x10 0x18 0x08 0x0c 0x04 0x1e 0xfe 0xe0 0x00
0x01 0x01 0x03 0x02 0x06 0x04 0x0c 0x08 0x18 0x10 0x30 0x20 0x78 0x7f 0x07 0x00
0x80 0x80 0xc0 0x40 0x60 0x20 0x20 0x30 0x10 0x18 0x18 0x08 0x0c 0xe4 0xfe 0x1e
] : rodata
}