mirror of
https://github.com/Zenithsiz/dcb.git
synced 2026-02-03 16:16:33 +00:00
Documented and renamed most commands.
This commit is contained in:
parent
6293b937c2
commit
166e31f499
@ -4,121 +4,187 @@
|
||||
//!
|
||||
//! The first word of the instruction is the mnemonic, with the words following being data.
|
||||
|
||||
// Imports
|
||||
use crate::ComboBox;
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use std::assert_matches::assert_matches;
|
||||
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
|
||||
use crate::ComboBox;
|
||||
|
||||
|
||||
/// Command
|
||||
// TODO: Merge common commands
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
pub enum Command<'a> {
|
||||
/// Display buffer
|
||||
DisplayBuffer,
|
||||
/// Displays the text buffer in the text box.
|
||||
///
|
||||
/// Displays the text in the text buffer and scrolls to the next line.
|
||||
/// If the text box is full, waits for input until displaying the next line.
|
||||
DisplayTextBuffer,
|
||||
|
||||
/// Wait for input
|
||||
/// Wait for input from the user.
|
||||
///
|
||||
/// Pauses execution until the users sends input.
|
||||
WaitInput,
|
||||
|
||||
/// Clear screen
|
||||
ClearScreen,
|
||||
/// Empty text box
|
||||
///
|
||||
/// Empties the text box, removing all characters and setting
|
||||
/// the cursor to the first line.
|
||||
EmptyTextBox,
|
||||
|
||||
/// Finish combo box
|
||||
FinishComboBox,
|
||||
/// Sets the background to the battle cafe
|
||||
SetBgBattleCafe,
|
||||
|
||||
DisplayBattleCafe,
|
||||
DisplayPlayerRoom,
|
||||
DisplayCardList,
|
||||
DisplayChoosePartner,
|
||||
DisplayBattleArena,
|
||||
DisplayKeyboard,
|
||||
DisplayEditPartner,
|
||||
DisplayTextBox,
|
||||
/// Sets the background to the battle arena
|
||||
// TODO: Check what texture it uses, looks all messed up most of the times.
|
||||
SetBgBattleArena,
|
||||
|
||||
/// Set value
|
||||
SetValue {
|
||||
var: u16,
|
||||
op: u32,
|
||||
value1: u32,
|
||||
/// Opens the player room
|
||||
OpenPlayerRoom,
|
||||
|
||||
/// Opens the card list
|
||||
OpenCardList,
|
||||
|
||||
/// Opens the partner chooser screen
|
||||
// TODO: Figure out parameters for this, they're all veemon
|
||||
OpenChoosePartner,
|
||||
|
||||
/// Opens the keyboard
|
||||
// TODO: Check where the text goes
|
||||
OpenKeyboard,
|
||||
|
||||
/// Opens the partner edit screen
|
||||
OpenEditPartner,
|
||||
|
||||
/// Opens the center text box
|
||||
// TODO: Rename, somewhat confusing
|
||||
DisplayCenterTextBox,
|
||||
|
||||
/// Changes a variable value
|
||||
///
|
||||
/// Depending on `op`, either sets or adds `value` to the `var` variable
|
||||
// TODO: Make `op` an enum
|
||||
ChangeVar {
|
||||
/// Variable
|
||||
var: u16,
|
||||
|
||||
/// Operation
|
||||
op: u32,
|
||||
|
||||
/// Value
|
||||
value: u32,
|
||||
},
|
||||
|
||||
/// Reset
|
||||
Reset,
|
||||
|
||||
/// Test
|
||||
/// Tests if a variable has a value
|
||||
///
|
||||
/// Depending on `op`, either checks if `var` is equal to, or less than `value`
|
||||
// TODO: Confirm less than
|
||||
// TODO: Explain that it skips the next instruction if false, maybe rename to `exec_if` or something
|
||||
Test {
|
||||
var: u16,
|
||||
value1: u32,
|
||||
value2: u32,
|
||||
/// Variable
|
||||
var: u16,
|
||||
|
||||
/// Operation
|
||||
op: u32,
|
||||
|
||||
/// Value
|
||||
value: u32,
|
||||
},
|
||||
|
||||
/// Jump
|
||||
/// Jumps to `addr`
|
||||
// TODO: Figure out `var`, seems to somewhat coincide with the label number, but that would be weird
|
||||
Jump {
|
||||
var: u16,
|
||||
/// Unknown
|
||||
var: u16,
|
||||
|
||||
/// Address to jump to
|
||||
addr: u32,
|
||||
},
|
||||
|
||||
/// Unknown 0a
|
||||
/// Unknown `0a`.
|
||||
// TODO:
|
||||
Unknown0a {
|
||||
/// Unknown
|
||||
value: u16,
|
||||
},
|
||||
|
||||
/// Open combo box
|
||||
/// Opens a combo box
|
||||
OpenComboBox {
|
||||
/// The combo box being opened
|
||||
combo_box: ComboBox,
|
||||
},
|
||||
|
||||
/// Add combo box option
|
||||
AddComboBoxOption {
|
||||
/// Adds a combo box button
|
||||
AddComboBoxButton {
|
||||
/// The button value
|
||||
value: u16,
|
||||
},
|
||||
|
||||
/// Awaits the user's selection on the combo box
|
||||
ComboBoxAwait,
|
||||
|
||||
/// Display scene
|
||||
// TODO: Figure out
|
||||
DisplayScene {
|
||||
/// Unknown
|
||||
value0: u8,
|
||||
|
||||
/// Unknown
|
||||
value1: u16,
|
||||
},
|
||||
|
||||
/// Set buffer
|
||||
/// Sets buffer `buffer` to `bytes`.
|
||||
///
|
||||
/// The following are the known buffers:
|
||||
/// - 0x4: Text buffer
|
||||
// TODO: Have `buffer` be an enum of the buffers and move the explanation there
|
||||
SetBuffer {
|
||||
kind: u8,
|
||||
/// The buffer to set
|
||||
buffer: u8,
|
||||
|
||||
/// The bytes to set
|
||||
bytes: &'a [u8],
|
||||
},
|
||||
|
||||
/// Set brightness
|
||||
/// Sets the brightness of `place` to `brightness`.
|
||||
// TODO: Figure out the rest
|
||||
SetBrightness {
|
||||
kind: u8,
|
||||
place: u16,
|
||||
/// Unknown
|
||||
kind: u8,
|
||||
|
||||
/// Place
|
||||
place: u16,
|
||||
|
||||
/// Brightness
|
||||
brightness: u16,
|
||||
value: u16,
|
||||
|
||||
/// Unknown
|
||||
value: u16,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'a> Command<'a> {
|
||||
/// Parses a command
|
||||
/// Parses a command from a slice of bytes.
|
||||
///
|
||||
/// Ignores everything after the command.
|
||||
#[must_use]
|
||||
#[allow(clippy::too_many_lines)] // TODO: Simplify
|
||||
pub fn parse(slice: &'a [u8]) -> Option<Self> {
|
||||
let command = match *slice.get(..0x4)? {
|
||||
[0x0a, 0x0, 0x01, 0x0] => Self::FinishComboBox,
|
||||
[0x0a, 0x0, 0x02, 0x0] => Self::DisplayBattleCafe,
|
||||
[0x0a, 0x0, 0x04, 0x0] => Self::DisplayBuffer,
|
||||
[0x0a, 0x0, 0x01, 0x0] => Self::ComboBoxAwait,
|
||||
[0x0a, 0x0, 0x02, 0x0] => Self::SetBgBattleCafe,
|
||||
[0x0a, 0x0, 0x04, 0x0] => Self::DisplayTextBuffer,
|
||||
[0x0a, 0x0, 0x05, 0x0] => Self::WaitInput,
|
||||
[0x0a, 0x0, 0x06, 0x0] => Self::ClearScreen,
|
||||
[0x0a, 0x0, 0x07, 0x0] => Self::DisplayPlayerRoom,
|
||||
[0x0a, 0x0, 0x09, 0x0] => Self::DisplayCardList,
|
||||
[0x0a, 0x0, 0x0a, 0x0] => Self::DisplayChoosePartner,
|
||||
[0x0a, 0x0, 0x0c, 0x0] => Self::DisplayBattleArena,
|
||||
[0x0a, 0x0, 0x0f, 0x0] => Self::DisplayKeyboard,
|
||||
[0x0a, 0x0, 0x11, 0x0] => Self::DisplayEditPartner,
|
||||
[0x0a, 0x0, 0x16, 0x0] => Self::DisplayTextBox,
|
||||
[0x0a, 0x0, 0x06, 0x0] => Self::EmptyTextBox,
|
||||
[0x0a, 0x0, 0x07, 0x0] => Self::OpenPlayerRoom,
|
||||
[0x0a, 0x0, 0x09, 0x0] => Self::OpenCardList,
|
||||
[0x0a, 0x0, 0x0a, 0x0] => Self::OpenChoosePartner,
|
||||
[0x0a, 0x0, 0x0c, 0x0] => Self::SetBgBattleArena,
|
||||
[0x0a, 0x0, 0x0f, 0x0] => Self::OpenKeyboard,
|
||||
[0x0a, 0x0, 0x11, 0x0] => Self::OpenEditPartner,
|
||||
[0x0a, 0x0, 0x16, 0x0] => Self::DisplayCenterTextBox,
|
||||
[0x0a, 0x0, value0, value1] => Self::Unknown0a {
|
||||
value: LittleEndian::read_u16(&[value0, value1]),
|
||||
},
|
||||
|
||||
// Reset
|
||||
// Maybe var = `0x0` is the program counter?
|
||||
// Played around with this idea, but couldn't jump anywhere other than 0 even with dividing positions by 4
|
||||
[0x07, 0x0, 0x0, 0x0] if slice.get(0x4..0xc)? == [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0] => Self::Reset,
|
||||
|
||||
// Set variable
|
||||
[0x07, 0x0, var0, var1] => {
|
||||
let var = LittleEndian::read_u16(&[var0, var1]);
|
||||
@ -131,7 +197,7 @@ impl<'a> Command<'a> {
|
||||
|
||||
assert_matches!(op, 0 | 1 | 6, "Unknown set_value operation");
|
||||
|
||||
Self::SetValue { var, op, value1 }
|
||||
Self::ChangeVar { var, op, value: value1 }
|
||||
},
|
||||
|
||||
// Test
|
||||
@ -142,7 +208,11 @@ impl<'a> Command<'a> {
|
||||
|
||||
assert_matches!(value1, 3 | 5, "Unknown test value1");
|
||||
|
||||
Self::Test { var, value1, value2 }
|
||||
Self::Test {
|
||||
var,
|
||||
op: value1,
|
||||
value: value2,
|
||||
}
|
||||
},
|
||||
|
||||
// Jump?
|
||||
@ -175,7 +245,7 @@ impl<'a> Command<'a> {
|
||||
}
|
||||
let value = LittleEndian::read_u16(slice.get(0x6..0x8)?);
|
||||
|
||||
Self::AddComboBoxOption { value }
|
||||
Self::AddComboBoxButton { value }
|
||||
},
|
||||
// Display scene?
|
||||
[0x0b, 0x0, value0, 0x0] => {
|
||||
@ -209,8 +279,8 @@ impl<'a> Command<'a> {
|
||||
}
|
||||
|
||||
Self::SetBuffer {
|
||||
kind,
|
||||
bytes: &bytes[..(len - 1)],
|
||||
buffer: kind,
|
||||
bytes: &bytes[..(len - 1)],
|
||||
}
|
||||
},
|
||||
|
||||
@ -244,27 +314,29 @@ impl<'a> Command<'a> {
|
||||
}
|
||||
|
||||
/// Returns this command's size
|
||||
pub fn size(&self) -> usize {
|
||||
#[must_use]
|
||||
pub const fn size(&self) -> usize {
|
||||
// TODO: Combine them
|
||||
#[allow(clippy::match_same_arms)] // We want to explicitly not combine them for now
|
||||
match self {
|
||||
Command::DisplayBuffer => 4,
|
||||
Command::DisplayTextBuffer => 4,
|
||||
Command::WaitInput => 4,
|
||||
Command::ClearScreen => 4,
|
||||
Command::FinishComboBox => 4,
|
||||
Command::DisplayBattleCafe => 4,
|
||||
Command::DisplayPlayerRoom => 4,
|
||||
Command::DisplayCardList => 4,
|
||||
Command::DisplayChoosePartner => 4,
|
||||
Command::DisplayBattleArena => 4,
|
||||
Command::DisplayKeyboard => 4,
|
||||
Command::DisplayEditPartner => 4,
|
||||
Command::DisplayTextBox => 4,
|
||||
Command::SetValue { .. } => 0xc,
|
||||
Command::Reset => 0xc,
|
||||
Command::EmptyTextBox => 4,
|
||||
Command::ComboBoxAwait => 4,
|
||||
Command::SetBgBattleCafe => 4,
|
||||
Command::OpenPlayerRoom => 4,
|
||||
Command::OpenCardList => 4,
|
||||
Command::OpenChoosePartner => 4,
|
||||
Command::SetBgBattleArena => 4,
|
||||
Command::OpenKeyboard => 4,
|
||||
Command::OpenEditPartner => 4,
|
||||
Command::DisplayCenterTextBox => 4,
|
||||
Command::ChangeVar { .. } => 0xc,
|
||||
Command::Test { .. } => 0xc,
|
||||
Command::Jump { .. } => 8,
|
||||
Command::Unknown0a { .. } => 4,
|
||||
Command::OpenComboBox { .. } => 8,
|
||||
Command::AddComboBoxOption { .. } => 8,
|
||||
Command::AddComboBoxButton { .. } => 8,
|
||||
Command::DisplayScene { .. } => 8,
|
||||
Command::SetBuffer { bytes, .. } => {
|
||||
let len = bytes.len() + 2;
|
||||
|
||||
@ -293,18 +293,18 @@ impl State {
|
||||
&mut self, labels: &HashMap<u32, String>, values: &HashMap<u16, String>, command: Command,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
match (&mut *self, command) {
|
||||
(State::Start, Command::DisplayBuffer) => println!("display_buffer"),
|
||||
(State::Start, Command::DisplayTextBuffer) => println!("display_buffer"),
|
||||
(State::Start, Command::WaitInput) => println!("wait_input"),
|
||||
(State::Start, Command::ClearScreen) => println!("clear_screen"),
|
||||
(State::Start, Command::DisplayBattleCafe) => println!("display_battle_cafe"),
|
||||
(State::Start, Command::DisplayPlayerRoom) => println!("display_player_room"),
|
||||
(State::Start, Command::DisplayCardList) => println!("display_card_list"),
|
||||
(State::Start, Command::DisplayChoosePartner) => println!("display_choose_partner"),
|
||||
(State::Start, Command::DisplayBattleArena) => println!("display_battle_arena"),
|
||||
(State::Start, Command::DisplayKeyboard) => println!("display_keyboard"),
|
||||
(State::Start, Command::DisplayEditPartner) => println!("display_edit_partner"),
|
||||
(State::Start, Command::DisplayTextBox) => println!("display_text_box"),
|
||||
(State::Start, Command::SetValue { var, op, value1 }) => {
|
||||
(State::Start, Command::EmptyTextBox) => println!("clear_screen"),
|
||||
(State::Start, Command::SetBgBattleCafe) => println!("display_battle_cafe"),
|
||||
(State::Start, Command::OpenPlayerRoom) => println!("display_player_room"),
|
||||
(State::Start, Command::OpenCardList) => println!("display_card_list"),
|
||||
(State::Start, Command::OpenChoosePartner) => println!("display_choose_partner"),
|
||||
(State::Start, Command::SetBgBattleArena) => println!("display_battle_arena"),
|
||||
(State::Start, Command::OpenKeyboard) => println!("display_keyboard"),
|
||||
(State::Start, Command::OpenEditPartner) => println!("display_edit_partner"),
|
||||
(State::Start, Command::DisplayCenterTextBox) => println!("display_text_box"),
|
||||
(State::Start, Command::ChangeVar { var, op, value: value1 }) => {
|
||||
let value = match values.get(&var) {
|
||||
Some(value) => value.to_owned(),
|
||||
None => format!("{var:#x}"),
|
||||
@ -319,7 +319,14 @@ impl State {
|
||||
|
||||
println!("set_value {value}, {op}, {value1:#x}");
|
||||
},
|
||||
(State::Start, Command::Test { var, value1, value2 }) => match values.get(&var) {
|
||||
(
|
||||
State::Start,
|
||||
Command::Test {
|
||||
var,
|
||||
op: value1,
|
||||
value: value2,
|
||||
},
|
||||
) => match values.get(&var) {
|
||||
Some(value) => println!("test {value}, {value1:#x}, {value2:#x}"),
|
||||
None => println!("test {var:#x}, {value1:#x}, {value2:#x}"),
|
||||
},
|
||||
@ -332,7 +339,6 @@ impl State {
|
||||
|
||||
println!("jump {var:#x}, {label}")
|
||||
},
|
||||
(State::Start, Command::Reset) => println!("reset"),
|
||||
(State::Start, Command::Unknown0a { value }) => println!("unknown_0a {value:#x}"),
|
||||
(State::Start, Command::OpenComboBox { combo_box: menu }) => {
|
||||
*self = State::Menu { menu, buttons: vec![] };
|
||||
@ -343,7 +349,7 @@ impl State {
|
||||
|
||||
_ => println!("display_scene {value0:#x}, {value1:#x}"),
|
||||
},
|
||||
(State::Start, Command::SetBuffer { kind, bytes }) => {
|
||||
(State::Start, Command::SetBuffer { buffer: kind, bytes }) => {
|
||||
let s = SHIFT_JIS
|
||||
.decode_without_bom_handling_and_without_replacement(bytes)
|
||||
.context("Unable to parse text buffer as utf-8")?;
|
||||
@ -367,19 +373,19 @@ impl State {
|
||||
(0x1, _, 0xffff, 0xffff) => println!("set_light_unknown {place:#x}"),
|
||||
_ => println!("set_light {kind:#x}, {place:#x}, {brightness:#x}, {value:#x}"),
|
||||
},
|
||||
(State::Menu { .. }, Command::FinishComboBox) => {
|
||||
(State::Menu { .. }, Command::ComboBoxAwait) => {
|
||||
*self = State::Start;
|
||||
println!("finish_menu");
|
||||
},
|
||||
(State::Menu { menu, buttons }, Command::AddComboBoxOption { value }) => {
|
||||
(State::Menu { menu, buttons }, Command::AddComboBoxButton { value }) => {
|
||||
let button = menu.parse_button(value).context("Menu doesn't support button")?;
|
||||
|
||||
buttons.push(button);
|
||||
|
||||
println!("add_menu \"{}\"", button.as_str().escape_debug());
|
||||
},
|
||||
(_, Command::FinishComboBox) => anyhow::bail!("Can only call `finish_menu` when mid-menu"),
|
||||
(_, Command::AddComboBoxOption { .. }) => anyhow::bail!("Can only call `add_menu_option` when mid-menu"),
|
||||
(_, Command::ComboBoxAwait) => anyhow::bail!("Can only call `finish_menu` when mid-menu"),
|
||||
(_, Command::AddComboBoxButton { .. }) => anyhow::bail!("Can only call `add_menu_option` when mid-menu"),
|
||||
|
||||
(State::Menu { .. }, command) => anyhow::bail!("Cannot execute command {:?} mid-menu", command),
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user