mirror of
https://github.com/Zenithsiz/dcb.git
synced 2026-02-08 19:34:27 +00:00
Added a read_maybe_null_ascii_string to game::util.
Added information to `Decks`. All decks are now read with `game::deck::Table`.
This commit is contained in:
@@ -1,8 +1,86 @@
|
||||
//! Decks
|
||||
|
||||
// byteorder
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
|
||||
// Crate
|
||||
use crate::game::{util, Bytes};
|
||||
|
||||
/// A deck
|
||||
#[derive(Debug)]
|
||||
#[derive(::serde::Serialize, ::serde::Deserialize)]
|
||||
pub struct Deck {
|
||||
/// Name of this deck
|
||||
pub name: ascii::AsciiString,
|
||||
|
||||
/// Digimon who plays this deck
|
||||
pub owner: ascii::AsciiString,
|
||||
|
||||
/// All of the card ids that make up this deck
|
||||
pub cards: [u16; 30],
|
||||
}
|
||||
|
||||
/// Error type for [`Bytes::from_bytes`]
|
||||
#[derive(Debug, derive_more::Display, err_impl::Error)]
|
||||
pub enum FromBytesError {
|
||||
/// Unable to read the deck name
|
||||
#[display(fmt = "Unable to read the deck name")]
|
||||
Name(#[error(source)] util::ReadMaybeNullAsciiStringError),
|
||||
|
||||
/// Unable to read the deck owner
|
||||
#[display(fmt = "Unable to read the deck owner")]
|
||||
Owner(#[error(source)] util::ReadMaybeNullAsciiStringError),
|
||||
}
|
||||
|
||||
/// Error type for [`Bytes::to_bytes`]
|
||||
#[derive(Debug, derive_more::Display, err_impl::Error)]
|
||||
pub enum ToBytesError {
|
||||
/// Unable to write the deck name
|
||||
#[display(fmt = "Unable to write the deck name")]
|
||||
Name(#[error(source)] util::WriteNullAsciiStringError),
|
||||
|
||||
/// Unable to write the deck owner
|
||||
#[display(fmt = "Unable to write the deck owner")]
|
||||
Owner(#[error(source)] util::WriteNullAsciiStringError),
|
||||
}
|
||||
|
||||
impl Bytes for Deck {
|
||||
type ByteArray = [u8; 0x6e];
|
||||
type FromError = FromBytesError;
|
||||
type ToError = ToBytesError;
|
||||
|
||||
fn from_bytes(bytes: &Self::ByteArray) -> Result<Self, Self::FromError> {
|
||||
// Split the bytes
|
||||
let bytes = util::array_split!(&bytes,
|
||||
deck : [0x3c],
|
||||
name : [0x13],
|
||||
owner: [0x13],
|
||||
|
||||
_unknown: [0xc],
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
name: util::read_maybe_null_ascii_string(bytes.name)
|
||||
.map_err(FromBytesError::Name)?
|
||||
.to_ascii_string(),
|
||||
|
||||
owner: util::read_maybe_null_ascii_string(bytes.owner)
|
||||
.map_err(FromBytesError::Owner)?
|
||||
.to_ascii_string(),
|
||||
|
||||
cards: {
|
||||
let mut cards_buf = [0; 0x1e];
|
||||
|
||||
for (card_id, card) in cards_buf.iter_mut().enumerate() {
|
||||
*card = LittleEndian::read_u16(&bytes.deck[0x0 + card_id * 2..0x2 + card_id * 2]);
|
||||
}
|
||||
|
||||
cards_buf
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
fn to_bytes(&self, _bytes: &mut Self::ByteArray) -> Result<(), Self::ToError> {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,9 @@
|
||||
// Std
|
||||
use std::io::{Read, Seek, Write};
|
||||
|
||||
// byteorder
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
|
||||
// Crate
|
||||
use crate::{
|
||||
game::Deck,
|
||||
game::{deck::deck, Bytes, Deck},
|
||||
io::{address::Data, GameFile},
|
||||
};
|
||||
|
||||
@@ -41,14 +38,22 @@ pub enum DeserializeError {
|
||||
/// Unable to read table header
|
||||
#[display(fmt = "Unable to read table header")]
|
||||
ReadHeader(#[error(source)] std::io::Error),
|
||||
/*
|
||||
/// The magic of the table was wrong
|
||||
#[display(fmt = "Found wrong table header magic (expected {:x}, found {:x})", Table::HEADER_MAGIC, "magic")]
|
||||
HeaderMagic { magic: u32 },
|
||||
*/
|
||||
/// Could not read a deck entry from the deck table
|
||||
#[display(fmt = "Unable to fully read a deck entry (The file was too small)")]
|
||||
DeckEntry(#[error(source)] std::io::Error),
|
||||
|
||||
/// Could not read a deck entry
|
||||
#[display(fmt = "Unable to read deck entry with id {}", "id")]
|
||||
ReadDeck {
|
||||
id: usize,
|
||||
#[error(source)]
|
||||
err: std::io::Error,
|
||||
},
|
||||
|
||||
/// Could not parse a deck entry
|
||||
#[display(fmt = "Unable to parse deck entry with id {}", "id")]
|
||||
ParseDeck {
|
||||
id: usize,
|
||||
#[error(source)]
|
||||
err: deck::FromBytesError,
|
||||
},
|
||||
}
|
||||
|
||||
impl Table {
|
||||
@@ -64,25 +69,14 @@ impl Table {
|
||||
.seek(std::io::SeekFrom::Start(u64::from(Self::DECK_TABLE_START_ADDRESS)))
|
||||
.map_err(DeserializeError::Seek)?;
|
||||
|
||||
// Then loop until we're at the end of the table
|
||||
//'table_loop: loop
|
||||
for _ in 0..100 {
|
||||
// Read the deck
|
||||
let mut buf = [0u8; 110];
|
||||
game_file.read_exact(&mut buf).map_err(DeserializeError::DeckEntry)?;
|
||||
// Then get each deck
|
||||
for id in 0..159 {
|
||||
// Read all bytes of the deck
|
||||
let mut bytes = [0; 0x6e];
|
||||
game_file.read_exact(&mut bytes).map_err(|err| DeserializeError::ReadDeck { id, err })?;
|
||||
|
||||
// And construct the deck
|
||||
let deck = Deck {
|
||||
cards: {
|
||||
let mut cards_buf = [0u16; 30];
|
||||
|
||||
for card_id in 0..30 {
|
||||
cards_buf[card_id] = LittleEndian::read_u16(&buf[0x0 + card_id * 2..0x2 + card_id * 2]);
|
||||
}
|
||||
|
||||
cards_buf
|
||||
},
|
||||
};
|
||||
// And try to serialize the deck
|
||||
let deck = Deck::from_bytes(&bytes).map_err(|err| DeserializeError::ParseDeck { id, err })?;
|
||||
|
||||
// And add it
|
||||
decks.push(deck);
|
||||
|
||||
@@ -134,6 +134,28 @@ pub fn read_null_ascii_string(buf: &impl AsRef<[u8]>) -> Result<&ascii::AsciiStr
|
||||
ascii::AsciiStr::from_ascii(buf).map_err(ReadNullAsciiStringError::NotAscii)
|
||||
}
|
||||
|
||||
/// Error type for [`read_maybe_null_ascii_string`]
|
||||
#[derive(Debug)]
|
||||
#[derive(derive_more::Display, err_impl::Error)]
|
||||
pub enum ReadMaybeNullAsciiStringError {
|
||||
/// The string was not ascii
|
||||
#[display(fmt = "The buffer did not contain valid Ascii")]
|
||||
NotAscii(#[error(source)] ascii::AsAsciiStrError),
|
||||
}
|
||||
|
||||
/// Reads a possibly null-terminated ascii string from a buffer.
|
||||
pub fn read_maybe_null_ascii_string(buf: &impl AsRef<[u8]>) -> Result<&ascii::AsciiStr, ReadMaybeNullAsciiStringError> {
|
||||
// Find the first null and trim the buffer until it
|
||||
let buf = buf.as_ref();
|
||||
let buf = match buf.iter().position(|&b| b == 0) {
|
||||
Some(null_idx) => &buf[0..null_idx],
|
||||
None => buf,
|
||||
};
|
||||
|
||||
// Then convert it from Ascii
|
||||
ascii::AsciiStr::from_ascii(buf).map_err(ReadMaybeNullAsciiStringError::NotAscii)
|
||||
}
|
||||
|
||||
/// Error type for [`write_null_ascii_string`]
|
||||
#[derive(Debug)]
|
||||
#[derive(derive_more::Display, err_impl::Error)]
|
||||
|
||||
Reference in New Issue
Block a user