stress-test add cartridge
This commit is contained in:
parent
52502830a3
commit
ca40a7b939
8
crates/tools/pbxgen-stress/Cargo.toml
Normal file
8
crates/tools/pbxgen-stress/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "pbxgen-stress"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
prometeu-bytecode = { path = "../../console/prometeu-bytecode" }
|
||||||
|
anyhow = "1"
|
||||||
180
crates/tools/pbxgen-stress/src/lib.rs
Normal file
180
crates/tools/pbxgen-stress/src/lib.rs
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
use prometeu_bytecode::assembler::assemble;
|
||||||
|
use prometeu_bytecode::model::{BytecodeModule, ConstantPoolEntry, DebugInfo, Export, FunctionMeta};
|
||||||
|
use std::fs;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
fn asm(s: &str) -> Vec<u8> { assemble(s).expect("assemble") }
|
||||||
|
|
||||||
|
pub fn generate() -> Result<()> {
|
||||||
|
let mut rom: Vec<u8> = Vec::new();
|
||||||
|
|
||||||
|
heavy_load(&mut rom);
|
||||||
|
//light_load(&mut rom);
|
||||||
|
|
||||||
|
let functions = vec![
|
||||||
|
FunctionMeta {
|
||||||
|
code_offset: 0,
|
||||||
|
code_len: rom.len() as u32,
|
||||||
|
param_slots: 0,
|
||||||
|
local_slots: 2,
|
||||||
|
return_slots: 0,
|
||||||
|
max_stack_slots: 16,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let module = BytecodeModule {
|
||||||
|
version: 0,
|
||||||
|
const_pool: vec![
|
||||||
|
ConstantPoolEntry::String("stress".into()),
|
||||||
|
ConstantPoolEntry::String("frame".into()),
|
||||||
|
],
|
||||||
|
functions,
|
||||||
|
code: rom,
|
||||||
|
debug_info: Some(DebugInfo {
|
||||||
|
pc_to_span: vec![],
|
||||||
|
function_names: vec![(0, "main".into())],
|
||||||
|
}),
|
||||||
|
exports: vec![Export { symbol: "main".into(), func_idx: 0 }],
|
||||||
|
};
|
||||||
|
|
||||||
|
let bytes = module.serialize();
|
||||||
|
|
||||||
|
let mut out_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||||
|
out_dir.pop(); // pbxgen-stress
|
||||||
|
out_dir.pop(); // tools
|
||||||
|
out_dir.pop(); // crates
|
||||||
|
out_dir.push("test-cartridges");
|
||||||
|
out_dir.push("stress-console");
|
||||||
|
fs::create_dir_all(&out_dir)?;
|
||||||
|
fs::write(out_dir.join("program.pbx"), bytes)?;
|
||||||
|
if !out_dir.join("assets.pa").exists() {
|
||||||
|
fs::write(out_dir.join("assets.pa"), &[] as &[u8])?;
|
||||||
|
}
|
||||||
|
if !out_dir.join("manifest.json").exists() {
|
||||||
|
fs::write(out_dir.join("manifest.json"), b"{\n \"magic\": \"PMTU\",\n \"cartridge_version\": 1,\n \"app_id\": 1,\n \"title\": \"Stress Console\",\n \"app_version\": \"0.1.0\",\n \"app_mode\": \"Game\",\n \"entrypoint\": \"main\"\n}\n")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn heavy_load(mut rom: &mut Vec<u8>) {
|
||||||
|
// Single function 0: main
|
||||||
|
// Everything runs here — no coroutines, no SPAWN, no YIELD.
|
||||||
|
//
|
||||||
|
// Global 0 = t (frame counter)
|
||||||
|
// Local 0 = scratch
|
||||||
|
// Local 1 = loop counter for discs
|
||||||
|
//
|
||||||
|
// Loop:
|
||||||
|
// t = (t + 1)
|
||||||
|
// clear screen
|
||||||
|
// draw 100 discs using t for animation
|
||||||
|
// draw 20 texts using t for animation
|
||||||
|
// RET (runtime handles the frame loop)
|
||||||
|
|
||||||
|
// --- init locals ---
|
||||||
|
// local 0: scratch
|
||||||
|
// local 1: loop counter for discs
|
||||||
|
rom.extend(asm("PUSH_I32 0\nSET_LOCAL 0\nPUSH_I32 0\nSET_LOCAL 1"));
|
||||||
|
|
||||||
|
// --- t = (t + 1) ---
|
||||||
|
// t is global 0 to persist across prepare_call resets
|
||||||
|
rom.extend(asm("GET_GLOBAL 0\nPUSH_I32 1\nADD\nSET_GLOBAL 0"));
|
||||||
|
|
||||||
|
// --- clear screen ---
|
||||||
|
rom.extend(asm("PUSH_I32 0\nSYSCALL 0x1010"));
|
||||||
|
|
||||||
|
// --- draw 500 discs ---
|
||||||
|
rom.extend(asm("PUSH_I32 0\nSET_LOCAL 1"));
|
||||||
|
let disc_loop_start = rom.len() as u32;
|
||||||
|
rom.extend(asm("GET_LOCAL 1\nPUSH_I32 500\nLT"));
|
||||||
|
let jif_disc_end_offset = rom.len() + 2;
|
||||||
|
rom.extend(asm("JMP_IF_FALSE 0"));
|
||||||
|
|
||||||
|
// x = (t * (i+7) + i * 13) % 320
|
||||||
|
rom.extend(asm("GET_GLOBAL 0\nGET_LOCAL 1\nPUSH_I32 7\nADD\nMUL\nGET_LOCAL 1\nPUSH_I32 13\nMUL\nADD\nPUSH_I32 320\nMOD"));
|
||||||
|
// y = (t * (i+11) + i * 17) % 180
|
||||||
|
rom.extend(asm("GET_GLOBAL 0\nGET_LOCAL 1\nPUSH_I32 11\nADD\nMUL\nGET_LOCAL 1\nPUSH_I32 17\nMUL\nADD\nPUSH_I32 180\nMOD"));
|
||||||
|
// r = ( (i*13) % 20 ) + 5
|
||||||
|
rom.extend(asm("GET_LOCAL 1\nPUSH_I32 13\nMUL\nPUSH_I32 20\nMOD\nPUSH_I32 5\nADD"));
|
||||||
|
// border color = (i * 1234) & 0xFFFF
|
||||||
|
rom.extend(asm("GET_LOCAL 1\nPUSH_I32 1234\nMUL\nPUSH_I32 65535\nBIT_AND"));
|
||||||
|
// fill color = (i * 5678 + t) & 0xFFFF
|
||||||
|
rom.extend(asm("GET_LOCAL 1\nPUSH_I32 5678\nMUL\nGET_GLOBAL 0\nADD\nPUSH_I32 65535\nBIT_AND"));
|
||||||
|
// SYSCALL GfxDrawDisc (x, y, r, border, fill)
|
||||||
|
rom.extend(asm("SYSCALL 0x1005"));
|
||||||
|
|
||||||
|
// i++
|
||||||
|
rom.extend(asm("GET_LOCAL 1\nPUSH_I32 1\nADD\nSET_LOCAL 1"));
|
||||||
|
let jmp_disc_loop_offset = rom.len() + 2;
|
||||||
|
rom.extend(asm("JMP 0"));
|
||||||
|
let disc_loop_end = rom.len() as u32;
|
||||||
|
|
||||||
|
// --- draw 20 texts ---
|
||||||
|
rom.extend(asm("PUSH_I32 0\nSET_LOCAL 1"));
|
||||||
|
let text_loop_start = rom.len() as u32;
|
||||||
|
rom.extend(asm("GET_LOCAL 1\nPUSH_I32 20\nLT"));
|
||||||
|
let jif_text_end_offset = rom.len() + 2;
|
||||||
|
rom.extend(asm("JMP_IF_FALSE 0"));
|
||||||
|
|
||||||
|
// x = (t * 3 + i * 40) % 320
|
||||||
|
rom.extend(asm("GET_GLOBAL 0\nPUSH_I32 3\nMUL\nGET_LOCAL 1\nPUSH_I32 40\nMUL\nADD\nPUSH_I32 320\nMOD"));
|
||||||
|
// y = (i * 30 + t) % 180
|
||||||
|
rom.extend(asm("GET_LOCAL 1\nPUSH_I32 30\nMUL\nGET_GLOBAL 0\nADD\nPUSH_I32 180\nMOD"));
|
||||||
|
// string (toggle between "stress" and "frame")
|
||||||
|
rom.extend(asm("GET_LOCAL 1\nPUSH_I32 1\nBIT_AND"));
|
||||||
|
let jif_text_alt_offset = rom.len() + 2;
|
||||||
|
rom.extend(asm("JMP_IF_FALSE 0"));
|
||||||
|
rom.extend(asm("PUSH_CONST 0")); // "stress"
|
||||||
|
let jmp_text_join_offset = rom.len() + 2;
|
||||||
|
rom.extend(asm("JMP 0"));
|
||||||
|
let text_alt_target = rom.len() as u32;
|
||||||
|
rom.extend(asm("PUSH_CONST 1")); // "frame"
|
||||||
|
let text_join_target = rom.len() as u32;
|
||||||
|
|
||||||
|
// color = (t * 10 + i * 1000) & 0xFFFF
|
||||||
|
rom.extend(asm("GET_GLOBAL 0\nPUSH_I32 10\nMUL\nGET_LOCAL 1\nPUSH_I32 1000\nMUL\nADD\nPUSH_I32 65535\nBIT_AND"));
|
||||||
|
// SYSCALL GfxDrawText (x, y, str, color)
|
||||||
|
rom.extend(asm("SYSCALL 0x1008"));
|
||||||
|
|
||||||
|
// i++
|
||||||
|
rom.extend(asm("GET_LOCAL 1\nPUSH_I32 1\nADD\nSET_LOCAL 1"));
|
||||||
|
let jmp_text_loop_offset = rom.len() + 2;
|
||||||
|
rom.extend(asm("JMP 0"));
|
||||||
|
let text_loop_end = rom.len() as u32;
|
||||||
|
|
||||||
|
// --- log every 60 frames ---
|
||||||
|
rom.extend(asm("GET_GLOBAL 0\nPUSH_I32 60\nMOD\nPUSH_I32 0\nEQ"));
|
||||||
|
let jif_log_offset = rom.len() + 2;
|
||||||
|
rom.extend(asm("JMP_IF_FALSE 0"));
|
||||||
|
rom.extend(asm("PUSH_I32 2\nPUSH_CONST 0\nSYSCALL 0x5001"));
|
||||||
|
let after_log = rom.len() as u32;
|
||||||
|
|
||||||
|
// --- end of function ---
|
||||||
|
rom.extend(asm("FRAME_SYNC\nRET"));
|
||||||
|
|
||||||
|
// --- Patch jump targets ---
|
||||||
|
let patch = |buf: &mut Vec<u8>, imm_offset: usize, target: u32| {
|
||||||
|
buf[imm_offset..imm_offset + 4].copy_from_slice(&target.to_le_bytes());
|
||||||
|
};
|
||||||
|
|
||||||
|
patch(&mut rom, jif_disc_end_offset, disc_loop_end);
|
||||||
|
patch(&mut rom, jmp_disc_loop_offset, disc_loop_start);
|
||||||
|
|
||||||
|
patch(&mut rom, jif_text_end_offset, text_loop_end);
|
||||||
|
patch(&mut rom, jif_text_alt_offset, text_alt_target);
|
||||||
|
patch(&mut rom, jmp_text_join_offset, text_join_target);
|
||||||
|
patch(&mut rom, jmp_text_loop_offset, text_loop_start);
|
||||||
|
|
||||||
|
patch(&mut rom, jif_log_offset, after_log);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn light_load(rom: &mut Vec<u8>) {
|
||||||
|
// // Single function 0: main
|
||||||
|
// // Only paints Purple: 0x780F once.
|
||||||
|
// // The runtime handles calling this function repeatedly every tick.
|
||||||
|
//
|
||||||
|
// // --- clear screen (Purple 0x780F) ---
|
||||||
|
// rom.extend(asm("PUSH_I32 30735\nSYSCALL 0x1010\nFRAME_SYNC\nRET")); // 30735 is 0x780F
|
||||||
|
// }
|
||||||
3
crates/tools/pbxgen-stress/src/main.rs
Normal file
3
crates/tools/pbxgen-stress/src/main.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
fn main() -> Result<()> { pbxgen_stress::generate() }
|
||||||
0
test-cartridges/stress-console/assets.pa
Normal file
0
test-cartridges/stress-console/assets.pa
Normal file
9
test-cartridges/stress-console/manifest.json
Normal file
9
test-cartridges/stress-console/manifest.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"magic": "PMTU",
|
||||||
|
"cartridge_version": 1,
|
||||||
|
"app_id": 1,
|
||||||
|
"title": "Stress Console",
|
||||||
|
"app_version": "0.1.0",
|
||||||
|
"app_mode": "Game",
|
||||||
|
"entrypoint": "main"
|
||||||
|
}
|
||||||
BIN
test-cartridges/stress-console/program.pbx
Normal file
BIN
test-cartridges/stress-console/program.pbx
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user