Session 1: hardware research, content measurement, codec decision, MAME harness
Verified GVRAM is one word-access per pixel in ALL color modes; chose 256-color 256x192 with movem.l bursts (page 1 sacrificed as double-buffer). Measured 8 scenes from the Blu-ray source: blit costs under 8% of the 12fps cycle budget, so I/O is the bottleneck, not CPU. Naive delta+RLE reaches only 3.2:1 (365 KB/s, 470MB) -> decision to use 4x4 vector quantization (~30 KB/s). "Shot on twos" assumption failed: the transfer has zero duplicate frames, so 12fps requires explicit decimation. Documents three false measurement results and their root causes (per-frame Floyd-Steinberg dithering, temporal denoise, exact-match dedupe on noisy source). MAME Lua injection harness works and is reusable for cycle-cost measurement; the IOCS _B_READ disk benchmark is blocked returning -1. Claude-Session: https://claude.ai/code/session_01194oWYW8DQXK1SZ2DnChW6
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
local function s(x) return tostring(x) end
|
||||
print("[API] add_machine_frame_notifier = "..s(emu.add_machine_frame_notifier))
|
||||
print("[API] add_machine_periodic_notifier = "..s(emu.add_machine_periodic_notifier))
|
||||
print("[API] add_machine_reset_notifier = "..s(emu.add_machine_reset_notifier))
|
||||
local m=manager.machine
|
||||
print("[API] time.seconds="..s(m.time.seconds).." atto="..s(m.time.attoseconds))
|
||||
print("[API] machine.exit="..s(m.exit))
|
||||
for k,v in pairs(emu) do if tostring(k):find("notif") then print("[API] emu."..s(k)) end end
|
||||
@@ -0,0 +1,53 @@
|
||||
M = manager.machine
|
||||
CPU = M.devices[":maincpu"]
|
||||
SP = CPU.spaces["program"]
|
||||
FLAG,STAT,NREAD,BUF = 0x18000,0x18004,0x18008,0x20000
|
||||
TOTAL = 16*65536
|
||||
local f=io.open("bench.bin","rb"); local d=f:read("a"); f:close()
|
||||
CODE={} ; for i=1,#d do CODE[i]=string.byte(d,i) end
|
||||
print("[BENCH] loaded bench.bin bytes="..#d)
|
||||
STATE,T0,NFIRE = "wait",nil,0
|
||||
local function T() local t=M.time return t.seconds + t.attoseconds/1e18 end
|
||||
local function P(s) print("[BENCH] "..s) end
|
||||
|
||||
local function tick()
|
||||
NFIRE = NFIRE + 1
|
||||
if NFIRE==1 then P("notifier firing OK") end
|
||||
local t=T()
|
||||
if STATE=="wait" then
|
||||
if t < 5.0 then return end
|
||||
for i=1,#CODE do SP:write_u8(0x10000+i-1, CODE[i]) end
|
||||
SP:write_u32(FLAG,0); SP:write_u32(STAT,0); SP:write_u32(NREAD,0); SP:write_u32(BUF,0)
|
||||
CPU.state["SR"].value=0x2000
|
||||
CPU.state["SP"].value=0x8000
|
||||
CPU.state["PC"].value=0x10000
|
||||
STATE="run"
|
||||
P(string.format("injected t=%.3f frames=%d",t,NFIRE))
|
||||
return
|
||||
end
|
||||
if STATE=="run" then
|
||||
local fl=SP:read_u32(FLAG)
|
||||
if fl==1 and not T0 then T0=t; P(string.format("started t=%.4f",t)) end
|
||||
if fl==0xFF then
|
||||
STATE="done"
|
||||
local dt=t-(T0 or t)
|
||||
P(string.format("DONE reads=%d status=%08X",SP:read_u32(NREAD),SP:read_u32(STAT)))
|
||||
P(string.format("elapsed=%.4f s bytes=%d",dt,TOTAL))
|
||||
if dt>0 then P(string.format("THROUGHPUT = %.1f KB/s",TOTAL/1024/dt)) end
|
||||
P(string.format("buf=%08X %08X",SP:read_u32(BUF),SP:read_u32(BUF+4)))
|
||||
M:exit()
|
||||
elseif fl==0xEE then
|
||||
STATE="done"; P(string.format("READ FAILED status=%08X reads=%d",SP:read_u32(STAT),SP:read_u32(NREAD))); M:exit()
|
||||
elseif t>25 then
|
||||
STATE="done"
|
||||
P(string.format("TIMEOUT flag=%08X status=%08X reads=%d PC=%08X SR=%04X",
|
||||
fl,SP:read_u32(STAT),SP:read_u32(NREAD),CPU.state["PC"].value,CPU.state["SR"].value))
|
||||
M:exit()
|
||||
end
|
||||
end
|
||||
end
|
||||
SUB = emu.add_machine_frame_notifier(function()
|
||||
local ok,err = pcall(tick)
|
||||
if not ok then print("[BENCH] LUA ERROR: "..tostring(err)); M:exit() end
|
||||
end)
|
||||
print("[BENCH] subscription="..tostring(SUB))
|
||||
@@ -0,0 +1,36 @@
|
||||
FLAG = $18000
|
||||
STAT = $18004
|
||||
NREAD = $18008
|
||||
BUF = $20000
|
||||
CHUNK = 65536 ; bytes per read
|
||||
RECS = CHUNK/256 ; 256-byte records per read
|
||||
NCHUNK = 16 ; 16 x 64KB = 1MB total
|
||||
|
||||
org $10000
|
||||
start:
|
||||
move.l #1,FLAG.l ; signal: started
|
||||
move.l #NCHUNK,d6
|
||||
moveq #0,d5 ; record position
|
||||
moveq #0,d4 ; completed count
|
||||
loop:
|
||||
movem.l d4-d6,-(sp)
|
||||
moveq #$46,d0 ; _B_READ
|
||||
move.l #$80000000,d1 ; PDA=$80 (SASI unit0), mode=0
|
||||
move.l d5,d2 ; position (records)
|
||||
move.l #CHUNK,d3 ; byte count
|
||||
lea BUF,a1
|
||||
trap #15
|
||||
movem.l (sp)+,d4-d6
|
||||
move.l d0,STAT.l ; last status
|
||||
tst.l d0
|
||||
bmi.s failed
|
||||
addq.l #1,d4
|
||||
move.l d4,NREAD.l
|
||||
add.l #RECS,d5
|
||||
subq.l #1,d6
|
||||
bne.s loop
|
||||
move.l #$FF,FLAG.l ; signal: done OK
|
||||
stop: bra.s stop
|
||||
failed:
|
||||
move.l #$EE,FLAG.l ; signal: error
|
||||
bra.s stop
|
||||
@@ -0,0 +1,24 @@
|
||||
M=manager.machine; CPU=M.devices[":maincpu"]; SP=CPU.spaces["program"]
|
||||
local f=io.open("one.bin","rb"); local d=f:read("a"); f:close()
|
||||
CODE={}; for i=1,#d do CODE[i]=string.byte(d,i) end
|
||||
STATE="wait"
|
||||
local function T() local t=M.time return t.seconds+t.attoseconds/1e18 end
|
||||
local function tick()
|
||||
local t=T()
|
||||
if STATE=="wait" then
|
||||
if t<5.0 then return end
|
||||
for i=1,#CODE do SP:write_u8(0x10000+i-1,CODE[i]) end
|
||||
SP:write_u32(0x18000,0); SP:write_u32(0x18004,0x5A5A5A5A); SP:write_u32(0x20000,0)
|
||||
CPU.state["SR"].value=0x2000; CPU.state["SP"].value=0x8000; CPU.state["PC"].value=0x10000
|
||||
STATE="run"; return
|
||||
end
|
||||
local fl=SP:read_u32(0x18000)
|
||||
if fl==0xFF or t>20 then
|
||||
STATE="done"
|
||||
print(string.format("[ONE] %s status=%08X buf=%08X",
|
||||
os.getenv("SZLABEL") or "?", SP:read_u32(0x18004), SP:read_u32(0x20000)))
|
||||
M:exit()
|
||||
end
|
||||
end
|
||||
SUB=emu.add_machine_frame_notifier(function()
|
||||
local ok,e=pcall(tick); if not ok then print("[ONE] ERR "..tostring(e)); M:exit() end end)
|
||||
@@ -0,0 +1,14 @@
|
||||
FLAG=$18000
|
||||
STAT=$18004
|
||||
BUF=$20000
|
||||
org $10000
|
||||
start: move.l #1,FLAG.l
|
||||
moveq #$46,d0
|
||||
move.l #$80000000,d1
|
||||
moveq #0,d2
|
||||
move.l #256,d3
|
||||
lea BUF,a1
|
||||
trap #15
|
||||
move.l d0,STAT.l
|
||||
move.l #$FF,FLAG.l
|
||||
stop: bra.s stop
|
||||
@@ -0,0 +1,5 @@
|
||||
local cpu = manager.machine.devices[":maincpu"]
|
||||
local names={}
|
||||
for k,v in pairs(cpu.state) do names[#names+1]=tostring(k) end
|
||||
table.sort(names)
|
||||
print("[REGS] "..table.concat(names,", "))
|
||||
@@ -0,0 +1,32 @@
|
||||
M=manager.machine; CPU=M.devices[":maincpu"]; SP=CPU.spaces["program"]
|
||||
local f=io.open("sweep.bin","rb"); local d=f:read("a"); f:close()
|
||||
CODE={}; for i=1,#d do CODE[i]=string.byte(d,i) end
|
||||
STATE="wait"
|
||||
local function T() local t=M.time return t.seconds+t.attoseconds/1e18 end
|
||||
local function tick()
|
||||
local t=T()
|
||||
if STATE=="wait" then
|
||||
if t<5.0 then return end
|
||||
for i=1,#CODE do SP:write_u8(0x10000+i-1,CODE[i]) end
|
||||
SP:write_u32(0x18000,0)
|
||||
for i=0,31 do SP:write_u32(0x18100+i*4,0x5A5A5A5A) end
|
||||
CPU.state["SR"].value=0x2000; CPU.state["SP"].value=0x8000; CPU.state["PC"].value=0x10000
|
||||
STATE="run"; print("[SW] injected")
|
||||
return
|
||||
end
|
||||
if STATE=="run" then
|
||||
local fl=SP:read_u32(0x18000)
|
||||
if fl==0xFF or t>25 then
|
||||
STATE="done"
|
||||
print("[SW] flag="..string.format("%X",fl))
|
||||
for i=0,15 do
|
||||
local a=SP:read_u32(0x18100+i*8)
|
||||
local b=SP:read_u32(0x18100+i*8+4)
|
||||
print(string.format("[SW] PDA=%02X encA(<<24)=%08X encB(<<8)=%08X",0x80+i,a,b))
|
||||
end
|
||||
M:exit()
|
||||
end
|
||||
end
|
||||
end
|
||||
SUB=emu.add_machine_frame_notifier(function()
|
||||
local ok,err=pcall(tick); if not ok then print("[SW] ERR "..tostring(err)); M:exit() end end)
|
||||
@@ -0,0 +1,34 @@
|
||||
FLAG = $18000
|
||||
RESULT = $18100
|
||||
BUF = $20000
|
||||
org $10000
|
||||
start:
|
||||
move.l #1,FLAG.l
|
||||
lea RESULT,a2
|
||||
moveq #0,d4
|
||||
outer:
|
||||
move.l d4,d1 ; encoding A: PDA in bits 31-24
|
||||
add.l #$80,d1
|
||||
swap d1
|
||||
lsl.l #8,d1
|
||||
bsr.s doread
|
||||
move.l d0,(a2)+
|
||||
move.l d4,d1 ; encoding B: PDA in bits 15-8
|
||||
add.l #$80,d1
|
||||
lsl.l #8,d1
|
||||
bsr.s doread
|
||||
move.l d0,(a2)+
|
||||
addq.l #1,d4
|
||||
cmpi.l #16,d4
|
||||
bne.s outer
|
||||
move.l #$FF,FLAG.l
|
||||
stop: bra.s stop
|
||||
doread:
|
||||
movem.l d2-d7/a2-a6,-(sp)
|
||||
moveq #$46,d0
|
||||
moveq #0,d2
|
||||
move.l #256,d3
|
||||
lea BUF,a1
|
||||
trap #15
|
||||
movem.l (sp)+,d2-d7/a2-a6
|
||||
rts
|
||||
Reference in New Issue
Block a user