From 2f4921b1acf371d14c15f3778fc78f75342b8396 Mon Sep 17 00:00:00 2001 From: ThisAccountHasBeenSuspended <176883156+ThisAccountHasBeenSuspended@users.noreply.github.com> Date: Thu, 29 Aug 2024 16:39:20 +0200 Subject: [PATCH 1/7] `lazy_static` replaced by `std::sync::OnceLock` --- vm-rust/Cargo.toml | 1 - vm-rust/src/director/chunks/handler.rs | 4 +- vm-rust/src/director/lingo/constants.rs | 323 +++++++++++++----------- vm-rust/src/player/bytecode/get_set.rs | 8 +- vm-rust/src/player/events.rs | 4 +- vm-rust/src/player/keyboard.rs | 4 +- vm-rust/src/player/keyboard_map.rs | 175 ++++++------- vm-rust/src/player/mod.rs | 10 +- vm-rust/src/player/profiling.rs | 14 +- 9 files changed, 281 insertions(+), 262 deletions(-) diff --git a/vm-rust/Cargo.toml b/vm-rust/Cargo.toml index d5df350..b91dfb0 100644 --- a/vm-rust/Cargo.toml +++ b/vm-rust/Cargo.toml @@ -21,7 +21,6 @@ console_error_panic_hook = { version = "0.1.7", optional = true } wasm-bindgen-futures = "0.4.37" js-sys = "0.3.64" binary-reader = "0.4.5" -lazy_static = "1.4.0" num = "0.4.1" num-derive = "0.4.0" num-traits = "0.2.16" diff --git a/vm-rust/src/director/chunks/handler.rs b/vm-rust/src/director/chunks/handler.rs index c0e38e4..e2ca025 100644 --- a/vm-rust/src/director/chunks/handler.rs +++ b/vm-rust/src/director/chunks/handler.rs @@ -1,7 +1,7 @@ use binary_reader::BinaryReader; use fxhash::FxHashMap; -use crate::director::lingo::{constants::OPCODE_NAMES, opcode::OpCode, script::ScriptContext}; +use crate::director::lingo::{constants::opcode_names, opcode::OpCode, script::ScriptContext}; #[allow(dead_code)] pub struct HandlerRecord { @@ -89,7 +89,7 @@ pub fn get_opcode_name(id: u16) -> String { } else { id }; - let it = OPCODE_NAMES.get(&OpCode::from(real_id)); + let it = opcode_names().get(&OpCode::from(real_id)); return it.unwrap_or(&"UNKOWN_BYTECODE".to_string()).to_owned() } diff --git a/vm-rust/src/director/lingo/constants.rs b/vm-rust/src/director/lingo/constants.rs index 9666644..38d757b 100644 --- a/vm-rust/src/director/lingo/constants.rs +++ b/vm-rust/src/director/lingo/constants.rs @@ -1,168 +1,187 @@ -use std::collections::HashMap; - -use lazy_static::lazy_static; +use std::{collections::HashMap, sync::OnceLock}; use super::opcode::OpCode; -lazy_static! { - pub static ref OPCODE_NAMES: HashMap = HashMap::from([ - // single-byte - (OpCode::Ret, "ret".to_owned()), - (OpCode::RetFactory, "retfactory".to_owned()), - (OpCode::Mul, "mul".to_owned()), - (OpCode::PushZero, "pushzero".to_owned()), - (OpCode::Add, "add".to_owned()), - (OpCode::Sub, "sub".to_owned()), - (OpCode::Div, "div".to_owned()), - (OpCode::Mod, "mod".to_owned()), - (OpCode::Inv, "inv".to_owned()), - (OpCode::JoinStr, "joinstr".to_owned()), - (OpCode::JoinPadStr, "joinpadstr".to_owned()), - (OpCode::Lt, "lt".to_owned()), - (OpCode::LtEq, "lteq".to_owned()), - (OpCode::NtEq, "nteq".to_owned()), - (OpCode::Eq, "eq".to_owned()), - (OpCode::Gt, "gt".to_owned()), - (OpCode::GtEq, "gteq".to_owned()), - (OpCode::And, "and".to_owned()), - (OpCode::Or, "or".to_owned()), - (OpCode::Not, "not".to_owned()), - (OpCode::ContainsStr, "containsstr".to_owned()), - (OpCode::Contains0Str, "contains0str".to_owned()), - (OpCode::GetChunk, "getchunk".to_owned()), - (OpCode::HiliteChunk, "hilitechunk".to_owned()), - (OpCode::OntoSpr, "ontospr".to_owned()), - (OpCode::IntoSpr, "intospr".to_owned()), - (OpCode::GetField, "getfield".to_owned()), - (OpCode::StartTell, "starttell".to_owned()), - (OpCode::EndTell, "endtell".to_owned()), - (OpCode::PushList, "pushlist".to_owned()), - (OpCode::PushPropList, "pushproplist".to_owned()), - (OpCode::Swap, "swap".to_owned()), - (OpCode::CallJavaScript, "calljavascript".to_owned()), - - // multi-byte - (OpCode::PushInt8, "pushint8".to_owned()), - (OpCode::PushArgListNoRet, "pusharglistnoret".to_owned()), - (OpCode::PushArgList, "pusharglist".to_owned()), - (OpCode::PushCons, "pushcons".to_owned()), - (OpCode::PushSymb, "pushsymb".to_owned()), - (OpCode::PushVarRef, "pushvarref".to_owned()), - (OpCode::GetGlobal2, "getglobal2".to_owned()), - (OpCode::GetGlobal, "getglobal".to_owned()), - (OpCode::GetProp, "getprop".to_owned()), - (OpCode::GetParam, "getparam".to_owned()), - (OpCode::GetLocal, "getlocal".to_owned()), - (OpCode::SetGlobal2, "setglobal2".to_owned()), - (OpCode::SetGlobal, "setglobal".to_owned()), - (OpCode::SetProp, "setprop".to_owned()), - (OpCode::SetParam, "setparam".to_owned()), - (OpCode::SetLocal, "setlocal".to_owned()), - (OpCode::Jmp, "jmp".to_owned()), - (OpCode::EndRepeat, "endrepeat".to_owned()), - (OpCode::JmpIfZ, "jmpifz".to_owned()), - (OpCode::LocalCall, "localcall".to_owned()), - (OpCode::ExtCall, "extcall".to_owned()), - (OpCode::ObjCallV4, "objcallv4".to_owned()), - (OpCode::Put, "put".to_owned()), - (OpCode::PutChunk, "putchunk".to_owned()), - (OpCode::DeleteChunk, "deletechunk".to_owned()), - (OpCode::Get, "get".to_owned()), - (OpCode::Set, "set".to_owned()), - (OpCode::GetMovieProp, "getmovieprop".to_owned()), - (OpCode::SetMovieProp, "setmovieprop".to_owned()), - (OpCode::GetObjProp, "getobjprop".to_owned()), - (OpCode::SetObjProp, "setobjprop".to_owned()), - (OpCode::TellCall, "tellcall".to_owned()), - (OpCode::Peek, "peek".to_owned()), - (OpCode::Pop, "pop".to_owned()), - (OpCode::TheBuiltin, "thebuiltin".to_owned()), - (OpCode::ObjCall, "objcall".to_owned()), - (OpCode::PushChunkVarRef, "pushchunkvarref".to_owned()), - (OpCode::PushInt16, "pushint16".to_owned()), - (OpCode::PushInt32, "pushint32".to_owned()), - (OpCode::GetChainedProp, "getchainedprop".to_owned()), - (OpCode::PushFloat32, "pushfloat32".to_owned()), - (OpCode::GetTopLevelProp, "gettoplevelprop".to_owned()), - (OpCode::NewObj, "newobj".to_owned()), - ]); +pub fn opcode_names() -> &'static HashMap { + static MAP: OnceLock> = OnceLock::new(); + MAP.get_or_init(|| { + HashMap::from([ + // single-byte + (OpCode::Ret, "ret".to_owned()), + (OpCode::RetFactory, "retfactory".to_owned()), + (OpCode::Mul, "mul".to_owned()), + (OpCode::PushZero, "pushzero".to_owned()), + (OpCode::Add, "add".to_owned()), + (OpCode::Sub, "sub".to_owned()), + (OpCode::Div, "div".to_owned()), + (OpCode::Mod, "mod".to_owned()), + (OpCode::Inv, "inv".to_owned()), + (OpCode::JoinStr, "joinstr".to_owned()), + (OpCode::JoinPadStr, "joinpadstr".to_owned()), + (OpCode::Lt, "lt".to_owned()), + (OpCode::LtEq, "lteq".to_owned()), + (OpCode::NtEq, "nteq".to_owned()), + (OpCode::Eq, "eq".to_owned()), + (OpCode::Gt, "gt".to_owned()), + (OpCode::GtEq, "gteq".to_owned()), + (OpCode::And, "and".to_owned()), + (OpCode::Or, "or".to_owned()), + (OpCode::Not, "not".to_owned()), + (OpCode::ContainsStr, "containsstr".to_owned()), + (OpCode::Contains0Str, "contains0str".to_owned()), + (OpCode::GetChunk, "getchunk".to_owned()), + (OpCode::HiliteChunk, "hilitechunk".to_owned()), + (OpCode::OntoSpr, "ontospr".to_owned()), + (OpCode::IntoSpr, "intospr".to_owned()), + (OpCode::GetField, "getfield".to_owned()), + (OpCode::StartTell, "starttell".to_owned()), + (OpCode::EndTell, "endtell".to_owned()), + (OpCode::PushList, "pushlist".to_owned()), + (OpCode::PushPropList, "pushproplist".to_owned()), + (OpCode::Swap, "swap".to_owned()), + (OpCode::CallJavaScript, "calljavascript".to_owned()), + + // multi-byte + (OpCode::PushInt8, "pushint8".to_owned()), + (OpCode::PushArgListNoRet, "pusharglistnoret".to_owned()), + (OpCode::PushArgList, "pusharglist".to_owned()), + (OpCode::PushCons, "pushcons".to_owned()), + (OpCode::PushSymb, "pushsymb".to_owned()), + (OpCode::PushVarRef, "pushvarref".to_owned()), + (OpCode::GetGlobal2, "getglobal2".to_owned()), + (OpCode::GetGlobal, "getglobal".to_owned()), + (OpCode::GetProp, "getprop".to_owned()), + (OpCode::GetParam, "getparam".to_owned()), + (OpCode::GetLocal, "getlocal".to_owned()), + (OpCode::SetGlobal2, "setglobal2".to_owned()), + (OpCode::SetGlobal, "setglobal".to_owned()), + (OpCode::SetProp, "setprop".to_owned()), + (OpCode::SetParam, "setparam".to_owned()), + (OpCode::SetLocal, "setlocal".to_owned()), + (OpCode::Jmp, "jmp".to_owned()), + (OpCode::EndRepeat, "endrepeat".to_owned()), + (OpCode::JmpIfZ, "jmpifz".to_owned()), + (OpCode::LocalCall, "localcall".to_owned()), + (OpCode::ExtCall, "extcall".to_owned()), + (OpCode::ObjCallV4, "objcallv4".to_owned()), + (OpCode::Put, "put".to_owned()), + (OpCode::PutChunk, "putchunk".to_owned()), + (OpCode::DeleteChunk, "deletechunk".to_owned()), + (OpCode::Get, "get".to_owned()), + (OpCode::Set, "set".to_owned()), + (OpCode::GetMovieProp, "getmovieprop".to_owned()), + (OpCode::SetMovieProp, "setmovieprop".to_owned()), + (OpCode::GetObjProp, "getobjprop".to_owned()), + (OpCode::SetObjProp, "setobjprop".to_owned()), + (OpCode::TellCall, "tellcall".to_owned()), + (OpCode::Peek, "peek".to_owned()), + (OpCode::Pop, "pop".to_owned()), + (OpCode::TheBuiltin, "thebuiltin".to_owned()), + (OpCode::ObjCall, "objcall".to_owned()), + (OpCode::PushChunkVarRef, "pushchunkvarref".to_owned()), + (OpCode::PushInt16, "pushint16".to_owned()), + (OpCode::PushInt32, "pushint32".to_owned()), + (OpCode::GetChainedProp, "getchainedprop".to_owned()), + (OpCode::PushFloat32, "pushfloat32".to_owned()), + (OpCode::GetTopLevelProp, "gettoplevelprop".to_owned()), + (OpCode::NewObj, "newobj".to_owned()), + ]) + }) +} - pub static ref ANIM_PROP_NAMES: HashMap = HashMap::from([ - (0x01, "beepOn".to_owned()), - (0x02, "buttonStyle".to_owned()), - (0x03, "centerStage".to_owned()), - (0x04, "checkBoxAccess".to_owned()), - (0x05, "checkboxType".to_owned()), - (0x06, "colorDepth".to_owned()), - (0x07, "colorQD".to_owned()), - (0x08, "exitLock".to_owned()), - (0x09, "fixStageSize".to_owned()), - (0x0a, "fullColorPermit".to_owned()), - (0x0b, "imageDirect".to_owned()), - (0x0c, "doubleClick".to_owned()), - (0x0d, "key".to_owned()), - (0x0e, "lastClick".to_owned()), - (0x0f, "lastEvent".to_owned()), - (0x10, "keyCode".to_owned()), - (0x11, "lastKey".to_owned()), - (0x12, "lastRoll".to_owned()), - (0x13, "timeoutLapsed".to_owned()), - (0x14, "multiSound".to_owned()), - (0x15, "pauseState".to_owned()), - (0x16, "quickTimePresent".to_owned()), - (0x17, "selEnd".to_owned()), - (0x18, "selStart".to_owned()), - (0x19, "soundEnabled".to_owned()), - (0x1a, "soundLevel".to_owned()), - (0x1b, "stageColor".to_owned()), - // 0x1c indicates dontPassEvent was called. - // It doesn't seem to have a Lingo-accessible name. - (0x1d, "switchColorDepth".to_owned()), - (0x1e, "timeoutKeyDown".to_owned()), - (0x1f, "timeoutLength".to_owned()), - (0x20, "timeoutMouse".to_owned()), - (0x21, "timeoutPlay".to_owned()), - (0x22, "timer".to_owned()), - (0x23, "preLoadRAM".to_owned()), - (0x24, "videoForWindowsPresent".to_owned()), - (0x25, "netPresent".to_owned()), - (0x26, "safePlayer".to_owned()), - (0x27, "soundKeepDevice".to_owned()), - (0x28, "soundMixMedia".to_owned()), - ]); +fn anim_prop_names() -> &'static HashMap { + static MAP: OnceLock> = OnceLock::new(); + MAP.get_or_init(|| { + HashMap::from([ + (0x01, "beepOn".to_owned()), + (0x02, "buttonStyle".to_owned()), + (0x03, "centerStage".to_owned()), + (0x04, "checkBoxAccess".to_owned()), + (0x05, "checkboxType".to_owned()), + (0x06, "colorDepth".to_owned()), + (0x07, "colorQD".to_owned()), + (0x08, "exitLock".to_owned()), + (0x09, "fixStageSize".to_owned()), + (0x0a, "fullColorPermit".to_owned()), + (0x0b, "imageDirect".to_owned()), + (0x0c, "doubleClick".to_owned()), + (0x0d, "key".to_owned()), + (0x0e, "lastClick".to_owned()), + (0x0f, "lastEvent".to_owned()), + (0x10, "keyCode".to_owned()), + (0x11, "lastKey".to_owned()), + (0x12, "lastRoll".to_owned()), + (0x13, "timeoutLapsed".to_owned()), + (0x14, "multiSound".to_owned()), + (0x15, "pauseState".to_owned()), + (0x16, "quickTimePresent".to_owned()), + (0x17, "selEnd".to_owned()), + (0x18, "selStart".to_owned()), + (0x19, "soundEnabled".to_owned()), + (0x1a, "soundLevel".to_owned()), + (0x1b, "stageColor".to_owned()), + // 0x1c indicates dontPassEvent was called. + // It doesn't seem to have a Lingo-accessible name. + (0x1d, "switchColorDepth".to_owned()), + (0x1e, "timeoutKeyDown".to_owned()), + (0x1f, "timeoutLength".to_owned()), + (0x20, "timeoutMouse".to_owned()), + (0x21, "timeoutPlay".to_owned()), + (0x22, "timer".to_owned()), + (0x23, "preLoadRAM".to_owned()), + (0x24, "videoForWindowsPresent".to_owned()), + (0x25, "netPresent".to_owned()), + (0x26, "safePlayer".to_owned()), + (0x27, "soundKeepDevice".to_owned()), + (0x28, "soundMixMedia".to_owned()), + ]) + }) +} - pub static ref ANIM2_PROP_NAMES: HashMap = HashMap::from([ - (0x01, "perFrameHook".to_owned()), - (0x02, "number of castMembers".to_owned()), - (0x03, "number of menus".to_owned()), - (0x04, "number of castLibs".to_owned()), - (0x05, "number of xtras".to_owned()), - ]); +fn anim2_prop_names() -> &'static HashMap { + static MAP: OnceLock> = OnceLock::new(); + MAP.get_or_init(|| { + HashMap::from([ + (0x01, "perFrameHook".to_owned()), + (0x02, "number of castMembers".to_owned()), + (0x03, "number of menus".to_owned()), + (0x04, "number of castLibs".to_owned()), + (0x05, "number of xtras".to_owned()), + ]) + }) +} - pub static ref MOVIE_PROP_NAMES: HashMap = HashMap::from([ - (0x00, "floatPrecision".to_owned()), - (0x01, "mouseDownScript".to_owned()), - (0x02, "mouseUpScript".to_owned()), - (0x03, "keyDownScript".to_owned()), - (0x04, "keyUpScript".to_owned()), - (0x05, "timeoutScript".to_owned()), - (0x06, "short time".to_owned()), - (0x07, "abbr time".to_owned()), - (0x08, "long time".to_owned()), - (0x09, "short date".to_owned()), - (0x0a, "abbr date".to_owned()), - (0x0b, "long date".to_owned()), - ]); +pub fn movie_prop_names() -> &'static HashMap { + static MAP: OnceLock> = OnceLock::new(); + MAP.get_or_init(|| { + HashMap::from([ + (0x00, "floatPrecision".to_owned()), + (0x01, "mouseDownScript".to_owned()), + (0x02, "mouseUpScript".to_owned()), + (0x03, "keyDownScript".to_owned()), + (0x04, "keyUpScript".to_owned()), + (0x05, "timeoutScript".to_owned()), + (0x06, "short time".to_owned()), + (0x07, "abbr time".to_owned()), + (0x08, "long time".to_owned()), + (0x09, "short date".to_owned()), + (0x0a, "abbr date".to_owned()), + (0x0b, "long date".to_owned()), + ]) + }) } +#[inline] pub fn get_opcode_name(opcode: &OpCode) -> String { - OPCODE_NAMES.get(opcode).unwrap().to_owned() + opcode_names().get(opcode).unwrap().to_owned() } +#[inline] pub fn get_anim_prop_name(name_id: u16) -> String { - ANIM_PROP_NAMES.get(&name_id).unwrap().to_owned() + anim_prop_names().get(&name_id).unwrap().to_owned() } +#[inline] pub fn get_anim2_prop_name(name_id: u16) -> String { - ANIM2_PROP_NAMES.get(&name_id).unwrap().to_owned() + anim2_prop_names().get(&name_id).unwrap().to_owned() } diff --git a/vm-rust/src/player/bytecode/get_set.rs b/vm-rust/src/player/bytecode/get_set.rs index 9267aed..f3036f7 100644 --- a/vm-rust/src/player/bytecode/get_set.rs +++ b/vm-rust/src/player/bytecode/get_set.rs @@ -1,4 +1,4 @@ -use crate::{console_warn, director::{chunks::handler::Bytecode, lingo::{constants::{get_anim_prop_name, MOVIE_PROP_NAMES}, datum::{Datum, StringChunkType}}}, player::{allocator::DatumAllocatorTrait, handlers::datum_handlers::string_chunk::StringChunkUtils, reserve_player_mut, script::{get_current_handler_def, get_current_variable_multiplier, get_name, get_obj_prop, player_set_obj_prop, script_get_prop, script_set_prop}, DatumRef, DirPlayer, HandlerExecutionResult, HandlerExecutionResultContext, ScriptError, PLAYER_OPT}}; +use crate::{console_warn, director::{chunks::handler::Bytecode, lingo::{constants::{get_anim_prop_name, movie_prop_names}, datum::{Datum, StringChunkType}}}, player::{allocator::DatumAllocatorTrait, handlers::datum_handlers::string_chunk::StringChunkUtils, reserve_player_mut, script::{get_current_handler_def, get_current_variable_multiplier, get_name, get_obj_prop, player_set_obj_prop, script_get_prop, script_set_prop}, DatumRef, DirPlayer, HandlerExecutionResult, HandlerExecutionResultContext, ScriptError, PLAYER_OPT}}; use super::handler_manager::BytecodeHandlerContext; @@ -123,7 +123,7 @@ impl GetSetBytecodeHandler { 0x00 => { if property_id <= 0x0b { // movie prop - let prop_name = MOVIE_PROP_NAMES.get(&(property_id as u16)).unwrap(); + let prop_name = movie_prop_names().get(&(property_id as u16)).unwrap(); GetSetUtils::set_the_built_in_prop(player, ctx, prop_name, value)?; Ok(HandlerExecutionResult::Advance) } else { @@ -303,11 +303,11 @@ impl GetSetBytecodeHandler { }; let prop_id = player.get_datum(&prop_id).int_value()?; let prop_type = player.get_ctx_current_bytecode(ctx).obj; - let max_movie_prop_id = *MOVIE_PROP_NAMES.keys().max().unwrap(); + let max_movie_prop_id = *movie_prop_names().keys().max().unwrap(); let result = if prop_type == 0 && prop_id <= max_movie_prop_id as i32 { // movie prop - let prop_name = MOVIE_PROP_NAMES.get(&(prop_id as u16)).unwrap(); + let prop_name = movie_prop_names().get(&(prop_id as u16)).unwrap(); GetSetUtils::get_the_built_in_prop(player, ctx, prop_name) } else if prop_type == 0 { // last chunk diff --git a/vm-rust/src/player/events.rs b/vm-rust/src/player/events.rs index a24334e..a2d73a5 100644 --- a/vm-rust/src/player/events.rs +++ b/vm-rust/src/player/events.rs @@ -8,7 +8,7 @@ use crate::{ }; use super::{ - cast_lib::CastMemberRef, handlers::datum_handlers::script_instance::ScriptInstanceUtils, player_call_script_handler, reserve_player_ref, script::ScriptInstanceId, script_ref::ScriptInstanceRef, DatumRef, ScriptError, ScriptErrorCode, PLAYER_EVENT_TX, PLAYER_SEMAPHONE + cast_lib::CastMemberRef, handlers::datum_handlers::script_instance::ScriptInstanceUtils, player_call_script_handler, reserve_player_ref, script::ScriptInstanceId, script_ref::ScriptInstanceRef, DatumRef, ScriptError, ScriptErrorCode, PLAYER_EVENT_TX, get_player_semaphone }; pub enum PlayerVMEvent { @@ -249,5 +249,5 @@ pub fn player_unwrap_result(result: Result) -> DatumRef { } pub async fn player_wait_available() { - PLAYER_SEMAPHONE.lock().await; + get_player_semaphone().lock().await; } diff --git a/vm-rust/src/player/keyboard.rs b/vm-rust/src/player/keyboard.rs index a035be3..c23db26 100644 --- a/vm-rust/src/player/keyboard.rs +++ b/vm-rust/src/player/keyboard.rs @@ -1,6 +1,6 @@ use log::debug; -use crate::player::keyboard_map::KEYBOARD_KEY_MAP_JS_TO_SW; +use crate::player::keyboard_map; pub struct KeyboardKey { pub key: String, @@ -19,7 +19,7 @@ impl KeyboardManager { } pub fn key_down(&mut self, key: String, code: u16) { - let code_mapped = KEYBOARD_KEY_MAP_JS_TO_SW.get(&code); + let code_mapped = keyboard_map::get_keyboard_key_map_js_to_sw().get(&code); debug!("Key down: {} {} (mapped to: {:?}", key, code, code_mapped); if !self.down_keys.iter().any(|x| x.code == code) { self.down_keys.push(KeyboardKey { diff --git a/vm-rust/src/player/keyboard_map.rs b/vm-rust/src/player/keyboard_map.rs index e836d1c..f719114 100644 --- a/vm-rust/src/player/keyboard_map.rs +++ b/vm-rust/src/player/keyboard_map.rs @@ -1,89 +1,90 @@ -use std::{collections::HashMap, iter::FromIterator}; +use std::{collections::HashMap, iter::FromIterator, sync::OnceLock}; -use lazy_static::lazy_static; - -lazy_static! { - pub static ref KEYBOARD_KEY_MAP_JS_TO_SW: HashMap = HashMap::from_iter([ - (8, 51), // backspace - (13, 36), // enter - (32, 49), // space - (65, 0), // a - (66, 11), // b - (67, 8), // c - (68, 2), // d - (69, 14), // e - (70, 3), // f - (71, 5), // g - (72, 4), // h - (73, 34), // i - (74, 38), // j - (75, 40), // k - (76, 37), // l - (77, 46), // m - (78, 45), // n - (79, 31), // o - (80, 35), // p - (81, 12), // q - (82, 15), // r - (83, 1), // s - (84, 17), // t - (85, 32), // u - (86, 9), // v - (87, 13), // w - (88, 7), // x - (89, 16), // y - (90, 6), // z - (48, 29), // 0 - (49, 18), // 1 - (50, 19), // 2 - (51, 20), // 3 - (52, 21), // 4 - (53, 23), // 5 - (54, 22), // 6 - (55, 26), // 7 - (56, 28), // 8 - (57, 25), // 9 - (37, 123), // left - (38, 126), // up - (39, 124), // right - (40, 125), // down - (16, 56), // shift - (17, 55), // ctrl - (18, 58), // alt - (27, 53), // esc - (112, 122), // f1 - (113, 120), // f2 - (114, 99), // f3 - (115, 118), // f4 - (116, 96), // f5 - (117, 97), // f6 - (118, 98), // f7 - (119, 100), // f8 - (120, 101), // f9 - (121, 109), // f10 - (122, 111), // f11 - (123, 110), // f12 - (192, 50), // ` - (189, 27), // - - (187, 24), // = - (219, 33), // [ - (221, 30), // ] - (186, 41), // ; - (222, 39), // ' - (220, 42), // \ - (188, 43), // , - (190, 47), // . - (191, 44), // / - (9, 48), // tab - (20, 57), - (97, 83), // numpad 1 - (98, 84), // numpad 2 - (99, 85), // numpad 3 - (100, 86), // numpad 4 - (101, 87), // numpad 5 - (102, 88), // numpad 6 - (103, 89), // numpad 7 - (104, 91), // numpad 8 - (105, 92), // numpad 9 - ]); +pub fn get_keyboard_key_map_js_to_sw() -> &'static HashMap { + static MAP: OnceLock> = OnceLock::new(); + MAP.get_or_init(|| { + HashMap::from_iter([ + (8, 51), // backspace + (13, 36), // enter + (32, 49), // space + (65, 0), // a + (66, 11), // b + (67, 8), // c + (68, 2), // d + (69, 14), // e + (70, 3), // f + (71, 5), // g + (72, 4), // h + (73, 34), // i + (74, 38), // j + (75, 40), // k + (76, 37), // l + (77, 46), // m + (78, 45), // n + (79, 31), // o + (80, 35), // p + (81, 12), // q + (82, 15), // r + (83, 1), // s + (84, 17), // t + (85, 32), // u + (86, 9), // v + (87, 13), // w + (88, 7), // x + (89, 16), // y + (90, 6), // z + (48, 29), // 0 + (49, 18), // 1 + (50, 19), // 2 + (51, 20), // 3 + (52, 21), // 4 + (53, 23), // 5 + (54, 22), // 6 + (55, 26), // 7 + (56, 28), // 8 + (57, 25), // 9 + (37, 123), // left + (38, 126), // up + (39, 124), // right + (40, 125), // down + (16, 56), // shift + (17, 55), // ctrl + (18, 58), // alt + (27, 53), // esc + (112, 122), // f1 + (113, 120), // f2 + (114, 99), // f3 + (115, 118), // f4 + (116, 96), // f5 + (117, 97), // f6 + (118, 98), // f7 + (119, 100), // f8 + (120, 101), // f9 + (121, 109), // f10 + (122, 111), // f11 + (123, 110), // f12 + (192, 50), // ` + (189, 27), // - + (187, 24), // = + (219, 33), // [ + (221, 30), // ] + (186, 41), // ; + (222, 39), // ' + (220, 42), // \ + (188, 43), // , + (190, 47), // . + (191, 44), // / + (9, 48), // tab + (20, 57), + (97, 83), // numpad 1 + (98, 84), // numpad 2 + (99, 85), // numpad 3 + (100, 86), // numpad 4 + (101, 87), // numpad 5 + (102, 88), // numpad 6 + (103, 89), // numpad 7 + (104, 91), // numpad 8 + (105, 92), // numpad 9 + ]) + }) } diff --git a/vm-rust/src/player/mod.rs b/vm-rust/src/player/mod.rs index d12e767..655513e 100644 --- a/vm-rust/src/player/mod.rs +++ b/vm-rust/src/player/mod.rs @@ -32,7 +32,7 @@ pub mod allocator; pub mod datum_ref; pub mod script_ref; -use std::{collections::HashMap, sync::Arc, time::Duration}; +use std::{collections::HashMap, sync::{Arc, OnceLock}, time::Duration}; use allocator::{DatumAllocator, DatumAllocatorTrait, ResetableAllocator}; use datum_ref::DatumRef; @@ -43,7 +43,6 @@ use fxhash::FxHashMap; use log::warn; use manual_future::{ManualFutureCompleter, ManualFuture}; use net_manager::NetManager; -use lazy_static::lazy_static; use profiling::{end_profiling, start_profiling}; use scope::ScopeResult; use script_ref::ScriptInstanceRef; @@ -765,9 +764,10 @@ pub async fn player_is_playing() -> bool { static mut PLAYER_TX: Option> = None; static mut PLAYER_EVENT_TX: Option> = None; pub static mut PLAYER_OPT: Option = None; -lazy_static! { - // pub static ref PLAYER_LOCK: RwLock> = RwLock::new(None); - pub static ref PLAYER_SEMAPHONE: Arc> = Arc::new(Mutex::new(())); + +pub fn get_player_semaphone() -> &'static Mutex<()> { + static MAP: OnceLock> = OnceLock::new(); + MAP.get_or_init(|| Mutex::new(())) } pub fn init_player() { diff --git a/vm-rust/src/player/profiling.rs b/vm-rust/src/player/profiling.rs index d2dba35..06a09ff 100644 --- a/vm-rust/src/player/profiling.rs +++ b/vm-rust/src/player/profiling.rs @@ -1,7 +1,6 @@ -use std::{collections::HashMap, sync::{Arc, Mutex}, time::Duration}; +use std::{collections::HashMap, sync::{Arc, Mutex, OnceLock}, time::Duration}; use fxhash::FxHashMap; use itertools::Itertools; -use lazy_static::lazy_static; pub struct ProfilingToken { name: String, @@ -77,23 +76,24 @@ impl PlayerProfiler { } } -lazy_static! { - pub static ref PROFILER: Arc> = Arc::new(Mutex::new(PlayerProfiler::new())); +fn get_profiler() -> &'static Mutex { + static MAP: OnceLock> = OnceLock::new(); + MAP.get_or_init(|| Mutex::new(PlayerProfiler::new())) } #[allow(dead_code)] pub fn start_profiling(name: String) -> u32 { - let mut profiler = PROFILER.lock().unwrap(); + let mut profiler = get_profiler().lock().unwrap(); profiler.start(name) } #[allow(dead_code)] pub fn end_profiling(id: u32) { - let mut profiler = PROFILER.lock().unwrap(); + let mut profiler = get_profiler().lock().unwrap(); profiler.end(id) } pub fn get_profiler_report() -> String { - let profiler = PROFILER.lock().unwrap(); + let profiler = get_profiler().lock().unwrap(); profiler.report() } From fd4393d19f9bf9ab40432e59bab9db3c710fb8bd Mon Sep 17 00:00:00 2001 From: ThisAccountHasBeenSuspended <176883156+ThisAccountHasBeenSuspended@users.noreply.github.com> Date: Fri, 30 Aug 2024 06:27:28 +0200 Subject: [PATCH 2/7] `get_` removed from the names of the functions with `OnceLock` --- vm-rust/src/player/events.rs | 4 ++-- vm-rust/src/player/mod.rs | 2 +- vm-rust/src/player/profiling.rs | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/vm-rust/src/player/events.rs b/vm-rust/src/player/events.rs index a2d73a5..11ebbc3 100644 --- a/vm-rust/src/player/events.rs +++ b/vm-rust/src/player/events.rs @@ -8,7 +8,7 @@ use crate::{ }; use super::{ - cast_lib::CastMemberRef, handlers::datum_handlers::script_instance::ScriptInstanceUtils, player_call_script_handler, reserve_player_ref, script::ScriptInstanceId, script_ref::ScriptInstanceRef, DatumRef, ScriptError, ScriptErrorCode, PLAYER_EVENT_TX, get_player_semaphone + cast_lib::CastMemberRef, handlers::datum_handlers::script_instance::ScriptInstanceUtils, player_call_script_handler, reserve_player_ref, script::ScriptInstanceId, script_ref::ScriptInstanceRef, DatumRef, ScriptError, ScriptErrorCode, PLAYER_EVENT_TX, player_semaphone }; pub enum PlayerVMEvent { @@ -249,5 +249,5 @@ pub fn player_unwrap_result(result: Result) -> DatumRef { } pub async fn player_wait_available() { - get_player_semaphone().lock().await; + player_semaphone().lock().await; } diff --git a/vm-rust/src/player/mod.rs b/vm-rust/src/player/mod.rs index 655513e..4ab3f6b 100644 --- a/vm-rust/src/player/mod.rs +++ b/vm-rust/src/player/mod.rs @@ -765,7 +765,7 @@ static mut PLAYER_TX: Option> = None; static mut PLAYER_EVENT_TX: Option> = None; pub static mut PLAYER_OPT: Option = None; -pub fn get_player_semaphone() -> &'static Mutex<()> { +pub fn player_semaphone() -> &'static Mutex<()> { static MAP: OnceLock> = OnceLock::new(); MAP.get_or_init(|| Mutex::new(())) } diff --git a/vm-rust/src/player/profiling.rs b/vm-rust/src/player/profiling.rs index 06a09ff..d935854 100644 --- a/vm-rust/src/player/profiling.rs +++ b/vm-rust/src/player/profiling.rs @@ -76,24 +76,24 @@ impl PlayerProfiler { } } -fn get_profiler() -> &'static Mutex { +fn profiler() -> &'static Mutex { static MAP: OnceLock> = OnceLock::new(); MAP.get_or_init(|| Mutex::new(PlayerProfiler::new())) } #[allow(dead_code)] pub fn start_profiling(name: String) -> u32 { - let mut profiler = get_profiler().lock().unwrap(); + let mut profiler = profiler().lock().unwrap(); profiler.start(name) } #[allow(dead_code)] pub fn end_profiling(id: u32) { - let mut profiler = get_profiler().lock().unwrap(); + let mut profiler = profiler().lock().unwrap(); profiler.end(id) } pub fn get_profiler_report() -> String { - let profiler = get_profiler().lock().unwrap(); + let profiler = profiler().lock().unwrap(); profiler.report() } From c2e31c479144ca3c81c8a631db4e950d5145e317 Mon Sep 17 00:00:00 2001 From: ThisAccountHasBeenSuspended <176883156+ThisAccountHasBeenSuspended@users.noreply.github.com> Date: Fri, 30 Aug 2024 08:43:49 +0200 Subject: [PATCH 3/7] General improvements 1. `String` was changed to `Box` to reduce memory usage. 2. The helper functions in `constants.rs` now return a reference instead of a copy which reduces memory usage and improves performance --- vm-rust/src/director/chunks/handler.rs | 9 +- vm-rust/src/director/lingo/constants.rs | 292 ++++++++++++------------ vm-rust/src/player/bytecode/get_set.rs | 8 +- vm-rust/src/player/mod.rs | 12 +- vm-rust/src/player/movie.rs | 8 +- 5 files changed, 166 insertions(+), 163 deletions(-) diff --git a/vm-rust/src/director/chunks/handler.rs b/vm-rust/src/director/chunks/handler.rs index e2ca025..a03a383 100644 --- a/vm-rust/src/director/chunks/handler.rs +++ b/vm-rust/src/director/chunks/handler.rs @@ -83,14 +83,17 @@ impl Bytecode { } } -pub fn get_opcode_name(id: u16) -> String { +pub fn get_opcode_name(id: u16) -> Box { let real_id = if id >= 0x40 { 0x40 + (id % 0x40) } else { id }; - let it = opcode_names().get(&OpCode::from(real_id)); - return it.unwrap_or(&"UNKOWN_BYTECODE".to_string()).to_owned() + if let Some(r) = opcode_names().get(&OpCode::from(real_id)) { + r.to_owned() + } else { + "UNKOWN_BYTECODE".into() + } } #[derive(Clone)] diff --git a/vm-rust/src/director/lingo/constants.rs b/vm-rust/src/director/lingo/constants.rs index 38d757b..05cfb39 100644 --- a/vm-rust/src/director/lingo/constants.rs +++ b/vm-rust/src/director/lingo/constants.rs @@ -2,186 +2,186 @@ use std::{collections::HashMap, sync::OnceLock}; use super::opcode::OpCode; -pub fn opcode_names() -> &'static HashMap { - static MAP: OnceLock> = OnceLock::new(); +pub fn opcode_names() -> &'static HashMap> { + static MAP: OnceLock>> = OnceLock::new(); MAP.get_or_init(|| { HashMap::from([ // single-byte - (OpCode::Ret, "ret".to_owned()), - (OpCode::RetFactory, "retfactory".to_owned()), - (OpCode::Mul, "mul".to_owned()), - (OpCode::PushZero, "pushzero".to_owned()), - (OpCode::Add, "add".to_owned()), - (OpCode::Sub, "sub".to_owned()), - (OpCode::Div, "div".to_owned()), - (OpCode::Mod, "mod".to_owned()), - (OpCode::Inv, "inv".to_owned()), - (OpCode::JoinStr, "joinstr".to_owned()), - (OpCode::JoinPadStr, "joinpadstr".to_owned()), - (OpCode::Lt, "lt".to_owned()), - (OpCode::LtEq, "lteq".to_owned()), - (OpCode::NtEq, "nteq".to_owned()), - (OpCode::Eq, "eq".to_owned()), - (OpCode::Gt, "gt".to_owned()), - (OpCode::GtEq, "gteq".to_owned()), - (OpCode::And, "and".to_owned()), - (OpCode::Or, "or".to_owned()), - (OpCode::Not, "not".to_owned()), - (OpCode::ContainsStr, "containsstr".to_owned()), - (OpCode::Contains0Str, "contains0str".to_owned()), - (OpCode::GetChunk, "getchunk".to_owned()), - (OpCode::HiliteChunk, "hilitechunk".to_owned()), - (OpCode::OntoSpr, "ontospr".to_owned()), - (OpCode::IntoSpr, "intospr".to_owned()), - (OpCode::GetField, "getfield".to_owned()), - (OpCode::StartTell, "starttell".to_owned()), - (OpCode::EndTell, "endtell".to_owned()), - (OpCode::PushList, "pushlist".to_owned()), - (OpCode::PushPropList, "pushproplist".to_owned()), - (OpCode::Swap, "swap".to_owned()), - (OpCode::CallJavaScript, "calljavascript".to_owned()), + (OpCode::Ret, "ret".into()), + (OpCode::RetFactory, "retfactory".into()), + (OpCode::Mul, "mul".into()), + (OpCode::PushZero, "pushzero".into()), + (OpCode::Add, "add".into()), + (OpCode::Sub, "sub".into()), + (OpCode::Div, "div".into()), + (OpCode::Mod, "mod".into()), + (OpCode::Inv, "inv".into()), + (OpCode::JoinStr, "joinstr".into()), + (OpCode::JoinPadStr, "joinpadstr".into()), + (OpCode::Lt, "lt".into()), + (OpCode::LtEq, "lteq".into()), + (OpCode::NtEq, "nteq".into()), + (OpCode::Eq, "eq".into()), + (OpCode::Gt, "gt".into()), + (OpCode::GtEq, "gteq".into()), + (OpCode::And, "and".into()), + (OpCode::Or, "or".into()), + (OpCode::Not, "not".into()), + (OpCode::ContainsStr, "containsstr".into()), + (OpCode::Contains0Str, "contains0str".into()), + (OpCode::GetChunk, "getchunk".into()), + (OpCode::HiliteChunk, "hilitechunk".into()), + (OpCode::OntoSpr, "ontospr".into()), + (OpCode::IntoSpr, "intospr".into()), + (OpCode::GetField, "getfield".into()), + (OpCode::StartTell, "starttell".into()), + (OpCode::EndTell, "endtell".into()), + (OpCode::PushList, "pushlist".into()), + (OpCode::PushPropList, "pushproplist".into()), + (OpCode::Swap, "swap".into()), + (OpCode::CallJavaScript, "calljavascript".into()), // multi-byte - (OpCode::PushInt8, "pushint8".to_owned()), - (OpCode::PushArgListNoRet, "pusharglistnoret".to_owned()), - (OpCode::PushArgList, "pusharglist".to_owned()), - (OpCode::PushCons, "pushcons".to_owned()), - (OpCode::PushSymb, "pushsymb".to_owned()), - (OpCode::PushVarRef, "pushvarref".to_owned()), - (OpCode::GetGlobal2, "getglobal2".to_owned()), - (OpCode::GetGlobal, "getglobal".to_owned()), - (OpCode::GetProp, "getprop".to_owned()), - (OpCode::GetParam, "getparam".to_owned()), - (OpCode::GetLocal, "getlocal".to_owned()), - (OpCode::SetGlobal2, "setglobal2".to_owned()), - (OpCode::SetGlobal, "setglobal".to_owned()), - (OpCode::SetProp, "setprop".to_owned()), - (OpCode::SetParam, "setparam".to_owned()), - (OpCode::SetLocal, "setlocal".to_owned()), - (OpCode::Jmp, "jmp".to_owned()), - (OpCode::EndRepeat, "endrepeat".to_owned()), - (OpCode::JmpIfZ, "jmpifz".to_owned()), - (OpCode::LocalCall, "localcall".to_owned()), - (OpCode::ExtCall, "extcall".to_owned()), - (OpCode::ObjCallV4, "objcallv4".to_owned()), - (OpCode::Put, "put".to_owned()), - (OpCode::PutChunk, "putchunk".to_owned()), - (OpCode::DeleteChunk, "deletechunk".to_owned()), - (OpCode::Get, "get".to_owned()), - (OpCode::Set, "set".to_owned()), - (OpCode::GetMovieProp, "getmovieprop".to_owned()), - (OpCode::SetMovieProp, "setmovieprop".to_owned()), - (OpCode::GetObjProp, "getobjprop".to_owned()), - (OpCode::SetObjProp, "setobjprop".to_owned()), - (OpCode::TellCall, "tellcall".to_owned()), - (OpCode::Peek, "peek".to_owned()), - (OpCode::Pop, "pop".to_owned()), - (OpCode::TheBuiltin, "thebuiltin".to_owned()), - (OpCode::ObjCall, "objcall".to_owned()), - (OpCode::PushChunkVarRef, "pushchunkvarref".to_owned()), - (OpCode::PushInt16, "pushint16".to_owned()), - (OpCode::PushInt32, "pushint32".to_owned()), - (OpCode::GetChainedProp, "getchainedprop".to_owned()), - (OpCode::PushFloat32, "pushfloat32".to_owned()), - (OpCode::GetTopLevelProp, "gettoplevelprop".to_owned()), - (OpCode::NewObj, "newobj".to_owned()), + (OpCode::PushInt8, "pushint8".into()), + (OpCode::PushArgListNoRet, "pusharglistnoret".into()), + (OpCode::PushArgList, "pusharglist".into()), + (OpCode::PushCons, "pushcons".into()), + (OpCode::PushSymb, "pushsymb".into()), + (OpCode::PushVarRef, "pushvarref".into()), + (OpCode::GetGlobal2, "getglobal2".into()), + (OpCode::GetGlobal, "getglobal".into()), + (OpCode::GetProp, "getprop".into()), + (OpCode::GetParam, "getparam".into()), + (OpCode::GetLocal, "getlocal".into()), + (OpCode::SetGlobal2, "setglobal2".into()), + (OpCode::SetGlobal, "setglobal".into()), + (OpCode::SetProp, "setprop".into()), + (OpCode::SetParam, "setparam".into()), + (OpCode::SetLocal, "setlocal".into()), + (OpCode::Jmp, "jmp".into()), + (OpCode::EndRepeat, "endrepeat".into()), + (OpCode::JmpIfZ, "jmpifz".into()), + (OpCode::LocalCall, "localcall".into()), + (OpCode::ExtCall, "extcall".into()), + (OpCode::ObjCallV4, "objcallv4".into()), + (OpCode::Put, "put".into()), + (OpCode::PutChunk, "putchunk".into()), + (OpCode::DeleteChunk, "deletechunk".into()), + (OpCode::Get, "get".into()), + (OpCode::Set, "set".into()), + (OpCode::GetMovieProp, "getmovieprop".into()), + (OpCode::SetMovieProp, "setmovieprop".into()), + (OpCode::GetObjProp, "getobjprop".into()), + (OpCode::SetObjProp, "setobjprop".into()), + (OpCode::TellCall, "tellcall".into()), + (OpCode::Peek, "peek".into()), + (OpCode::Pop, "pop".into()), + (OpCode::TheBuiltin, "thebuiltin".into()), + (OpCode::ObjCall, "objcall".into()), + (OpCode::PushChunkVarRef, "pushchunkvarref".into()), + (OpCode::PushInt16, "pushint16".into()), + (OpCode::PushInt32, "pushint32".into()), + (OpCode::GetChainedProp, "getchainedprop".into()), + (OpCode::PushFloat32, "pushfloat32".into()), + (OpCode::GetTopLevelProp, "gettoplevelprop".into()), + (OpCode::NewObj, "newobj".into()), ]) }) } -fn anim_prop_names() -> &'static HashMap { - static MAP: OnceLock> = OnceLock::new(); +fn anim_prop_names() -> &'static HashMap> { + static MAP: OnceLock>> = OnceLock::new(); MAP.get_or_init(|| { HashMap::from([ - (0x01, "beepOn".to_owned()), - (0x02, "buttonStyle".to_owned()), - (0x03, "centerStage".to_owned()), - (0x04, "checkBoxAccess".to_owned()), - (0x05, "checkboxType".to_owned()), - (0x06, "colorDepth".to_owned()), - (0x07, "colorQD".to_owned()), - (0x08, "exitLock".to_owned()), - (0x09, "fixStageSize".to_owned()), - (0x0a, "fullColorPermit".to_owned()), - (0x0b, "imageDirect".to_owned()), - (0x0c, "doubleClick".to_owned()), - (0x0d, "key".to_owned()), - (0x0e, "lastClick".to_owned()), - (0x0f, "lastEvent".to_owned()), - (0x10, "keyCode".to_owned()), - (0x11, "lastKey".to_owned()), - (0x12, "lastRoll".to_owned()), - (0x13, "timeoutLapsed".to_owned()), - (0x14, "multiSound".to_owned()), - (0x15, "pauseState".to_owned()), - (0x16, "quickTimePresent".to_owned()), - (0x17, "selEnd".to_owned()), - (0x18, "selStart".to_owned()), - (0x19, "soundEnabled".to_owned()), - (0x1a, "soundLevel".to_owned()), - (0x1b, "stageColor".to_owned()), + (0x01, "beepOn".into()), + (0x02, "buttonStyle".into()), + (0x03, "centerStage".into()), + (0x04, "checkBoxAccess".into()), + (0x05, "checkboxType".into()), + (0x06, "colorDepth".into()), + (0x07, "colorQD".into()), + (0x08, "exitLock".into()), + (0x09, "fixStageSize".into()), + (0x0a, "fullColorPermit".into()), + (0x0b, "imageDirect".into()), + (0x0c, "doubleClick".into()), + (0x0d, "key".into()), + (0x0e, "lastClick".into()), + (0x0f, "lastEvent".into()), + (0x10, "keyCode".into()), + (0x11, "lastKey".into()), + (0x12, "lastRoll".into()), + (0x13, "timeoutLapsed".into()), + (0x14, "multiSound".into()), + (0x15, "pauseState".into()), + (0x16, "quickTimePresent".into()), + (0x17, "selEnd".into()), + (0x18, "selStart".into()), + (0x19, "soundEnabled".into()), + (0x1a, "soundLevel".into()), + (0x1b, "stageColor".into()), // 0x1c indicates dontPassEvent was called. // It doesn't seem to have a Lingo-accessible name. - (0x1d, "switchColorDepth".to_owned()), - (0x1e, "timeoutKeyDown".to_owned()), - (0x1f, "timeoutLength".to_owned()), - (0x20, "timeoutMouse".to_owned()), - (0x21, "timeoutPlay".to_owned()), - (0x22, "timer".to_owned()), - (0x23, "preLoadRAM".to_owned()), - (0x24, "videoForWindowsPresent".to_owned()), - (0x25, "netPresent".to_owned()), - (0x26, "safePlayer".to_owned()), - (0x27, "soundKeepDevice".to_owned()), - (0x28, "soundMixMedia".to_owned()), + (0x1d, "switchColorDepth".into()), + (0x1e, "timeoutKeyDown".into()), + (0x1f, "timeoutLength".into()), + (0x20, "timeoutMouse".into()), + (0x21, "timeoutPlay".into()), + (0x22, "timer".into()), + (0x23, "preLoadRAM".into()), + (0x24, "videoForWindowsPresent".into()), + (0x25, "netPresent".into()), + (0x26, "safePlayer".into()), + (0x27, "soundKeepDevice".into()), + (0x28, "soundMixMedia".into()), ]) }) } -fn anim2_prop_names() -> &'static HashMap { - static MAP: OnceLock> = OnceLock::new(); +fn anim2_prop_names() -> &'static HashMap> { + static MAP: OnceLock>> = OnceLock::new(); MAP.get_or_init(|| { HashMap::from([ - (0x01, "perFrameHook".to_owned()), - (0x02, "number of castMembers".to_owned()), - (0x03, "number of menus".to_owned()), - (0x04, "number of castLibs".to_owned()), - (0x05, "number of xtras".to_owned()), + (0x01, "perFrameHook".into()), + (0x02, "number of castMembers".into()), + (0x03, "number of menus".into()), + (0x04, "number of castLibs".into()), + (0x05, "number of xtras".into()), ]) }) } -pub fn movie_prop_names() -> &'static HashMap { - static MAP: OnceLock> = OnceLock::new(); +pub fn movie_prop_names() -> &'static HashMap> { + static MAP: OnceLock>> = OnceLock::new(); MAP.get_or_init(|| { HashMap::from([ - (0x00, "floatPrecision".to_owned()), - (0x01, "mouseDownScript".to_owned()), - (0x02, "mouseUpScript".to_owned()), - (0x03, "keyDownScript".to_owned()), - (0x04, "keyUpScript".to_owned()), - (0x05, "timeoutScript".to_owned()), - (0x06, "short time".to_owned()), - (0x07, "abbr time".to_owned()), - (0x08, "long time".to_owned()), - (0x09, "short date".to_owned()), - (0x0a, "abbr date".to_owned()), - (0x0b, "long date".to_owned()), + (0x00, "floatPrecision".into()), + (0x01, "mouseDownScript".into()), + (0x02, "mouseUpScript".into()), + (0x03, "keyDownScript".into()), + (0x04, "keyUpScript".into()), + (0x05, "timeoutScript".into()), + (0x06, "short time".into()), + (0x07, "abbr time".into()), + (0x08, "long time".into()), + (0x09, "short date".into()), + (0x0a, "abbr date".into()), + (0x0b, "long date".into()), ]) }) } #[inline] -pub fn get_opcode_name(opcode: &OpCode) -> String { - opcode_names().get(opcode).unwrap().to_owned() +pub fn get_opcode_name(opcode: &OpCode) -> &str { + opcode_names().get(opcode).unwrap().as_ref() } #[inline] -pub fn get_anim_prop_name(name_id: u16) -> String { - anim_prop_names().get(&name_id).unwrap().to_owned() +pub fn get_anim_prop_name<'a>(name_id: u16) -> &'a str { + anim_prop_names().get(&name_id).unwrap().as_ref() } #[inline] -pub fn get_anim2_prop_name(name_id: u16) -> String { - anim2_prop_names().get(&name_id).unwrap().to_owned() +pub fn get_anim2_prop_name<'a>(name_id: u16) -> &'a str { + anim2_prop_names().get(&name_id).unwrap().as_ref() } diff --git a/vm-rust/src/player/bytecode/get_set.rs b/vm-rust/src/player/bytecode/get_set.rs index f3036f7..880bc61 100644 --- a/vm-rust/src/player/bytecode/get_set.rs +++ b/vm-rust/src/player/bytecode/get_set.rs @@ -10,9 +10,9 @@ impl GetSetUtils { pub fn get_the_built_in_prop( player: &mut DirPlayer, ctx: &BytecodeHandlerContext, - prop_name: &String, + prop_name: &str, ) -> Result { - match prop_name.as_str() { + match prop_name { "paramCount" => Ok(player.alloc_datum(Datum::Int(player.scopes.get(ctx.scope_ref).unwrap().args.len() as i32))), "result" => Ok(player.last_handler_result.clone()), _ => Ok(player.alloc_datum(player.get_movie_prop(prop_name)?)) @@ -22,10 +22,10 @@ impl GetSetUtils { pub fn set_the_built_in_prop( player: &mut DirPlayer, _ctx: &BytecodeHandlerContext, - prop_name: &String, + prop_name: &str, value: Datum, ) -> Result<(), ScriptError> { - match prop_name.as_str() { + match prop_name { _ => player.set_movie_prop(prop_name, value) } } diff --git a/vm-rust/src/player/mod.rs b/vm-rust/src/player/mod.rs index 4ab3f6b..b0b5fef 100644 --- a/vm-rust/src/player/mod.rs +++ b/vm-rust/src/player/mod.rs @@ -304,8 +304,8 @@ impl DirPlayer { return self.allocator.alloc_datum(datum).unwrap() } - fn get_movie_prop(&self, prop: &String) -> Result { - match prop.as_str() { + fn get_movie_prop(&self, prop: &str) -> Result { + match prop { "stage" => Ok(Datum::Stage), "time" => Ok(Datum::String(Local::now().format("%H:%M %p").to_string())), "milliSeconds" => Ok(Datum::Int(chrono::Local::now().signed_duration_since(self.start_time).num_milliseconds() as i32)), @@ -359,7 +359,7 @@ impl DirPlayer { fn get_anim_prop(&self, prop_id: u16) -> Result { let prop_name = get_anim_prop_name(prop_id); - match prop_name.as_str() { + match prop_name { "colorDepth" => Ok(Datum::Int(32)), "timer" => Ok(Datum::Int(get_elapsed_ticks(self.timer_tick_start))), _ => Err(ScriptError::new(format!("Unknown anim prop {}", prop_name))) @@ -368,14 +368,14 @@ impl DirPlayer { fn get_anim2_prop(&self, prop_id: u16) -> Result { let prop_name = get_anim2_prop_name(prop_id); - match prop_name.as_str() { + match prop_name { "number of castLibs" => Ok(Datum::Int(self.movie.cast_manager.casts.len() as i32)), _ => Err(ScriptError::new(format!("Unknown anim2 prop {}", prop_name))) } } - fn set_movie_prop(&mut self, prop: &String, value: Datum) -> Result<(), ScriptError> { - match prop.as_str() { + fn set_movie_prop(&mut self, prop: &str, value: Datum) -> Result<(), ScriptError> { + match prop { "keyboardFocusSprite" => { // TODO switch focus self.keyboard_focus_sprite = value.int_value()? as i16; diff --git a/vm-rust/src/player/movie.rs b/vm-rust/src/player/movie.rs index 479c1f3..59e9d71 100644 --- a/vm-rust/src/player/movie.rs +++ b/vm-rust/src/player/movie.rs @@ -47,8 +47,8 @@ impl Movie { self.file_name = file.file_name.to_string(); } - pub fn get_prop(&self, prop: &String) -> Result { - match prop.as_str() { + pub fn get_prop(&self, prop: &str) -> Result { + match prop { "alertHook" => { match self.alert_hook.to_owned() { Some(ScriptReceiver::Script(script_ref)) => Ok(Datum::ScriptRef(script_ref)), @@ -94,8 +94,8 @@ impl Movie { } } - pub fn set_prop(&mut self, prop: &String, value: Datum, datums: &DatumAllocator) -> Result<(), ScriptError> { - match prop.as_str() { + pub fn set_prop(&mut self, prop: &str, value: Datum, datums: &DatumAllocator) -> Result<(), ScriptError> { + match prop { "exitLock" => { self.exit_lock = value.int_value()? == 1; }, From 9b7881dfd2d0b729a1153ae78e813f7832d0f3b1 Mon Sep 17 00:00:00 2001 From: ThisAccountHasBeenSuspended <176883156+ThisAccountHasBeenSuspended@users.noreply.github.com> Date: Sat, 31 Aug 2024 05:53:45 +0200 Subject: [PATCH 4/7] Last changes fixed --- vm-rust/src/director/lingo/constants.rs | 86 ++++++++++++------------- vm-rust/src/player/bytecode/get_set.rs | 4 +- vm-rust/src/player/score.rs | 4 +- 3 files changed, 47 insertions(+), 47 deletions(-) diff --git a/vm-rust/src/director/lingo/constants.rs b/vm-rust/src/director/lingo/constants.rs index 1a5e3aa..bb673b3 100644 --- a/vm-rust/src/director/lingo/constants.rs +++ b/vm-rust/src/director/lingo/constants.rs @@ -175,48 +175,48 @@ pub fn sprite_prop_names() -> &'static HashMap> { static MAP: OnceLock>> = OnceLock::new(); MAP.get_or_init(|| { HashMap::from([ - (0x01, "type".to_owned()), - (0x02, "backColor".to_owned()), - (0x03, "bottom".to_owned()), - (0x04, "castNum".to_owned()), - (0x05, "constraint".to_owned()), - (0x06, "cursor".to_owned()), - (0x07, "foreColor".to_owned()), - (0x08, "height".to_owned()), - (0x09, "immediate".to_owned()), - (0x0a, "ink".to_owned()), - (0x0b, "left".to_owned()), - (0x0c, "lineSize".to_owned()), - (0x0d, "locH".to_owned()), - (0x0e, "locV".to_owned()), - (0x0f, "movieRate".to_owned()), - (0x10, "movieTime".to_owned()), - (0x11, "pattern".to_owned()), - (0x12, "puppet".to_owned()), - (0x13, "right".to_owned()), - (0x14, "startTime".to_owned()), - (0x15, "stopTime".to_owned()), - (0x16, "stretch".to_owned()), - (0x17, "top".to_owned()), - (0x18, "trails".to_owned()), - (0x19, "visible".to_owned()), - (0x1a, "volume".to_owned()), - (0x1b, "width".to_owned()), - (0x1c, "blend".to_owned()), - (0x1d, "scriptNum".to_owned()), - (0x1e, "moveableSprite".to_owned()), - (0x1f, "editableText".to_owned()), - (0x20, "scoreColor".to_owned()), - (0x21, "loc".to_owned()), - (0x22, "rect".to_owned()), - (0x23, "memberNum".to_owned()), - (0x24, "castLibNum".to_owned()), - (0x25, "scriptNum".to_owned()), - (0x26, "scriptInstanceList".to_owned()), - (0x27, "currentTime".to_owned()), - (0x28, "mostRecentCuePoint".to_owned()), - (0x29, "tweened".to_owned()), - (0x2a, "name".to_string()), + (0x01, "type".into()), + (0x02, "backColor".into()), + (0x03, "bottom".into()), + (0x04, "castNum".into()), + (0x05, "constraint".into()), + (0x06, "cursor".into()), + (0x07, "foreColor".into()), + (0x08, "height".into()), + (0x09, "immediate".into()), + (0x0a, "ink".into()), + (0x0b, "left".into()), + (0x0c, "lineSize".into()), + (0x0d, "locH".into()), + (0x0e, "locV".into()), + (0x0f, "movieRate".into()), + (0x10, "movieTime".into()), + (0x11, "pattern".into()), + (0x12, "puppet".into()), + (0x13, "right".into()), + (0x14, "startTime".into()), + (0x15, "stopTime".into()), + (0x16, "stretch".into()), + (0x17, "top".into()), + (0x18, "trails".into()), + (0x19, "visible".into()), + (0x1a, "volume".into()), + (0x1b, "width".into()), + (0x1c, "blend".into()), + (0x1d, "scriptNum".into()), + (0x1e, "moveableSprite".into()), + (0x1f, "editableText".into()), + (0x20, "scoreColor".into()), + (0x21, "loc".into()), + (0x22, "rect".into()), + (0x23, "memberNum".into()), + (0x24, "castLibNum".into()), + (0x25, "scriptNum".into()), + (0x26, "scriptInstanceList".into()), + (0x27, "currentTime".into()), + (0x28, "mostRecentCuePoint".into()), + (0x29, "tweened".into()), + (0x2a, "name".into()), ]) }) } @@ -237,5 +237,5 @@ pub fn get_anim2_prop_name<'a>(name_id: u16) -> &'a str { } pub fn get_sprite_prop_name<'a>(name_id: u16) -> &'a str { - SPRITE_PROP_NAMES.get(&name_id).unwrap().as_ref() + sprite_prop_names().get(&name_id).unwrap().as_ref() } \ No newline at end of file diff --git a/vm-rust/src/player/bytecode/get_set.rs b/vm-rust/src/player/bytecode/get_set.rs index 9614fef..03e90ff 100644 --- a/vm-rust/src/player/bytecode/get_set.rs +++ b/vm-rust/src/player/bytecode/get_set.rs @@ -331,14 +331,14 @@ impl GetSetBytecodeHandler { Ok(player.alloc_datum(Datum::String(last_chunk))) } else if prop_type == 0x06 { // sprite prop - let prop_name = sprite_prop_names.get(&(prop_id as u16)); + let prop_name = sprite_prop_names().get(&(prop_id as u16)); if prop_name.is_some() { let datum_ref = { let scope = player.scopes.get_mut(ctx.scope_ref).unwrap(); scope.stack.pop().unwrap() }; let sprite_num = player.get_datum(&datum_ref).int_value()?; - let result = sprite_get_prop(player, sprite_num as i16, &(prop_name.unwrap().into()))?; + let result = sprite_get_prop(player, sprite_num as i16, prop_name.unwrap())?; Ok(player.alloc_datum(result)) } else { Err(ScriptError::new(format!("kOpGet sprite prop {} not implemented", prop_id))) diff --git a/vm-rust/src/player/score.rs b/vm-rust/src/player/score.rs index 8477502..f126c97 100644 --- a/vm-rust/src/player/score.rs +++ b/vm-rust/src/player/score.rs @@ -261,10 +261,10 @@ pub fn borrow_sprite_mut( pub fn sprite_set_prop( sprite_id: i16, - prop_name: &String, + prop_name: &str, value: Datum, ) -> Result<(), ScriptError> { - let result = match prop_name.as_str() { + let result = match prop_name { "visible" => borrow_sprite_mut( sprite_id, |_| {}, From 8719d370ea8d87cced21e6b36ecf00683baef360 Mon Sep 17 00:00:00 2001 From: ThisAccountHasBeenSuspended <176883156+ThisAccountHasBeenSuspended@users.noreply.github.com> Date: Sat, 31 Aug 2024 09:09:01 +0200 Subject: [PATCH 5/7] Small improvements --- vm-rust/src/director/chunks/handler.rs | 33 +++++++++++++------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/vm-rust/src/director/chunks/handler.rs b/vm-rust/src/director/chunks/handler.rs index a03a383..f58476b 100644 --- a/vm-rust/src/director/chunks/handler.rs +++ b/vm-rust/src/director/chunks/handler.rs @@ -43,35 +43,35 @@ impl Bytecode { let mut writer = String::new(); writer.push_str(&Self::pos_to_str(self.pos).as_str()); - writer.push_str(" "); - writer.push_str(&opcode_name); + writer.push(' '); + writer.push_str(opcode_name); match self.opcode { OpCode::Jmp | OpCode::JmpIfZ => { - writer.push_str(" "); + writer.push(' '); writer.push_str(&Self::pos_to_str(self.pos + self.obj as usize)); } OpCode::EndRepeat => { - writer.push_str(" "); + writer.push(' '); writer.push_str(&Self::pos_to_str(self.pos - self.obj as usize)); } OpCode::ObjCall | OpCode::ExtCall | OpCode::GetObjProp | OpCode::SetObjProp | OpCode::PushSymb | OpCode::GetProp | OpCode::GetChainedProp => { let name = lctx.names.get(self.obj as usize).unwrap(); - writer.push_str(" "); + writer.push(' '); writer.push_str(name); } OpCode::SetLocal | OpCode::GetLocal => { let name_id = handler.local_name_ids.get(self.obj as usize).map(|x| *x as usize); let name = name_id.and_then(|name_id| lctx.names.get(name_id).map(|x| x.as_str())).unwrap_or("UNKOWN_LOCAL"); - writer.push_str(" "); + writer.push(' '); writer.push_str(name); } OpCode::PushFloat32 => { - writer.push_str(" "); + writer.push(' '); writer.push_str("[TODO pushfloat32]"); } _ => { if op_id > 0x40 { - writer.push_str(" "); + writer.push(' '); writer.push_str(self.obj.to_string().as_str()) } } @@ -83,16 +83,15 @@ impl Bytecode { } } -pub fn get_opcode_name(id: u16) -> Box { - let real_id = if id >= 0x40 { - 0x40 + (id % 0x40) - } else { - id - }; - if let Some(r) = opcode_names().get(&OpCode::from(real_id)) { - r.to_owned() +pub fn get_opcode_name(mut id: u16) -> &'static str { + if id >= 0x40 { + id += 0x40 + (id & 0x40); + } + + if let Some(r) = opcode_names().get(&OpCode::from(id)) { + r.as_ref() } else { - "UNKOWN_BYTECODE".into() + "UNKOWN_BYTECODE" } } From 02a0e8fcf422fe703163151e6fda03bdef0b041b Mon Sep 17 00:00:00 2001 From: ThisAccountHasBeenSuspended <176883156+ThisAccountHasBeenSuspended@users.noreply.github.com> Date: Sat, 31 Aug 2024 09:26:26 +0200 Subject: [PATCH 6/7] Lifetime changed from `'a` to `'static` & Small improvements --- vm-rust/src/director/lingo/constants.rs | 10 +++--- vm-rust/src/director/lingo/opcode.rs | 12 +++---- .../src/player/bytecode/handler_manager.rs | 36 +++++++++---------- 3 files changed, 27 insertions(+), 31 deletions(-) diff --git a/vm-rust/src/director/lingo/constants.rs b/vm-rust/src/director/lingo/constants.rs index bb673b3..78fc909 100644 --- a/vm-rust/src/director/lingo/constants.rs +++ b/vm-rust/src/director/lingo/constants.rs @@ -222,20 +222,20 @@ pub fn sprite_prop_names() -> &'static HashMap> { } #[inline] -pub fn get_opcode_name(opcode: &OpCode) -> &str { - opcode_names().get(opcode).unwrap().as_ref() +pub fn get_opcode_name(opcode: OpCode) -> &'static str { + opcode_names().get(&opcode).unwrap().as_ref() } #[inline] -pub fn get_anim_prop_name<'a>(name_id: u16) -> &'a str { +pub fn get_anim_prop_name(name_id: u16) -> &'static str { anim_prop_names().get(&name_id).unwrap().as_ref() } #[inline] -pub fn get_anim2_prop_name<'a>(name_id: u16) -> &'a str { +pub fn get_anim2_prop_name(name_id: u16) -> &'static str { anim2_prop_names().get(&name_id).unwrap().as_ref() } -pub fn get_sprite_prop_name<'a>(name_id: u16) -> &'a str { +pub fn get_sprite_prop_name(name_id: u16) -> &'static str { sprite_prop_names().get(&name_id).unwrap().as_ref() } \ No newline at end of file diff --git a/vm-rust/src/director/lingo/opcode.rs b/vm-rust/src/director/lingo/opcode.rs index 11ced5b..5060f2c 100644 --- a/vm-rust/src/director/lingo/opcode.rs +++ b/vm-rust/src/director/lingo/opcode.rs @@ -2,8 +2,8 @@ use num_derive::{FromPrimitive, ToPrimitive}; #[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq, Eq, Hash)] pub enum OpCode { - // single-byte - Invalid = 0x0, + // single-byte + Invalid = 0x0, Ret = 0x01, RetFactory = 0x02, PushZero = 0x03, @@ -84,12 +84,12 @@ pub enum OpCode { NewObj = 0x73 } -impl OpCode { - pub fn from(value: u16) -> OpCode { - if let Some(result) = num::FromPrimitive::from_u16(value) { +impl From for OpCode { + fn from(value: u16) -> Self { + if let Some(result) = num::FromPrimitive::from_u16(value) { result } else { panic!("Invalid OpCode: {}", value) } - } + } } diff --git a/vm-rust/src/player/bytecode/handler_manager.rs b/vm-rust/src/player/bytecode/handler_manager.rs index e43ae04..7412af6 100644 --- a/vm-rust/src/player/bytecode/handler_manager.rs +++ b/vm-rust/src/player/bytecode/handler_manager.rs @@ -21,7 +21,7 @@ pub struct BytecodeHandlerContext { pub struct StaticBytecodeHandlerManager {} impl StaticBytecodeHandlerManager { #[inline(always)] - pub fn call_sync_handler(opcode: &OpCode, ctx: &BytecodeHandlerContext) -> Result { + pub fn call_sync_handler(opcode: OpCode, ctx: &BytecodeHandlerContext) -> Result { match opcode { OpCode::Add => ArithmeticsBytecodeHandler::add(ctx), OpCode::PushInt8 => StackBytecodeHandler::push_int(ctx), @@ -81,14 +81,12 @@ impl StaticBytecodeHandlerManager { OpCode::PushChunkVarRef => StackBytecodeHandler::push_chunk_var_ref(ctx), OpCode::DeleteChunk => StringBytecodeHandler::delete_chunk(ctx), OpCode::GetTopLevelProp => GetSetBytecodeHandler::get_top_level_prop(ctx), - _ => Err(ScriptError::new( - format_args!( - "No handler for opcode {} ({:#04x})", - get_opcode_name(&opcode), - num::ToPrimitive::to_u16(opcode).unwrap() - ) - .to_string(), - )), + _ => { + let prim = num::ToPrimitive::to_u16(&opcode).unwrap(); + let name = get_opcode_name(opcode); + let fmt = format!("No handler for opcode {name} ({prim:#04x})"); + Err(ScriptError::new(fmt)) + }, } } @@ -105,21 +103,19 @@ impl StaticBytecodeHandlerManager { } #[inline(always)] - pub async fn call_async_handler(opcode: &OpCode, ctx: &BytecodeHandlerContext) -> Result { + pub async fn call_async_handler(opcode: OpCode, ctx: &BytecodeHandlerContext) -> Result { match opcode { OpCode::NewObj => StackBytecodeHandler::new_obj(&ctx).await, OpCode::ExtCall => FlowControlBytecodeHandler::ext_call(&ctx).await, OpCode::ObjCall => FlowControlBytecodeHandler::obj_call(&ctx).await, OpCode::LocalCall => FlowControlBytecodeHandler::local_call(&ctx).await, OpCode::SetObjProp => GetSetBytecodeHandler::set_obj_prop(&ctx).await, - _ => Err(ScriptError::new( - format_args!( - "No handler for opcode {} ({:#04x})", - get_opcode_name(&opcode), - num::ToPrimitive::to_u16(opcode).unwrap() - ) - .to_string(), - )), + _ => { + let prim = num::ToPrimitive::to_u16(&opcode).unwrap(); + let name = get_opcode_name(opcode); + let fmt = format!("No handler for opcode {name} ({prim:#04x})"); + Err(ScriptError::new(fmt)) + }, } } } @@ -140,8 +136,8 @@ pub async fn player_execute_bytecode<'a>( }; if StaticBytecodeHandlerManager::has_async_handler(&opcode) { - StaticBytecodeHandlerManager::call_async_handler(&opcode, ctx).await + StaticBytecodeHandlerManager::call_async_handler(opcode, ctx).await } else { - StaticBytecodeHandlerManager::call_sync_handler(&opcode, ctx) + StaticBytecodeHandlerManager::call_sync_handler(opcode, ctx) } } From b2217956e905b6bd4af3037f86ff3a533bcd11df Mon Sep 17 00:00:00 2001 From: ThisAccountHasBeenSuspended <176883156+ThisAccountHasBeenSuspended@users.noreply.github.com> Date: Sat, 31 Aug 2024 09:38:16 +0200 Subject: [PATCH 7/7] Fixed a mistake --- vm-rust/src/director/chunks/handler.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm-rust/src/director/chunks/handler.rs b/vm-rust/src/director/chunks/handler.rs index f58476b..ec316b3 100644 --- a/vm-rust/src/director/chunks/handler.rs +++ b/vm-rust/src/director/chunks/handler.rs @@ -85,7 +85,7 @@ impl Bytecode { pub fn get_opcode_name(mut id: u16) -> &'static str { if id >= 0x40 { - id += 0x40 + (id & 0x40); + id = 0x40 + (id % 0x40); } if let Some(r) = opcode_names().get(&OpCode::from(id)) {