From dd6740bf018acce123578f1a871836c1e81203f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Albeza?= Date: Fri, 19 Jul 2024 11:50:19 +0200 Subject: [PATCH] Replace the old animation rom for a pacman-themed one (#16) --- coco-ui/index.html | 2 +- coco-ui/roms/pacman.rom | Bin 0 -> 249 bytes coco-ui/roms/pacman.tal | 85 +++++++++++++++++++++++++++++++++ coco-ui/roms/sprite_move.rom | Bin 89 -> 0 bytes coco-ui/roms/sprite_move.tal | 38 --------------- coco-ui/src/lib.rs | 5 +- coco-ui/vendor/coco_ui.js | 49 +++++++++++-------- coco-ui/vendor/coco_ui_bg.wasm | Bin 48192 -> 48987 bytes 8 files changed, 118 insertions(+), 61 deletions(-) create mode 100644 coco-ui/roms/pacman.rom create mode 100644 coco-ui/roms/pacman.tal delete mode 100644 coco-ui/roms/sprite_move.rom delete mode 100644 coco-ui/roms/sprite_move.tal diff --git a/coco-ui/index.html b/coco-ui/index.html index f82ec9b..bbe7d15 100644 --- a/coco-ui/index.html +++ b/coco-ui/index.html @@ -19,7 +19,7 @@

👻-8

- +
diff --git a/coco-ui/roms/pacman.rom b/coco-ui/roms/pacman.rom new file mode 100644 index 0000000000000000000000000000000000000000..9c4a3a682cabe444f03913192072df5adceefed6 GIT binary patch literal 249 zcmXwyJr2S!3`U(IwG@Gx08+}&!h#sf)C+JI*1}Macthd_=@eGqfQ@T#5>{*qk^JdP zUh)#nnrt1-gOWV~87BdbHZ=EAXzC?qo+{ZBSVPb4YPm@DiXdZ6s!xg`4JNc1_kyGn z-A+&PaWpR#r&7K@98{K6RMuo^>7xl+!BSE7YSk(MK!gmjIr>w3L42cgi03QnYP04D f%rLs&V#g7>2oQ9n=Ncivmop15xnt(=n?L^mYB5fC literal 0 HcmV?d00001 diff --git a/coco-ui/roms/pacman.tal b/coco-ui/roms/pacman.tal new file mode 100644 index 0000000..4ef9d06 --- /dev/null +++ b/coco-ui/roms/pacman.tal @@ -0,0 +1,85 @@ +( sprite animation ) +|10 @Screen &vector $2 &x $1 &y $1 &pixel $1 &pad $3 &address $2 &sprite $1 + +%MOD { DUP2 DIV MUL SUB } ( a b -- a%b ) + +|0000 +@x $1 +@t $1 +@pacman-spr $2 + +|0100 ( -> ) + ;on-frame .Screen/vector DEO2 + + ( init vars ) + ;pacman00 .pacman-spr STZ2 + #00 .t STZ + #00 .x STZ + + ( draw bg ) + #21 .Screen/pixel DEO +BRK + +@on-frame ( -> ) + ( clear foreground ) + #00 .Screen/x DEO + #00 .Screen/y DEO + #30 .Screen/pixel DEO + + ( move party ) + .x LDZ INC #c0 MOD DUP + + .x STZ .Screen/x DEO + +( handle animation time ) + .t LDZ INC DUP .t STZ #0f EQU ,&update-frame JCN ,&draw-pacman JMP + &update-frame + #00 .t STZ + .pacman-spr LDZ2 ;pacman00 EQU2 ,&change-to-01 JCN ,&change-to-00 JMP + &change-to-01 + ;pacman01 .pacman-spr STZ2 ,&draw-pacman JMP + &change-to-00 + ;pacman00 .pacman-spr STZ2 + + ( draw pacman ) + &draw-pacman + #44 .Screen/y DEO + .pacman-spr LDZ2 .Screen/address DEO2 + #10 .Screen/sprite DEO + + ( draw ghost ) + &draw-ghost + ;coco .Screen/address DEO2 + .x LDZ #0f ADD #c0 MOD .Screen/x DEO + #10 .Screen/sprite DEO +BRK + +@coco +0077 7700 +0777 7770 +6717 7176 +7f77 77f7 +7711 1177 +7772 8777 +7777 7777 +7607 7067 + +@pacman00 +00aa aa00 +0aa1 8aa0 +9aaa a000 +9aa0 0000 +99a0 0000 +99aa a000 +0999 aaa0 +0099 9900 + +@pacman01 +00aa aa00 +0aaa aaa0 +9aaa 18aa +9aaa aaaa +99aa aaaa +99aa aaaa +0999 aaa0 +0099 9900 \ No newline at end of file diff --git a/coco-ui/roms/sprite_move.rom b/coco-ui/roms/sprite_move.rom deleted file mode 100644 index a9bc92639e014e64e4b6a880babb9a0869bb450b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89 zcmZ3$DAXWezJSrPLBhO2u|Y(fp+QKj0Z51g31RUD1E3IN!vQsEDM^r+3rI|$K}wu~ ip}d@dy}Z02UA(ZYzP$W ) - ;on-frame .Screen/vector DEO2 - ;coco .Screen/address DEO2 - - ( draw bg ) - #21 .Screen/pixel DEO -BRK - -@on-frame ( -> ) - ( clear foreground ) - .Screen/x DEI - #00 .Screen/x DEO - #00 .Screen/y DEO - #30 .Screen/pixel DEO - - ( move ghost ) - INC #c0 MOD .Screen/x DEO - #44 .Screen/y DEO - - ( draw ghost ) - #10 .Screen/sprite DEO -BRK - -@coco -0077 7700 -0777 7770 -6717 7176 -7f77 77f7 -7711 1177 -7772 8777 -7777 7777 -7607 7067 - diff --git a/coco-ui/src/lib.rs b/coco-ui/src/lib.rs index 944fb91..6394d69 100644 --- a/coco-ui/src/lib.rs +++ b/coco-ui/src/lib.rs @@ -53,7 +53,10 @@ pub fn run_rom(rom: &[u8]) -> Result { render(&mut vm.borrow_mut(), &ctx, &mut canvas_buffer); *g.borrow_mut() = Some(Closure::new(move || { - vm.borrow_mut().on_video(&mut cpu.borrow_mut()); + let on_video_output = vm.borrow_mut().on_video(&mut cpu.borrow_mut()); + if on_video_output.sys_stdout.len() > 0 { + web_sys::console::log_1(&JsValue::from(on_video_output.sys_stdout)); + } render(&mut vm.borrow_mut(), &ctx, &mut canvas_buffer); request_animation_frame(f.borrow().as_ref().unwrap()) })); diff --git a/coco-ui/vendor/coco_ui.js b/coco-ui/vendor/coco_ui.js index dba6796..248b2bd 100644 --- a/coco-ui/vendor/coco_ui.js +++ b/coco-ui/vendor/coco_ui.js @@ -20,6 +20,24 @@ function takeObject(idx) { return ret; } +const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } ); + +if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); }; + +let cachedUint8Memory0 = null; + +function getUint8Memory0() { + if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) { + cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8Memory0; +} + +function getStringFromWasm0(ptr, len) { + ptr = ptr >>> 0; + return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); +} + function addHeapObject(obj) { if (heap_next === heap.length) heap.push(heap.length + 1); const idx = heap_next; @@ -96,15 +114,6 @@ function debugString(val) { let WASM_VECTOR_LEN = 0; -let cachedUint8Memory0 = null; - -function getUint8Memory0() { - if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) { - cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); - } - return cachedUint8Memory0; -} - const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } ); const encodeString = (typeof cachedTextEncoder.encodeInto === 'function' @@ -168,15 +177,6 @@ function getInt32Memory0() { return cachedInt32Memory0; } -const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } ); - -if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); }; - -function getStringFromWasm0(ptr, len) { - ptr = ptr >>> 0; - return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); -} - const CLOSURE_DTORS = (typeof FinalizationRegistry === 'undefined') ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry(state => { @@ -207,7 +207,7 @@ function makeMutClosure(arg0, arg1, dtor, f) { CLOSURE_DTORS.register(real, state, state); return real; } -function __wbg_adapter_14(arg0, arg1) { +function __wbg_adapter_16(arg0, arg1) { wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hbe6b0b61f022bb4f(arg0, arg1); } @@ -366,6 +366,10 @@ function __wbg_get_imports() { const ret = false; return ret; }; + imports.wbg.__wbindgen_string_new = function(arg0, arg1) { + const ret = getStringFromWasm0(arg0, arg1); + return addHeapObject(ret); + }; imports.wbg.__wbg_instanceof_Window_f401953a2cf86220 = function(arg0) { let result; try { @@ -405,6 +409,9 @@ function __wbg_get_imports() { const ret = new ImageData(getClampedArrayU8FromWasm0(arg0, arg1), arg2 >>> 0, arg3 >>> 0); return addHeapObject(ret); }, arguments) }; + imports.wbg.__wbg_log_5bb5f88f245d7762 = function(arg0) { + console.log(getObject(arg0)); + }; imports.wbg.__wbg_instanceof_HtmlCanvasElement_46bdbf323b0b18d1 = function(arg0) { let result; try { @@ -461,8 +468,8 @@ function __wbg_get_imports() { imports.wbg.__wbindgen_throw = function(arg0, arg1) { throw new Error(getStringFromWasm0(arg0, arg1)); }; - imports.wbg.__wbindgen_closure_wrapper25 = function(arg0, arg1, arg2) { - const ret = makeMutClosure(arg0, arg1, 3, __wbg_adapter_14); + imports.wbg.__wbindgen_closure_wrapper27 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 3, __wbg_adapter_16); return addHeapObject(ret); }; diff --git a/coco-ui/vendor/coco_ui_bg.wasm b/coco-ui/vendor/coco_ui_bg.wasm index 5d533af9280732527261241941a1d2741eb62308..d433b40e571199245dcada083c8a477202ee89cd 100644 GIT binary patch delta 6641 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