From af1f9f5d8910f3020bb7ea17eecbfa27d9bcf8e8 Mon Sep 17 00:00:00 2001 From: dawnDus <96957561+dawndus@users.noreply.github.com> Date: Fri, 21 Jan 2022 11:31:25 -0500 Subject: [PATCH 1/3] Loading counter --- src/components/nikumaru.rs | 42 +++++++++++++++++++++++++++++++++++++- src/scene/title_scene.rs | 8 ++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/components/nikumaru.rs b/src/components/nikumaru.rs index fcd7e83..f6bf39c 100644 --- a/src/components/nikumaru.rs +++ b/src/components/nikumaru.rs @@ -1,9 +1,12 @@ +use byteorder::{ReadBytesExt, LE}; + use crate::common::Rect; -use crate::components::draw_common::{Alignment, draw_number, draw_number_zeros}; +use crate::components::draw_common::{draw_number, draw_number_zeros, Alignment}; use crate::entity::GameEntity; use crate::frame::Frame; use crate::framework::context::Context; use crate::framework::error::GameResult; +use crate::framework::filesystem; use crate::player::Player; use crate::shared_game_state::{SharedGameState, TimingMode}; @@ -17,6 +20,43 @@ impl NikumaruCounter { pub fn new() -> NikumaruCounter { NikumaruCounter { tick: 0, shown: false } } + + fn load_saved_time(&mut self, ctx: &mut Context) -> GameResult { + if let Ok(mut data) = filesystem::user_open(ctx, "/290.rec") { + let mut ticks: [u32; 4] = [0, 0, 0, 0]; + + for iter in 0..=3 { + ticks[iter] = data.read_u32::()?; + } + + let random = data.read_u32::()?; + let random_list: [u8; 4] = random.to_le_bytes(); + + for iter in 0..=3 { + ticks[iter] = u32::from_le_bytes([ + ticks[iter].to_le_bytes()[0] - random_list[iter], + ticks[iter].to_le_bytes()[1] - random_list[iter], + ticks[iter].to_le_bytes()[2] - random_list[iter], + ticks[iter].to_le_bytes()[3] - random_list[iter] / 2, + ]); + } + + if ticks[0] == ticks[1] && ticks[0] == ticks[2] { + return Ok(ticks[0]); + } + } else { + log::warn!("Cannot open 290.rec."); + } + Ok(0) + } + + pub fn load_counter(&mut self, ctx: &mut Context) -> GameResult { + self.tick = self.load_saved_time(ctx)? as usize; + if self.tick > 0 { + self.shown = true; + } + Ok(()) + } } impl GameEntity<&Player> for NikumaruCounter { diff --git a/src/scene/title_scene.rs b/src/scene/title_scene.rs index 7f89e7f..3bda25c 100644 --- a/src/scene/title_scene.rs +++ b/src/scene/title_scene.rs @@ -1,5 +1,7 @@ use crate::common::{Color, VERSION_BANNER}; use crate::components::background::Background; +use crate::components::nikumaru::NikumaruCounter; +use crate::entity::GameEntity; use crate::frame::Frame; use crate::framework::context::Context; use crate::framework::error::GameResult; @@ -34,6 +36,7 @@ pub struct TitleScene { save_select_menu: Menu, background: Background, frame: Frame, + nikumaru_rec: NikumaruCounter, stage: Stage, textures: StageTexturePaths, } @@ -67,6 +70,7 @@ impl TitleScene { save_select_menu: Menu::new(0, 0, 200, 0), background: Background::new(), frame: Frame::new(), + nikumaru_rec: NikumaruCounter::new(), stage: fake_stage, textures, } @@ -117,6 +121,8 @@ impl Scene for TitleScene { self.controller.update(state, ctx)?; self.controller.update_trigger(); + self.nikumaru_rec.load_counter(ctx)?; + Ok(()) } @@ -211,6 +217,8 @@ impl Scene for TitleScene { self.draw_text_centered(&VERSION_BANNER, state.canvas_size.1 - 15.0, state, ctx)?; self.draw_text_centered(COPYRIGHT_PIXEL, state.canvas_size.1 - 30.0, state, ctx)?; + self.nikumaru_rec.draw(state, ctx, &self.frame)?; + match self.current_menu { CurrentMenu::MainMenu => self.main_menu.draw(state, ctx)?, CurrentMenu::OptionMenu => self.option_menu.draw(state, ctx)?, From eadeedae6ba555fec8723be6a8b9a09acc5b6299 Mon Sep 17 00:00:00 2001 From: dawnDus <96957561+dawndus@users.noreply.github.com> Date: Fri, 21 Jan 2022 16:40:37 -0500 Subject: [PATCH 2/3] STC command --- src/components/nikumaru.rs | 53 ++++++++++++++++++++++++++------ src/scripting/tsc/text_script.rs | 20 +++++++++--- 2 files changed, 60 insertions(+), 13 deletions(-) diff --git a/src/components/nikumaru.rs b/src/components/nikumaru.rs index f6bf39c..31418e6 100644 --- a/src/components/nikumaru.rs +++ b/src/components/nikumaru.rs @@ -1,4 +1,4 @@ -use byteorder::{ReadBytesExt, LE}; +use byteorder::{ReadBytesExt, WriteBytesExt, LE}; use crate::common::Rect; use crate::components::draw_common::{draw_number, draw_number_zeros, Alignment}; @@ -7,7 +7,9 @@ use crate::frame::Frame; use crate::framework::context::Context; use crate::framework::error::GameResult; use crate::framework::filesystem; +use crate::framework::vfs::OpenOptions; use crate::player::Player; +use crate::rng::RNG; use crate::shared_game_state::{SharedGameState, TimingMode}; #[derive(Clone, Copy)] @@ -21,9 +23,9 @@ impl NikumaruCounter { NikumaruCounter { tick: 0, shown: false } } - fn load_saved_time(&mut self, ctx: &mut Context) -> GameResult { + fn load_time(&mut self, ctx: &mut Context) -> GameResult { if let Ok(mut data) = filesystem::user_open(ctx, "/290.rec") { - let mut ticks: [u32; 4] = [0, 0, 0, 0]; + let mut ticks: [u32; 4] = [0; 4]; for iter in 0..=3 { ticks[iter] = data.read_u32::()?; @@ -34,10 +36,10 @@ impl NikumaruCounter { for iter in 0..=3 { ticks[iter] = u32::from_le_bytes([ - ticks[iter].to_le_bytes()[0] - random_list[iter], - ticks[iter].to_le_bytes()[1] - random_list[iter], - ticks[iter].to_le_bytes()[2] - random_list[iter], - ticks[iter].to_le_bytes()[3] - random_list[iter] / 2, + ticks[iter].to_le_bytes()[0].wrapping_sub(random_list[iter]), + ticks[iter].to_le_bytes()[1].wrapping_sub(random_list[iter]), + ticks[iter].to_le_bytes()[2].wrapping_sub(random_list[iter]), + ticks[iter].to_le_bytes()[3].wrapping_sub(random_list[iter] / 2), ]); } @@ -45,18 +47,51 @@ impl NikumaruCounter { return Ok(ticks[0]); } } else { - log::warn!("Cannot open 290.rec."); + log::warn!("Failed to open 290 record."); } Ok(0) } + fn save_time(&mut self, new_time: u32, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { + if let Ok(mut data) = filesystem::open_options(ctx, "/290.rec", OpenOptions::new().write(true).create(true)) { + let mut ticks: [u32; 4] = [new_time; 4]; + let mut random_list: [u8; 4] = [0; 4]; + + for iter in 0..=3 { + random_list[iter] = state.game_rng.range(0..250) as u8 + iter as u8; + + ticks[iter] = u32::from_le_bytes([ + ticks[iter].to_le_bytes()[0].wrapping_add(random_list[iter]), + ticks[iter].to_le_bytes()[1].wrapping_add(random_list[iter]), + ticks[iter].to_le_bytes()[2].wrapping_add(random_list[iter]), + ticks[iter].to_le_bytes()[3].wrapping_add(random_list[iter] / 2), + ]); + + data.write_u32::(ticks[iter])?; + } + + data.write_u32::(u32::from_le_bytes(random_list))?; + } else { + log::warn!("Failed to write 290 record."); + } + Ok(()) + } + pub fn load_counter(&mut self, ctx: &mut Context) -> GameResult { - self.tick = self.load_saved_time(ctx)? as usize; + self.tick = self.load_time(ctx)? as usize; if self.tick > 0 { self.shown = true; } Ok(()) } + + pub fn save_counter(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { + let old_record = self.load_time(ctx)? as usize; + if self.tick < old_record || old_record == 0 { + self.save_time(self.tick as u32, state, ctx)?; + } + Ok(()) + } } impl GameEntity<&Player> for NikumaruCounter { diff --git a/src/scripting/tsc/text_script.rs b/src/scripting/tsc/text_script.rs index af0fb95..a585def 100644 --- a/src/scripting/tsc/text_script.rs +++ b/src/scripting/tsc/text_script.rs @@ -11,8 +11,8 @@ use std::rc::Rc; use num_traits::{clamp, FromPrimitive}; use crate::bitfield; -use crate::common::{Direction, FadeDirection, FadeState, Rect}; use crate::common::Direction::{Left, Right}; +use crate::common::{Direction, FadeDirection, FadeState, Rect}; use crate::engine_constants::EngineConstants; use crate::entity::GameEntity; use crate::frame::UpdateTarget; @@ -396,7 +396,13 @@ impl TextScriptVM { state.textscript_vm.state = if !new_line { TextScriptExecutionState::Msg(event, cursor.position() as u32, remaining - 1, ticks) } else { - TextScriptExecutionState::MsgNewLine(event, cursor.position() as u32, remaining - 1, ticks, 4) + TextScriptExecutionState::MsgNewLine( + event, + cursor.position() as u32, + remaining - 1, + ticks, + 4, + ) }; } else { state.textscript_vm.state = @@ -419,7 +425,8 @@ impl TextScriptVM { state.textscript_vm.line_2.append(&mut state.textscript_vm.line_3); state.textscript_vm.state = TextScriptExecutionState::Msg(event, ip, remaining, ticks); } else { - state.textscript_vm.state = TextScriptExecutionState::MsgNewLine(event, ip, remaining, ticks, counter); + state.textscript_vm.state = + TextScriptExecutionState::MsgNewLine(event, ip, remaining, ticks, counter); } break; } @@ -1650,9 +1657,14 @@ impl TextScriptVM { mode != 0, ); } + TSCOpCode::STC => { + game_scene.nikumaru.save_counter(state, ctx)?; + + exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32); + } // unimplemented opcodes // Zero operands - TSCOpCode::KE2 | TSCOpCode::MLP | TSCOpCode::FR2 | TSCOpCode::STC | TSCOpCode::HM2 => { + TSCOpCode::KE2 | TSCOpCode::MLP | TSCOpCode::FR2 | TSCOpCode::HM2 => { log::warn!("unimplemented opcode: {:?}", op); exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32); From 203bacb1a0c72e1f564f47d09a3bb0c01aa4a40f Mon Sep 17 00:00:00 2001 From: dawnDus <96957561+dawndus@users.noreply.github.com> Date: Fri, 21 Jan 2022 16:41:40 -0500 Subject: [PATCH 3/3] reset cutscene skip speed in main menu --- src/menu/pause_menu.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/menu/pause_menu.rs b/src/menu/pause_menu.rs index 1eef834..ed39c0f 100644 --- a/src/menu/pause_menu.rs +++ b/src/menu/pause_menu.rs @@ -103,6 +103,7 @@ impl PauseMenu { self.current_menu = CurrentMenu::OptionsMenu; } MenuSelectionResult::Selected(3, _) => { + state.textscript_vm.flags.set_cutscene_skip(false); state.next_scene = Some(Box::new(TitleScene::new())); } MenuSelectionResult::Selected(5, _) => {