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] 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; },