mirror of
https://github.com/Zenithsiz/dcb.git
synced 2026-02-06 17:35:40 +00:00
Changed Bytes interface to provide more safety with arrays.
This commit is contained in:
parent
e426d229f9
commit
888ace2017
@ -13,6 +13,7 @@ log = "0.4"
|
||||
byteorder = "1.3"
|
||||
arrayvec = { version = "0.5", features = ["serde"] }
|
||||
ascii = { version = "1.0", features = ["serde"] }
|
||||
arrayref = "0.3"
|
||||
|
||||
# Serde
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
||||
@ -5,18 +5,18 @@ pub trait Bytes
|
||||
where
|
||||
Self: Sized
|
||||
{
|
||||
/// The size of the structure in bytes
|
||||
const BUF_BYTE_SIZE: usize;
|
||||
/// The type of array required by this structure
|
||||
type ByteArray: Sized;
|
||||
|
||||
/// The error type used for the operation
|
||||
type FromError: std::fmt::Debug + std::error::Error;
|
||||
|
||||
/// Reads `bytes` and returns a result with `Self`
|
||||
fn from_bytes(bytes: &[u8]) -> Result<Self, Self::FromError>;
|
||||
fn from_bytes(bytes: &Self::ByteArray) -> Result<Self, Self::FromError>;
|
||||
|
||||
/// The error type used for the operation
|
||||
type ToError: std::fmt::Debug + std::error::Error;
|
||||
|
||||
/// Writes bytes into `bytes` from self
|
||||
fn to_bytes(&self, bytes: &mut [u8]) -> Result<(), Self::ToError>;
|
||||
fn to_bytes(&self, bytes: &mut Self::ByteArray) -> Result<(), Self::ToError>;
|
||||
}
|
||||
|
||||
@ -5,27 +5,27 @@
|
||||
//! # Layout
|
||||
//! The digimon card has a size of 0x138 bytes, and it's layout is the following:
|
||||
//!
|
||||
//! | Offset | Size | Type | Name | Location | Details |
|
||||
//! |--------|------|----------------------|---------------------------|--------------------------------|-------------------------------------------------------------------------------------|
|
||||
//! | 0x0 | 0x15 | `[char; 0x15]` | Name | `name` | Null-terminated |
|
||||
//! | 0x15 | 0x2 | `u16` | Unknown | `unknown_15` | Most likely contains the digimon's model |
|
||||
//! | 0x17 | 0x1 | `u8` | Speciality & Level | `speciality level` | The bottom nibble of this byte is the level, while the top nibble is the speciality |
|
||||
//! | 0x18 | 0x1 | `u8` | DP | `dp_cost` | |
|
||||
//! | 0x19 | 0x1 | `u8` | +P | `dp_give` | |
|
||||
//! | 0x1a | 0x1 | `u8` | Unknown | `unknown_1a` | Is` 0` for all digimon |
|
||||
//! | 0x1b | 0x2 | `u16` | Health | `hp` | |
|
||||
//! | 0x1d | 0x1c | [`Move`] | Circle Move | `moves.circle` | |
|
||||
//! | 0x39 | 0x1c | [`Move`] | Triangle move | `moves.triangle` | |
|
||||
//! | 0x55 | 0x1c | [`Move`] | Cross move | `moves.cross` | |
|
||||
//! | 0x71 | 0x20 | [`SupportCondition`] | First condition | `effects.conditions.first` | |
|
||||
//! | 0x91 | 0x20 | [`SupportCondition`] | Second condition | `effects.conditions.second` | |
|
||||
//! | 0xb1 | 0x10 | [`SupportEffect`] | First effect | `support.effects.first` | |
|
||||
//! | 0xc1 | 0x10 | [`SupportEffect`] | Second effect | `support.effects.second` | |
|
||||
//! | 0xd1 | 0x10 | [`SupportEffect`] | Third effect | `support.effects.third` | |
|
||||
//! | 0xe1 | 0x1 | [`CrossMoveEffect`] | Cross move effect | `support.cross_move` | |
|
||||
//! | 0xe2 | 0x1 | `u8` | Unknown | `support.unknown` | |
|
||||
//! | 0xe3 | 0x1 | [`ArrowColor`] | Effect arrow color | `effects.arrow_color` | |
|
||||
//! | 0xe4 | 0x54 | `[[char; 0x15]; 4]` | Effect description lines | `effects.description` | Each line is` 0x15` bytes, split over 4 lines, each null terminated |
|
||||
//! | Offset | Size | Type | Name | Location | Details |
|
||||
//! |--------|------|----------------------|---------------------------|------------------------|-------------------------------------------------------------------------------------|
|
||||
//! | 0x0 | 0x15 | `[char; 0x15]` | Name | `name` | Null-terminated |
|
||||
//! | 0x15 | 0x2 | `u16` | Unknown | `unknown_15` | Most likely contains the digimon's model |
|
||||
//! | 0x17 | 0x1 | `u8` | Speciality & Level | `speciality level` | The bottom nibble of this byte is the level, while the top nibble is the speciality |
|
||||
//! | 0x18 | 0x1 | `u8` | DP | `dp_cost` | |
|
||||
//! | 0x19 | 0x1 | `u8` | +P | `dp_give` | |
|
||||
//! | 0x1a | 0x1 | `u8` | Unknown | `unknown_1a` | Is` 0` for all digimon |
|
||||
//! | 0x1b | 0x2 | `u16` | Health | `hp` | |
|
||||
//! | 0x1d | 0x1c | [`Move`] | Circle Move | `move_circle` | |
|
||||
//! | 0x39 | 0x1c | [`Move`] | Triangle move | `move_triangle` | |
|
||||
//! | 0x55 | 0x1c | [`Move`] | Cross move | `move_cross` | |
|
||||
//! | 0x71 | 0x20 | [`SupportCondition`] | First condition | `effect_conditions[0]` | |
|
||||
//! | 0x91 | 0x20 | [`SupportCondition`] | Second condition | `effect_conditions[1]` | |
|
||||
//! | 0xb1 | 0x10 | [`SupportEffect`] | First effect | `effects[0]` | |
|
||||
//! | 0xc1 | 0x10 | [`SupportEffect`] | Second effect | `effects[1]` | |
|
||||
//! | 0xd1 | 0x10 | [`SupportEffect`] | Third effect | `effects[2]` | |
|
||||
//! | 0xe1 | 0x1 | [`CrossMoveEffect`] | Cross move effect | `cross_move_effect` | |
|
||||
//! | 0xe2 | 0x1 | `u8` | Unknown | `unknown_e2` | |
|
||||
//! | 0xe3 | 0x1 | [`ArrowColor`] | Effect arrow color | `effect_arrow_color` | |
|
||||
//! | 0xe4 | 0x54 | `[[char; 0x15]; 4]` | Effect description lines | `effect_description` | Each line is` 0x15` bytes, split over 4 lines, each null terminated |
|
||||
|
||||
// byteorder
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
@ -87,13 +87,13 @@ pub struct Digimon
|
||||
pub unknown_e2: u8,
|
||||
|
||||
/// The digimon's circle move
|
||||
pub circle_move: Move,
|
||||
pub move_circle: Move,
|
||||
|
||||
/// The digimon's triangle move
|
||||
pub triangle_move: Move,
|
||||
pub move_triangle: Move,
|
||||
|
||||
/// The digimon's cross move
|
||||
pub cross_move: Move,
|
||||
pub move_cross: Move,
|
||||
|
||||
/// The digimon's cross move effect, if any
|
||||
#[serde(default)]
|
||||
@ -123,12 +123,6 @@ pub struct Digimon
|
||||
#[derive(derive_more::Display, err_impl::Error)]
|
||||
pub enum FromBytesError
|
||||
{
|
||||
/// The given slice was not big enough
|
||||
#[display(fmt = "Given slice was too small ({} / {})", "slice_len", "Digimon::BUF_BYTE_SIZE")]
|
||||
SliceTooSmall {
|
||||
slice_len: usize,
|
||||
},
|
||||
|
||||
/// Unable to read the digimon name
|
||||
#[display(fmt = "Unable to read the digimon name")]
|
||||
Name( #[error(source)] util::ReadNullAsciiStringError ),
|
||||
@ -203,12 +197,6 @@ pub enum FromBytesError
|
||||
#[derive(derive_more::Display, err_impl::Error)]
|
||||
pub enum ToBytesError
|
||||
{
|
||||
/// The given slice was not big enough
|
||||
#[display(fmt = "Given slice was too small ({} / {})", "slice_len", "Digimon::BUF_BYTE_SIZE")]
|
||||
SliceTooSmall {
|
||||
slice_len: usize,
|
||||
},
|
||||
|
||||
/// Unable to write a move
|
||||
#[display(fmt = "Unable to write the {} move", name)]
|
||||
Move {
|
||||
@ -220,21 +208,25 @@ pub enum ToBytesError
|
||||
|
||||
impl Bytes for Digimon
|
||||
{
|
||||
const BUF_BYTE_SIZE : usize = 0x138;
|
||||
type ByteArray = [u8; 0x138];
|
||||
|
||||
type FromError = FromBytesError;
|
||||
|
||||
fn from_bytes(bytes: &[u8]) -> Result<Self, Self::FromError>
|
||||
fn from_bytes(bytes: &Self::ByteArray) -> Result<Self, Self::FromError>
|
||||
{
|
||||
// Make sure `bytes` is an array big enough, else return Err
|
||||
// SAFETY: We confirm `bytes` has at least `Self::BUF_BYTE_SIZE` elements.
|
||||
if bytes.len() < Self::BUF_BYTE_SIZE {
|
||||
return Err( FromBytesError::SliceTooSmall { slice_len: bytes.len() } );
|
||||
}
|
||||
let bytes: &[u8; Self::BUF_BYTE_SIZE] = unsafe {
|
||||
#[allow(clippy::as_conversions)]
|
||||
&*( bytes.as_ptr() as *const [u8; Self::BUF_BYTE_SIZE] )
|
||||
};
|
||||
// Get all byte arrays we need
|
||||
util::array_split!(bytes,
|
||||
0x00..0x1d => _,
|
||||
0x1d..0x39 => move_circle,
|
||||
0x39..0x55 => move_triangle,
|
||||
0x55..0x71 => move_cross,
|
||||
0x71..0x91 => condition_first,
|
||||
0x91..0xb1 => condition_second,
|
||||
0xb1..0xc1 => effect_first,
|
||||
0xc1..0xd1 => effect_second,
|
||||
0xd1..0xe1 => effect_third,
|
||||
0xe1..0x138 => _,
|
||||
);
|
||||
|
||||
// Return the struct after building it
|
||||
Ok( Self {
|
||||
@ -245,10 +237,10 @@ impl Bytes for Digimon
|
||||
|
||||
unknown_15: LittleEndian::read_u16( &bytes[0x15..0x17] ),
|
||||
|
||||
speciality: Speciality::from_bytes( &[(bytes[0x17] & 0xF0) >> 4] )
|
||||
speciality: Speciality::from_bytes( &( (bytes[0x17] & 0xF0) >> 4 ) )
|
||||
.map_err(FromBytesError::Speciality)?,
|
||||
|
||||
level: Level::from_bytes( &[(bytes[0x17] & 0x0F) >> 0] )
|
||||
level: Level::from_bytes( &( (bytes[0x17] & 0x0F) >> 0 ) )
|
||||
.map_err(FromBytesError::Level)?,
|
||||
|
||||
dp_cost : bytes[0x18],
|
||||
@ -258,52 +250,52 @@ impl Bytes for Digimon
|
||||
hp: LittleEndian::read_u16( &bytes[0x1b..0x1d] ),
|
||||
|
||||
// 0x1d - 0x71
|
||||
circle_move: Move::from_bytes( &bytes[0x1d..0x39] )
|
||||
move_circle: Move::from_bytes( move_circle )
|
||||
.map_err(FromBytesError::MoveCircle)?,
|
||||
triangle_move: Move::from_bytes( &bytes[0x39..0x55] )
|
||||
move_triangle: Move::from_bytes( move_triangle )
|
||||
.map_err(FromBytesError::MoveTriangle)?,
|
||||
cross_move: Move::from_bytes( &bytes[0x55..0x71] )
|
||||
move_cross: Move::from_bytes( move_cross )
|
||||
.map_err(FromBytesError::MoveCross)?,
|
||||
|
||||
// 0x71 - 0x138
|
||||
effect_conditions: [
|
||||
(bytes[0x73] != 0)
|
||||
.then(|| SupportCondition::from_bytes( &bytes[0x71..0x91] ) )
|
||||
.then(|| SupportCondition::from_bytes( condition_first ) )
|
||||
.transpose()
|
||||
.map_err(FromBytesError::EffectConditionFirst)?,
|
||||
|
||||
(bytes[0x93] != 0)
|
||||
.then(|| SupportCondition::from_bytes( &bytes[0x91..0xb1] ) )
|
||||
.then(|| SupportCondition::from_bytes( condition_second ) )
|
||||
.transpose()
|
||||
.map_err(FromBytesError::EffectConditionSecond)?,
|
||||
],
|
||||
|
||||
effects: [
|
||||
(bytes[0xb1] != 0)
|
||||
.then(|| SupportEffect::from_bytes( &bytes[0xb1..0xc1] ) )
|
||||
.then(|| SupportEffect::from_bytes( effect_first ) )
|
||||
.transpose()
|
||||
.map_err(FromBytesError::EffectFirst)?,
|
||||
|
||||
(bytes[0xc1] != 0)
|
||||
.then(|| SupportEffect::from_bytes( &bytes[0xc1..0xd1] ) )
|
||||
.then(|| SupportEffect::from_bytes( effect_second ) )
|
||||
.transpose()
|
||||
.map_err(FromBytesError::EffectSecond)?,
|
||||
|
||||
(bytes[0xd1] != 0)
|
||||
.then(|| SupportEffect::from_bytes( &bytes[0xd1..0xe1] ) )
|
||||
.then(|| SupportEffect::from_bytes( effect_third ) )
|
||||
.transpose()
|
||||
.map_err(FromBytesError::EffectThird)?,
|
||||
],
|
||||
|
||||
cross_move_effect: (bytes[0xe1] != 0)
|
||||
.then(|| CrossMoveEffect::from_bytes( &bytes[0xe1..0xe2] ) )
|
||||
.then(|| CrossMoveEffect::from_bytes( &bytes[0xe1] ) )
|
||||
.transpose()
|
||||
.map_err(FromBytesError::CrossMoveEffect)?,
|
||||
|
||||
unknown_e2: bytes[0xe2],
|
||||
|
||||
effect_arrow_color: (bytes[0xe3] != 0)
|
||||
.then(|| ArrowColor::from_bytes( &bytes[0xe3..0xe4] ) )
|
||||
.then(|| ArrowColor::from_bytes( &bytes[0xe3] ) )
|
||||
.transpose()
|
||||
.map_err(FromBytesError::ArrowColor)?,
|
||||
|
||||
@ -325,99 +317,106 @@ impl Bytes for Digimon
|
||||
}
|
||||
|
||||
type ToError = ToBytesError;
|
||||
|
||||
fn to_bytes(&self, bytes: &mut [u8]) -> Result<(), Self::ToError>
|
||||
fn to_bytes(&self, bytes: &mut Self::ByteArray) -> Result<(), Self::ToError>
|
||||
{
|
||||
// Make sure `bytes` is an array big enough, else return Err
|
||||
// SAFETY: We confirm `bytes` has at least `Self::BUF_BYTE_SIZE` elements.
|
||||
if bytes.len() < Self::BUF_BYTE_SIZE {
|
||||
return Err( ToBytesError::SliceTooSmall { slice_len: bytes.len() } );
|
||||
}
|
||||
let bytes: &mut [u8; Self::BUF_BYTE_SIZE] = unsafe {
|
||||
#[allow(clippy::as_conversions)]
|
||||
&mut *( bytes.as_mut_ptr() as *mut [u8; Self::BUF_BYTE_SIZE] )
|
||||
};
|
||||
// Get all byte arrays we need
|
||||
util::array_split_mut!(bytes,
|
||||
0x00..0x15 => name,
|
||||
0x15..0x17 => unknown_15,
|
||||
0x17..0x18 => speciality_level,
|
||||
0x18..0x19 => dp_cost,
|
||||
0x19..0x1a => dp_give,
|
||||
0x1a..0x1b => unknown_1a,
|
||||
0x1b..0x1d => hp,
|
||||
0x1d..0x39 => move_circle,
|
||||
0x39..0x55 => move_triangle,
|
||||
0x55..0x71 => move_cross,
|
||||
0x71..0x91 => condition_first,
|
||||
0x91..0xb1 => condition_second,
|
||||
0xb1..0xc1 => effect_first,
|
||||
0xc1..0xd1 => effect_second,
|
||||
0xd1..0xe1 => effect_third,
|
||||
0xe1..0xe2 => cross_move_effect,
|
||||
0xe2..0xe3 => unknown_e2,
|
||||
0xe3..0xe4 => effect_arrow_color,
|
||||
0xe4..0x138 => effect_description,
|
||||
);
|
||||
|
||||
// Name
|
||||
bytes[0x0..0x15].copy_from_slice(
|
||||
// name
|
||||
name.copy_from_slice(
|
||||
// Note: `self.name` is at most [char; 20], this cannot fail
|
||||
util::write_null_ascii_string(self.name.as_ref().as_ref(), &mut [0u8; 21])
|
||||
.expect("Name was too large for output buffer")
|
||||
);
|
||||
|
||||
// Basic
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// unknown_15
|
||||
LittleEndian::write_u16(unknown_15, self.unknown_15);
|
||||
|
||||
// Speciality / Level
|
||||
{
|
||||
let (mut speciality_byte, mut level_byte) = ( 0u8, 0u8 );
|
||||
|
||||
// Note: Buffers have 1 byte, so this can't fail
|
||||
self.speciality.to_bytes(&mut speciality_byte)?;
|
||||
self.level.to_bytes(&mut level_byte)?;
|
||||
|
||||
// Unknown 1
|
||||
LittleEndian::write_u16(&mut bytes[0x15..0x17], self.unknown_15);
|
||||
|
||||
// Speciality / Level
|
||||
{
|
||||
let (mut speciality_byte, mut level_byte) = ( [0u8], [0u8] );
|
||||
|
||||
// Note: Buffers have 1 byte, so this can't fail
|
||||
self.speciality.to_bytes(&mut speciality_byte)
|
||||
.expect("Could not convert speciality to bytes");
|
||||
self.level.to_bytes(&mut level_byte)
|
||||
.expect("Could not convert level to bytes");
|
||||
|
||||
// Merge them
|
||||
bytes[0x17] = (speciality_byte[0] << 4) | level_byte[0];
|
||||
}
|
||||
|
||||
// DP / +P
|
||||
bytes[0x18] = self.dp_cost;
|
||||
bytes[0x19] = self.dp_give;
|
||||
|
||||
// Unknown
|
||||
bytes[0x1a] = self.unknown_1a;
|
||||
|
||||
// Health
|
||||
LittleEndian::write_u16(&mut bytes[0x1b..0x1d], self.hp);
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Merge them
|
||||
speciality_level[0] = (speciality_byte << 4) | level_byte;
|
||||
}
|
||||
|
||||
// DP / +P
|
||||
dp_cost[0] = self.dp_cost;
|
||||
dp_give[0] = self.dp_give;
|
||||
|
||||
// Unknown
|
||||
unknown_1a[0] = self.unknown_1a;
|
||||
|
||||
// Health
|
||||
LittleEndian::write_u16(hp, self.hp);
|
||||
|
||||
// Moves
|
||||
self. circle_move.to_bytes(&mut bytes[0x1d..0x39]).map_err(|err| ToBytesError::Move{ name: "circle" , err })?;
|
||||
self.triangle_move.to_bytes(&mut bytes[0x39..0x55]).map_err(|err| ToBytesError::Move{ name: "triangle", err })?;
|
||||
self. cross_move.to_bytes(&mut bytes[0x55..0x71]).map_err(|err| ToBytesError::Move{ name: "cross" , err })?;
|
||||
|
||||
// Support
|
||||
self. move_circle.to_bytes( move_circle ).map_err(|err| ToBytesError::Move{ name: "circle" , err })?;
|
||||
self.move_triangle.to_bytes( move_triangle ).map_err(|err| ToBytesError::Move{ name: "triangle", err })?;
|
||||
self. move_cross.to_bytes( move_cross ).map_err(|err| ToBytesError::Move{ name: "cross" , err })?;
|
||||
|
||||
// Support conditions
|
||||
// Note: Although support conditions and effects aren't written if they're None,
|
||||
// a bit pattern of all 0s is a valid pattern and means "None" to the game.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Support conditions
|
||||
if let Some(support_condition) = &self.effect_conditions[0] { support_condition.to_bytes(&mut bytes[0x71..0x91])?; }
|
||||
if let Some(support_condition) = &self.effect_conditions[1] { support_condition.to_bytes(&mut bytes[0x91..0xb1])?; }
|
||||
|
||||
// Support effects
|
||||
if let Some(support_effect) = &self.effects[0] { support_effect.to_bytes(&mut bytes[0xb1..0xc1])?; }
|
||||
if let Some(support_effect) = &self.effects[1] { support_effect.to_bytes(&mut bytes[0xc1..0xd1])?; }
|
||||
if let Some(support_effect) = &self.effects[2] { support_effect.to_bytes(&mut bytes[0xd1..0xe1])?; }
|
||||
|
||||
// Cross move
|
||||
if let Some(cross_move) = self.cross_move_effect { cross_move.to_bytes(&mut bytes[0xe1..0xe2])
|
||||
.expect("Unable to convert cross move effect to bytes")
|
||||
};
|
||||
|
||||
// Unknown
|
||||
bytes[0xe2] = self.unknown_e2;
|
||||
|
||||
// Support arrow color
|
||||
if let Some(arrow_color) = self.effect_arrow_color { arrow_color.to_bytes( &mut bytes[0xe3..0xe4] )
|
||||
.expect("Unable to convert arrow color to bytes");
|
||||
}
|
||||
|
||||
// Write the support effects
|
||||
for (index, line) in self.effect_description.iter().enumerate()
|
||||
{
|
||||
bytes[0x0e4 + (0x15 * index) .. 0x0f9 + (0x15 * index)].copy_from_slice(
|
||||
// Note: `line` is at most [char; 20], this cannot fail
|
||||
util::write_null_ascii_string(line.as_ref().as_ref(), &mut [0u8; 21])
|
||||
.expect("Effect description was too large for output buffer")
|
||||
);
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
if let Some(support_condition) = &self.effect_conditions[0] { support_condition.to_bytes( condition_first )?; }
|
||||
if let Some(support_condition) = &self.effect_conditions[1] { support_condition.to_bytes( condition_second )?; }
|
||||
|
||||
// Support effects
|
||||
if let Some(support_effect) = &self.effects[0] { support_effect.to_bytes( effect_first )?; }
|
||||
if let Some(support_effect) = &self.effects[1] { support_effect.to_bytes( effect_second )?; }
|
||||
if let Some(support_effect) = &self.effects[2] { support_effect.to_bytes( effect_third )?; }
|
||||
|
||||
// Cross move
|
||||
if let Some(move_cross) = self.cross_move_effect { move_cross.to_bytes( &mut cross_move_effect[0] )
|
||||
.expect("Unable to convert cross move effect to bytes")
|
||||
};
|
||||
|
||||
// Unknown
|
||||
unknown_e2[0] = self.unknown_e2;
|
||||
|
||||
// Support arrow color
|
||||
if let Some(arrow_color) = self.effect_arrow_color { arrow_color.to_bytes( &mut effect_arrow_color[1] )
|
||||
.expect("Unable to convert arrow color to bytes");
|
||||
}
|
||||
|
||||
// effect_description
|
||||
// Note: Each string is at most [char; 20], this cannot fail
|
||||
effect_description[0x00..0x15].copy_from_slice( util::write_null_ascii_string(self.effect_description[0].as_ref().as_ref(), &mut [0u8; 21])
|
||||
.expect("First line of effect description was too large for output buffer")
|
||||
);
|
||||
effect_description[0x15..0x2a].copy_from_slice( util::write_null_ascii_string(self.effect_description[1].as_ref().as_ref(), &mut [0u8; 21])
|
||||
.expect("Second line of effect description was too large for output buffer")
|
||||
);
|
||||
effect_description[0x2a..0x3f].copy_from_slice( util::write_null_ascii_string(self.effect_description[2].as_ref().as_ref(), &mut [0u8; 21])
|
||||
.expect("Third line of effect description was too large for output buffer")
|
||||
);
|
||||
effect_description[0x3f..0x54].copy_from_slice( util::write_null_ascii_string(self.effect_description[3].as_ref().as_ref(), &mut [0u8; 21])
|
||||
.expect("Fourth line of effect description was too large for output buffer")
|
||||
);
|
||||
|
||||
// Return Ok
|
||||
Ok(())
|
||||
|
||||
@ -149,11 +149,10 @@ use serde::Deserialize;
|
||||
// Bytes
|
||||
impl Bytes for Digivolve
|
||||
{
|
||||
const BUF_BYTE_SIZE : usize = 0x6c;
|
||||
type ByteArray = [u8; 0x6c];
|
||||
|
||||
type FromError = FromBytesError;
|
||||
|
||||
fn from_bytes(bytes: &[u8]) -> Result<Self, Self::FromError>
|
||||
fn from_bytes(bytes: &Self::ByteArray) -> Result<Self, Self::FromError>
|
||||
{
|
||||
Ok( Self {
|
||||
basic: Basic {
|
||||
@ -176,8 +175,7 @@ use serde::Deserialize;
|
||||
}
|
||||
|
||||
type ToError = ToBytesError;
|
||||
|
||||
fn to_bytes(&self, bytes: &mut [u8]) -> Result<(), Self::ToError>
|
||||
fn to_bytes(&self, bytes: &mut Self::ByteArray) -> Result<(), Self::ToError>
|
||||
{
|
||||
// Basic
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@ -10,6 +10,9 @@
|
||||
use crate::game::card::property::ArrowColor;
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
// Array-ref
|
||||
use arrayref::{array_ref, array_mut_ref};
|
||||
|
||||
// byteorder
|
||||
use byteorder::ByteOrder;
|
||||
use byteorder::LittleEndian;
|
||||
@ -144,10 +147,10 @@ use serde::Deserialize;
|
||||
// Bytes
|
||||
impl Bytes for Item
|
||||
{
|
||||
const BUF_BYTE_SIZE : usize = 0xde;
|
||||
type ByteArray = [u8; 0xde];
|
||||
|
||||
type FromError = FromBytesError;
|
||||
fn from_bytes(bytes: &[u8]) -> Result<Self, Self::FromError>
|
||||
fn from_bytes(bytes: &Self::ByteArray) -> Result<Self, Self::FromError>
|
||||
{
|
||||
// Assert some fields are 0
|
||||
//assert_eq!(bytes[0x1a], 0);
|
||||
@ -169,30 +172,30 @@ use serde::Deserialize;
|
||||
],
|
||||
|
||||
arrow_color: if bytes[0x89] != 0 {
|
||||
Some( ArrowColor::from_bytes( &bytes[0x89..0x8a] ).map_err(FromBytesError::EffectArrowColor)? )
|
||||
Some( ArrowColor::from_bytes( &bytes[0x89] ).map_err(FromBytesError::EffectArrowColor)? )
|
||||
} else { None },
|
||||
|
||||
conditions: SupportConditions {
|
||||
first: if bytes[0x19] != 0 { Some(
|
||||
SupportCondition::from_bytes( &bytes[0x19..0x39] ).map_err(|err| FromBytesError::SupportCondition{ rank: "1st", item_pos: 0x19, err })?
|
||||
SupportCondition::from_bytes( array_ref!(bytes, 0x19, 0x20) ).map_err(|err| FromBytesError::SupportCondition{ rank: "1st", item_pos: 0x19, err })?
|
||||
)} else { None },
|
||||
|
||||
second: if bytes[0x39] != 0 { Some(
|
||||
SupportCondition::from_bytes( &bytes[0x39..0x59] ).map_err(|err| FromBytesError::SupportCondition{ rank: "2nd", item_pos: 0x39, err })?
|
||||
SupportCondition::from_bytes( array_ref!(bytes, 0x39, 0x20) ).map_err(|err| FromBytesError::SupportCondition{ rank: "2nd", item_pos: 0x39, err })?
|
||||
)} else { None },
|
||||
},
|
||||
|
||||
effects: SupportEffects {
|
||||
first: if bytes[0x59] != 0 { Some(
|
||||
SupportEffect::from_bytes( &bytes[0x59..0x69] ).map_err(|err| FromBytesError::SupportEffect{ rank: "1st", err })?
|
||||
SupportEffect::from_bytes( array_ref!(bytes, 0x59, 0x10) ).map_err(|err| FromBytesError::SupportEffect{ rank: "1st", err })?
|
||||
)} else { None },
|
||||
|
||||
second: if bytes[0x69] != 0 { Some(
|
||||
SupportEffect::from_bytes( &bytes[0x69..0x79] ).map_err(|err| FromBytesError::SupportEffect{ rank: "2nd", err })?
|
||||
SupportEffect::from_bytes( array_ref!(bytes, 0x69, 0x10) ).map_err(|err| FromBytesError::SupportEffect{ rank: "2nd", err })?
|
||||
)} else { None },
|
||||
|
||||
third: if bytes[0x79] != 0 { Some(
|
||||
SupportEffect::from_bytes( &bytes[0x79..0x89] ).map_err(|err| FromBytesError::SupportEffect{ rank: "3rd", err })?
|
||||
SupportEffect::from_bytes( array_ref!(bytes, 0x79, 0x10) ).map_err(|err| FromBytesError::SupportEffect{ rank: "3rd", err })?
|
||||
)} else { None },
|
||||
},
|
||||
},
|
||||
@ -200,7 +203,7 @@ use serde::Deserialize;
|
||||
}
|
||||
|
||||
type ToError = ToBytesError;
|
||||
fn to_bytes(&self, bytes: &mut [u8]) -> Result<(), Self::ToError>
|
||||
fn to_bytes(&self, bytes: &mut Self::ByteArray) -> Result<(), Self::ToError>
|
||||
{
|
||||
// Basic
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -243,17 +246,17 @@ use serde::Deserialize;
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(arrow_color) = self.effects.arrow_color { arrow_color.to_bytes( &mut bytes[0x89..0x8a] ).expect("Unable to convert arrow color to bytes"); }
|
||||
if let Some(arrow_color) = self.effects.arrow_color { arrow_color.to_bytes( &mut bytes[0x89] ).expect("Unable to convert arrow color to bytes"); }
|
||||
|
||||
// If they are None, 0 is a valid value for the conditions
|
||||
if let Some(support_condition) = &self.effects.conditions.first { support_condition.to_bytes(&mut bytes[0x19..0x39])?; }
|
||||
if let Some(support_condition) = &self.effects.conditions.second { support_condition.to_bytes(&mut bytes[0x39..0x59])?; }
|
||||
if let Some(support_condition) = &self.effects.conditions.first { support_condition.to_bytes( array_mut_ref!(bytes, 0x19, 0x20) )?; }
|
||||
if let Some(support_condition) = &self.effects.conditions.second { support_condition.to_bytes( array_mut_ref!(bytes, 0x39, 0x20) )?; }
|
||||
|
||||
|
||||
// If they are None, 0 is a valid value for the effects
|
||||
if let Some(support_effect) = &self.effects.effects.first { support_effect.to_bytes(&mut bytes[0x59..0x69])?; }
|
||||
if let Some(support_effect) = &self.effects.effects.second { support_effect.to_bytes(&mut bytes[0x69..0x79])?; }
|
||||
if let Some(support_effect) = &self.effects.effects.third { support_effect.to_bytes(&mut bytes[0x79..0x89])?; }
|
||||
if let Some(support_effect) = &self.effects.effects.first { support_effect.to_bytes( array_mut_ref!(bytes, 0x59, 0x10) )?; }
|
||||
if let Some(support_effect) = &self.effects.effects.second { support_effect.to_bytes( array_mut_ref!(bytes, 0x69, 0x10) )?; }
|
||||
if let Some(support_effect) = &self.effects.effects.third { support_effect.to_bytes( array_mut_ref!(bytes, 0x79, 0x10) )?; }
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
// Return the bytes
|
||||
|
||||
@ -73,61 +73,31 @@ macro_rules! generate_enum_property_mod
|
||||
#[derive(::derive_more::Display, ::err_impl::Error)]
|
||||
$mod_vis enum FromBytesError {
|
||||
|
||||
/// The given slice was not big enough
|
||||
#[display(fmt = "Given slice was too small ({} / 1)", "slice_len")]
|
||||
SliceTooSmall {
|
||||
slice_len: usize,
|
||||
},
|
||||
|
||||
/// Unknown value
|
||||
#[display(fmt = $error_unknown_value_display, "byte")]
|
||||
UnknownValue {
|
||||
byte: u8,
|
||||
}
|
||||
}
|
||||
|
||||
/// Error type for [`Bytes::to_bytes`]
|
||||
#[derive(Debug)]
|
||||
#[derive(::derive_more::Display, ::err_impl::Error)]
|
||||
$mod_vis enum ToBytesError {
|
||||
|
||||
/// The given slice was not big enough
|
||||
#[display(fmt = "Given slice was too small ({} / 1)", "slice_len")]
|
||||
SliceTooSmall {
|
||||
slice_len: usize,
|
||||
},
|
||||
}
|
||||
|
||||
// Bytes
|
||||
impl $crate::game::Bytes for $enum_name
|
||||
{
|
||||
const BUF_BYTE_SIZE: usize = 1;
|
||||
type ByteArray = u8;
|
||||
|
||||
type FromError = FromBytesError;
|
||||
fn from_bytes(bytes: &[u8]) -> Result<Self, Self::FromError>
|
||||
fn from_bytes(byte: &Self::ByteArray) -> Result<Self, Self::FromError>
|
||||
{
|
||||
use ::std::convert::TryInto;
|
||||
let bytes: &[u8; 1] = bytes
|
||||
.try_into()
|
||||
.map_err(|_| Self::FromError::SliceTooSmall { slice_len: bytes.len() })?;
|
||||
|
||||
match bytes[0] {
|
||||
match byte {
|
||||
$( $enum_variant_value => Ok( <$enum_name>::$enum_variant_name ), )*
|
||||
|
||||
_ => Err( Self::FromError::UnknownValue{ byte: bytes[0] } ),
|
||||
_ => Err( Self::FromError::UnknownValue{ byte: *byte } ),
|
||||
}
|
||||
}
|
||||
|
||||
type ToError = ToBytesError;
|
||||
fn to_bytes(&self, bytes: &mut [u8]) -> Result<(), Self::ToError>
|
||||
type ToError = !;
|
||||
fn to_bytes(&self, byte: &mut Self::ByteArray) -> Result<(), Self::ToError>
|
||||
{
|
||||
use ::std::convert::TryInto;
|
||||
let slice_len = bytes.len();
|
||||
let bytes: &mut [u8; 1] = bytes
|
||||
.try_into()
|
||||
.map_err(|_| Self::ToError::SliceTooSmall { slice_len })?;
|
||||
|
||||
bytes[0] = match self {
|
||||
*byte = match self {
|
||||
$( <$enum_name>::$enum_variant_name => $enum_variant_value, )*
|
||||
};
|
||||
|
||||
@ -197,15 +167,15 @@ macro_rules! generate_enum_property_mod
|
||||
{
|
||||
/// Returns the byte size of the corresponding card
|
||||
#[must_use]
|
||||
pub fn card_byte_size(self) -> usize
|
||||
pub fn byte_size(self) -> usize
|
||||
{
|
||||
use crate::game::Bytes;
|
||||
|
||||
match self
|
||||
{
|
||||
Self::Digimon => <crate::game::card::Digimon as Bytes>::BUF_BYTE_SIZE,
|
||||
Self::Item => <crate::game::card::Item as Bytes>::BUF_BYTE_SIZE,
|
||||
Self::Digivolve => <crate::game::card::Digivolve as Bytes>::BUF_BYTE_SIZE,
|
||||
Self::Digimon => std::mem::size_of::< <crate::game::card::Digimon as Bytes>::ByteArray >(),
|
||||
Self::Item => std::mem::size_of::< <crate::game::card::Item as Bytes>::ByteArray >(),
|
||||
Self::Digivolve => std::mem::size_of::< <crate::game::card::Digivolve as Bytes>::ByteArray >(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,10 +50,10 @@ use byteorder::LittleEndian;
|
||||
// Bytes
|
||||
impl Bytes for Move
|
||||
{
|
||||
const BUF_BYTE_SIZE : usize = 0x1c;
|
||||
type ByteArray = [u8; 0x1c];
|
||||
|
||||
type FromError = FromBytesError;
|
||||
fn from_bytes(bytes: &[u8]) -> Result<Self, Self::FromError>
|
||||
fn from_bytes(bytes: &Self::ByteArray) -> Result<Self, Self::FromError>
|
||||
{
|
||||
// And return the move
|
||||
Ok( Self {
|
||||
@ -64,7 +64,7 @@ use byteorder::LittleEndian;
|
||||
}
|
||||
|
||||
type ToError = ToBytesError;
|
||||
fn to_bytes(&self, bytes: &mut [u8]) -> Result<(), Self::ToError>
|
||||
fn to_bytes(&self, bytes: &mut Self::ByteArray) -> Result<(), Self::ToError>
|
||||
{
|
||||
// Write the name
|
||||
bytes[0x6..0x1c].copy_from_slice( &{
|
||||
|
||||
@ -72,13 +72,13 @@ use byteorder::{ByteOrder, LittleEndian};
|
||||
// Bytes
|
||||
impl Bytes for SupportCondition
|
||||
{
|
||||
const BUF_BYTE_SIZE : usize = 0x20;
|
||||
type ByteArray = [u8; 0x20];
|
||||
|
||||
type FromError = FromBytesError;
|
||||
fn from_bytes(bytes: &[u8]) -> Result<Self, Self::FromError>
|
||||
fn from_bytes(bytes: &Self::ByteArray) -> Result<Self, Self::FromError>
|
||||
{
|
||||
// Get the condition
|
||||
let cond = DigimonProperty::from_bytes( &bytes[0x2..0x3] ).map_err(FromBytesError::Condition)?;
|
||||
let cond = DigimonProperty::from_bytes( &bytes[0x2] ).map_err(FromBytesError::Condition)?;
|
||||
|
||||
// And return the move
|
||||
Ok( Self {
|
||||
@ -86,12 +86,12 @@ use byteorder::{ByteOrder, LittleEndian};
|
||||
cond,
|
||||
|
||||
type_arg: if bytes[0x8] != 0 { Some(
|
||||
DigimonProperty::from_bytes( &[bytes[0x8]] ).map_err(FromBytesError::PropertyArgument)?
|
||||
DigimonProperty::from_bytes( &bytes[0x8] ).map_err(FromBytesError::PropertyArgument)?
|
||||
)} else { None },
|
||||
|
||||
num_arg: LittleEndian::read_u16( &bytes[0x14..0x16] ),
|
||||
|
||||
operation: SupportConditionOperation::from_bytes( &bytes[0x1a..0x1b] ).map_err(FromBytesError::Operation)?,
|
||||
operation: SupportConditionOperation::from_bytes( &bytes[0x1a] ).map_err(FromBytesError::Operation)?,
|
||||
|
||||
unknown: [
|
||||
bytes[0x3], bytes[0x4], bytes[0x5], bytes[0x6], bytes[0x7],
|
||||
@ -103,7 +103,7 @@ use byteorder::{ByteOrder, LittleEndian};
|
||||
}
|
||||
|
||||
type ToError = !;
|
||||
fn to_bytes(&self, bytes: &mut [u8]) -> Result<(), Self::ToError>
|
||||
fn to_bytes(&self, bytes: &mut Self::ByteArray) -> Result<(), Self::ToError>
|
||||
{
|
||||
// 0x0 - Misfire
|
||||
bytes[0x0] = if self.misfire { 1 } else { 0 };
|
||||
@ -113,7 +113,7 @@ use byteorder::{ByteOrder, LittleEndian};
|
||||
|
||||
// 0x2 - Condition
|
||||
#[allow(clippy::diverging_sub_expression)] { // False positive
|
||||
self.cond.to_bytes(&mut bytes[0x2..0x3])
|
||||
self.cond.to_bytes(&mut bytes[0x2])
|
||||
.expect("Unable to convert condition to bytes");
|
||||
}
|
||||
|
||||
@ -122,20 +122,20 @@ use byteorder::{ByteOrder, LittleEndian};
|
||||
|
||||
// 0x8 - Type arg / 0 if None
|
||||
if let Some(type_arg) = self.type_arg {
|
||||
type_arg.to_bytes(&mut bytes[0x8..0x9])
|
||||
type_arg.to_bytes(&mut bytes[0x8])
|
||||
.expect("Unable to convert type argument to bytes")
|
||||
}
|
||||
else { bytes[0x8] = 0; }
|
||||
|
||||
// 0x9..0x14 - Unknown[5..16]
|
||||
bytes[0x9..0x14].copy_from_slice( &self.unknown[5..16] );
|
||||
// 0x9..0x14 - Unknown[0x5..0x10]
|
||||
bytes[0x9..0x14].copy_from_slice( &self.unknown[0x5..0x10] );
|
||||
|
||||
// 0x14..0x16 - Number arg
|
||||
LittleEndian::write_u16(&mut bytes[0x14..0x16], self.num_arg);
|
||||
|
||||
// 0x1a - Operation arg
|
||||
#[allow(clippy::diverging_sub_expression)] { // False positive
|
||||
self.operation.to_bytes(&mut bytes[0x1a..0x1b])
|
||||
self.operation.to_bytes(&mut bytes[0x1a])
|
||||
.expect("Unable to convert operation to bytes");
|
||||
}
|
||||
|
||||
|
||||
@ -197,12 +197,11 @@ use crate::{
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
impl Bytes for SupportEffect
|
||||
{
|
||||
const BUF_BYTE_SIZE : usize = 0x10;
|
||||
type ByteArray = [u8; 0x10];
|
||||
|
||||
type FromError = FromBytesError;
|
||||
|
||||
/// `bytes` should include the `exists` byte
|
||||
fn from_bytes(bytes: &[u8]) -> Result<Self, Self::FromError>
|
||||
fn from_bytes(bytes: &Self::ByteArray) -> Result<Self, Self::FromError>
|
||||
{
|
||||
// Assert that we do exist
|
||||
assert_ne!(bytes[0x0], 0);
|
||||
@ -212,15 +211,15 @@ use crate::{
|
||||
|
||||
// The properties
|
||||
let a = if bytes[0x2] != 0 {
|
||||
Some( DigimonProperty::from_bytes( &bytes[0x2..0x3] ) .map_err(|err| FromBytesError::PropertyArgument{ rank: "1st", err })? )
|
||||
Some( DigimonProperty::from_bytes( &bytes[0x2] ) .map_err(|err| FromBytesError::PropertyArgument{ rank: "1st", err })? )
|
||||
} else { None };
|
||||
|
||||
let b = if bytes[0x4] != 0 {
|
||||
Some( DigimonProperty::from_bytes( &bytes[0x4..0x5] ) .map_err(|err| FromBytesError::PropertyArgument{ rank: "2nd", err })? )
|
||||
Some( DigimonProperty::from_bytes( &bytes[0x4] ) .map_err(|err| FromBytesError::PropertyArgument{ rank: "2nd", err })? )
|
||||
} else { None };
|
||||
|
||||
let c = if bytes[0x6] != 0 {
|
||||
Some( DigimonProperty::from_bytes( &bytes[0x6..0x7] ) .map_err(|err| FromBytesError::PropertyArgument{ rank: "3rd", err })? )
|
||||
Some( DigimonProperty::from_bytes( &bytes[0x6] ) .map_err(|err| FromBytesError::PropertyArgument{ rank: "3rd", err })? )
|
||||
} else { None };
|
||||
|
||||
// The numbers
|
||||
@ -228,7 +227,7 @@ use crate::{
|
||||
let y = LittleEndian::read_u16( &bytes[0xc..0xe] );
|
||||
|
||||
// The operation
|
||||
let op = SupportEffectOperation::from_bytes( &bytes[0xf..0x10] ) .map_err(FromBytesError::Operation)?;
|
||||
let op = SupportEffectOperation::from_bytes( &bytes[0xf] ) .map_err(FromBytesError::Operation)?;
|
||||
|
||||
// Check what the effect type is
|
||||
match effect_type_byte
|
||||
@ -236,15 +235,15 @@ use crate::{
|
||||
0..=13 => {
|
||||
Ok( Self::ChangeProperty {
|
||||
// Note: unwrapping is fine here because we know that `effect_type_byte+1` is between 1 and 14 inclusive
|
||||
property: DigimonProperty::from_bytes( &[ effect_type_byte+1 ] )
|
||||
property: DigimonProperty::from_bytes( &(effect_type_byte+1) )
|
||||
.expect("Unable to get digimon property from bytes"),
|
||||
a, b, c, x, y, op,
|
||||
})
|
||||
},
|
||||
|
||||
// Take lower byte from `x` for these
|
||||
16 => { Ok( Self::UseAttack{ player: PlayerType::Player , attack: AttackType::from_bytes( &[x.to_le_bytes()[0]] ) .map_err(FromBytesError::AttackType)? } ) },
|
||||
17 => { Ok( Self::UseAttack{ player: PlayerType::Opponent, attack: AttackType::from_bytes( &[x.to_le_bytes()[0]] ) .map_err(FromBytesError::AttackType)? } ) },
|
||||
16 => { Ok( Self::UseAttack{ player: PlayerType::Player , attack: AttackType::from_bytes( &x.to_le_bytes()[0] ) .map_err(FromBytesError::AttackType)? } ) },
|
||||
17 => { Ok( Self::UseAttack{ player: PlayerType::Opponent, attack: AttackType::from_bytes( &x.to_le_bytes()[0] ) .map_err(FromBytesError::AttackType)? } ) },
|
||||
|
||||
|
||||
25 => { Ok( Self::SetTempSlot{ a, b, c, op } ) },
|
||||
@ -290,7 +289,7 @@ use crate::{
|
||||
}
|
||||
|
||||
type ToError = !;
|
||||
fn to_bytes(&self, _bytes: &mut [u8]) -> Result<(), Self::ToError>
|
||||
fn to_bytes(&self, _bytes: &mut Self::ByteArray) -> Result<(), Self::ToError>
|
||||
{
|
||||
// Match which effect we are
|
||||
todo!()
|
||||
|
||||
@ -111,9 +111,9 @@ pub enum DeserializeError {
|
||||
"digimon_cards",
|
||||
"item_cards",
|
||||
"digivolve_cards",
|
||||
" digimon_cards * (0x3 + Digimon ::BUF_BYTE_SIZE + 0x1) +
|
||||
item_cards * (0x3 + Item ::BUF_BYTE_SIZE + 0x1) +
|
||||
digivolve_cards * (0x3 + Digivolve::BUF_BYTE_SIZE + 0x1)",
|
||||
" digimon_cards * (0x3 + CardType::Digimon .byte_size() + 0x1) +
|
||||
item_cards * (0x3 + CardType::Item .byte_size() + 0x1) +
|
||||
digivolve_cards * (0x3 + CardType::Digivolve.byte_size() + 0x1)",
|
||||
Table::MAX_BYTE_SIZE
|
||||
)]
|
||||
TooManyCards {
|
||||
@ -175,9 +175,9 @@ pub enum SerializeError {
|
||||
"digimon_cards",
|
||||
"item_cards",
|
||||
"digivolve_cards",
|
||||
" digimon_cards * (0x3 + Digimon ::BUF_BYTE_SIZE + 0x1) +
|
||||
item_cards * (0x3 + Item ::BUF_BYTE_SIZE + 0x1) +
|
||||
digivolve_cards * (0x3 + Digivolve::BUF_BYTE_SIZE + 0x1)",
|
||||
" digimon_cards * (0x3 + CardType::Digimon .byte_size() + 0x1) +
|
||||
item_cards * (0x3 + CardType::Item .byte_size() + 0x1) +
|
||||
digivolve_cards * (0x3 + CardType::Digivolve.byte_size() + 0x1)",
|
||||
Table::MAX_BYTE_SIZE
|
||||
)]
|
||||
TooManyCards {
|
||||
@ -240,10 +240,12 @@ impl Table {
|
||||
// And calculate the number of cards
|
||||
let cards_len = digimon_cards + item_cards + digivolve_cards;
|
||||
|
||||
|
||||
|
||||
// If there are too many cards, return Err
|
||||
let table_size = digimon_cards * (0x3 + Digimon ::BUF_BYTE_SIZE + 0x1) +
|
||||
item_cards * (0x3 + Item ::BUF_BYTE_SIZE + 0x1) +
|
||||
digivolve_cards * (0x3 + Digivolve::BUF_BYTE_SIZE + 0x1);
|
||||
let table_size = digimon_cards * (0x3 + CardType::Digimon .byte_size() + 0x1) +
|
||||
item_cards * (0x3 + CardType::Item .byte_size() + 0x1) +
|
||||
digivolve_cards * (0x3 + CardType::Digivolve.byte_size() + 0x1);
|
||||
log::debug!("[Table Header] {} total bytes of cards", table_size);
|
||||
if table_size > Self::MAX_BYTE_SIZE { return Err( DeserializeError::TooManyCards {
|
||||
digimon_cards,
|
||||
@ -266,7 +268,7 @@ impl Table {
|
||||
|
||||
// Read the header
|
||||
let card_id = LittleEndian::read_u16( &card_header_bytes[0x0..0x2] );
|
||||
let card_type = CardType::from_bytes( &card_header_bytes[0x2..0x3] )
|
||||
let card_type = CardType::from_bytes( &card_header_bytes[0x2] )
|
||||
.map_err(|err| DeserializeError::UnknownCardType{ id: cur_id, err } )?;
|
||||
|
||||
log::debug!("[Card Header] Found {} with id {}", card_type, card_id);
|
||||
@ -279,7 +281,7 @@ impl Table {
|
||||
match card_type
|
||||
{
|
||||
CardType::Digimon => {
|
||||
let mut digimon_bytes = [0; Digimon::BUF_BYTE_SIZE];
|
||||
let mut digimon_bytes = [0; std::mem::size_of::< <Digimon as Bytes>::ByteArray>()];
|
||||
file.read_exact(&mut digimon_bytes)
|
||||
.expect("Unable to read digimon bytes");
|
||||
let digimon = Digimon::from_bytes(&digimon_bytes)
|
||||
@ -287,7 +289,7 @@ impl Table {
|
||||
digimons.push(digimon);
|
||||
},
|
||||
CardType::Item => {
|
||||
let mut item_bytes = [0; Item::BUF_BYTE_SIZE];
|
||||
let mut item_bytes = [0; std::mem::size_of::< <Item as Bytes>::ByteArray>()];
|
||||
file.read_exact(&mut item_bytes)
|
||||
.expect("Unable to read item bytes");
|
||||
let item = Item::from_bytes(&item_bytes)
|
||||
@ -295,7 +297,7 @@ impl Table {
|
||||
items.push(item);
|
||||
},
|
||||
CardType::Digivolve => {
|
||||
let mut digivolve_bytes = [0; Digivolve::BUF_BYTE_SIZE];
|
||||
let mut digivolve_bytes = [0; std::mem::size_of::< <Digivolve as Bytes>::ByteArray>()];
|
||||
file.read_exact(&mut digivolve_bytes)
|
||||
.expect("Unable to read digivolve bytes");
|
||||
let digivolve = Digivolve::from_bytes(&digivolve_bytes)
|
||||
@ -323,9 +325,9 @@ impl Table {
|
||||
|
||||
pub fn serialize<R: Read + Write + Seek>(&self, file: &mut GameFile<R>) -> Result<(), SerializeError> {
|
||||
// Get the final table size
|
||||
let table_size = self.digimons .len() * (0x3 + Digimon ::BUF_BYTE_SIZE + 0x1) +
|
||||
self.items .len() * (0x3 + Item ::BUF_BYTE_SIZE + 0x1) +
|
||||
self.digivolves.len() * (0x3 + Digivolve::BUF_BYTE_SIZE + 0x1);
|
||||
let table_size = self. digimons.len() * (0x3 + CardType::Digimon .byte_size() + 0x1) +
|
||||
self. items.len() * (0x3 + CardType::Item .byte_size() + 0x1) +
|
||||
self.digivolves.len() * (0x3 + CardType::Digivolve.byte_size() + 0x1);
|
||||
|
||||
// If the total table size is bigger than the max, return Err
|
||||
if table_size > Self::MAX_BYTE_SIZE { return Err( SerializeError::TooManyCards {
|
||||
|
||||
@ -6,7 +6,39 @@
|
||||
//! All items in this module will eventually be depracated and moved
|
||||
//! somewhere else, but this change might take some time.
|
||||
|
||||
// Macros
|
||||
/// Splits an array into it's various element arrays
|
||||
pub macro array_split {
|
||||
(
|
||||
$arr:ident,
|
||||
$( $start:literal..$end:literal => $name:tt),* $(,)?
|
||||
) => {
|
||||
let (
|
||||
$(
|
||||
$name,
|
||||
)*
|
||||
) = ::arrayref::array_refs!(
|
||||
$arr,
|
||||
$( $end - $start ),*
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Splits an array mutable into it's various element arrays
|
||||
pub macro array_split_mut {
|
||||
(
|
||||
$arr:ident,
|
||||
$( $start:literal..$end:literal => $name:tt),* $(,)?
|
||||
) => {
|
||||
let (
|
||||
$(
|
||||
$name,
|
||||
)*
|
||||
) = ::arrayref::mut_array_refs!(
|
||||
$arr,
|
||||
$( $end - $start ),*
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Types
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
trait_alias,
|
||||
unsized_locals,
|
||||
bool_to_option,
|
||||
decl_macro,
|
||||
)]
|
||||
|
||||
// Lints
|
||||
@ -47,6 +48,7 @@
|
||||
clippy::multiple_inherent_impl, // We prefer to separate certain methods by type and insert error types in between methods
|
||||
clippy::identity_op, // Makes sense sometimes for symmetry
|
||||
clippy::items_after_statements, // Sometimes we only introduce items when we first use them.
|
||||
clippy::unseparated_literal_suffix, // We only separate them when they are long
|
||||
|
||||
// TODO: Deal with casts eventually
|
||||
clippy::cast_possible_wrap,
|
||||
@ -56,9 +58,7 @@
|
||||
// TODO: Remove these once all modules are ported
|
||||
clippy::missing_docs_in_private_items,
|
||||
clippy::as_conversions,
|
||||
clippy::panic,
|
||||
clippy::indexing_slicing,
|
||||
clippy::unseparated_literal_suffix,
|
||||
clippy::integer_arithmetic,
|
||||
clippy::unreachable,
|
||||
clippy::todo,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user