mirror of
https://github.com/Zenithsiz/dcb.git
synced 2026-02-09 03:40:23 +00:00
212 lines
6.1 KiB
Rust
212 lines
6.1 KiB
Rust
// Dcb
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Io
|
|
use crate::io::address::Data;
|
|
use crate::io::GameFile;
|
|
|
|
// Game
|
|
//use crate::game::deck::Deck;
|
|
//use crate::game::Bytes;
|
|
//use crate::game::FromBytes;
|
|
//use crate::game::ToBytes;
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
// Read / Write
|
|
use std::io::Read;
|
|
use std::io::Write;
|
|
use std::io::Seek;
|
|
|
|
// byteorder
|
|
use byteorder::ByteOrder;
|
|
use byteorder::LittleEndian;
|
|
|
|
// Macros
|
|
|
|
use serde::Serialize;
|
|
use serde::Deserialize;
|
|
|
|
// Types
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// The decks table, where all decks are stored
|
|
///
|
|
/// # Details
|
|
/// This type serves as an interface to this table, being able to read
|
|
/// and write to it, it is the only type able to do so, as each deck
|
|
/// type may only be converted to and from bytes.
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
pub struct Table
|
|
{
|
|
decks: Vec<Deck>
|
|
}
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
pub struct Deck
|
|
{
|
|
cards: [u16; 30],
|
|
}
|
|
|
|
/// Error type for `Table::new`
|
|
#[derive(Debug, derive_more::Display)]
|
|
pub enum NewError
|
|
{
|
|
/// Could not seek tothe beginning of the deck table
|
|
#[display(fmt = "Could not seek to the beginning of the deck table")]
|
|
SeekTableBegin( std::io::Error ),
|
|
|
|
|
|
|
|
/// 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( std::io::Error ),
|
|
|
|
|
|
/*
|
|
/// Could not constructs a deck
|
|
#[display(fmt = "Could not construct a deck from the deck table")]
|
|
DeckConstruction( crate::game::deck::deck::FromBytesError ),
|
|
*/
|
|
|
|
|
|
/// Could not read the next entry info
|
|
#[display(fmt = "Unable to fully read next entry info (The file was too small)")]
|
|
NextEntryInfo( std::io::Error ),
|
|
|
|
/*
|
|
/// The deck table was malformed
|
|
#[display(fmt = "The deck table is malformed")]
|
|
MalformedTable( crate::game::deck::property::deck_type::UnknownDeckType ),
|
|
*/
|
|
}
|
|
|
|
impl std::error::Error for NewError {
|
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
|
match self {
|
|
Self::SeekTableBegin(err) |
|
|
Self::DeckEntry(err) |
|
|
Self::NextEntryInfo(err) => Some(err),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Error type for `Table::write_to_file`
|
|
#[derive(Debug, derive_more::Display)]
|
|
pub enum WriteError
|
|
{
|
|
/// The deck table was too big
|
|
#[display(fmt = "The deck table was too big (is {}, should be 65536 max)", _0)]
|
|
TooManyDeck( usize ),
|
|
|
|
/*
|
|
/// Unable to convert a deck to bytes
|
|
#[display(fmt = "Unable to convert deck with id {} to bytes", id)]
|
|
UnableToConvertDeckToBytes {
|
|
id: u16,
|
|
err: crate::game::deck::deck::ToBytesError,
|
|
},
|
|
|
|
/// Unable to write deck entry
|
|
#[display(fmt = "Unable to write deck entry with id {}", id)]
|
|
UnableToWriteDeckEntry {
|
|
id: u16,
|
|
err: std::io::Error,
|
|
},
|
|
*/
|
|
}
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
// Impl
|
|
//--------------------------------------------------------------------------------------------------
|
|
impl Table
|
|
{
|
|
// Constants
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// The start address of the decks table
|
|
const DECK_TABLE_START_ADDRESS : Data = Data::from_u64(0x21a6808);
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
// Constructors
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Reads the deck table from a dcb bin file
|
|
pub fn new<F>(game_file: &mut GameFile<F>) -> Result<Self, NewError>
|
|
where
|
|
F: Read + Write + Seek
|
|
{
|
|
// The deck array
|
|
let mut decks = vec![];
|
|
|
|
|
|
// Seek to the beginning of the deck table
|
|
game_file.seek( std::io::SeekFrom::Start( u64::from( Self::DECK_TABLE_START_ADDRESS) ) ).map_err(NewError::SeekTableBegin)?;
|
|
|
|
// 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(NewError::DeckEntry)?;
|
|
|
|
// 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 add it
|
|
decks.push(deck);
|
|
}
|
|
|
|
// And return the table
|
|
Ok( Self {
|
|
decks,
|
|
})
|
|
}
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
// Write
|
|
//--------------------------------------------------------------------------------------------------
|
|
/*
|
|
/// Writes this table to a dcb bin file
|
|
pub fn write_to_file<F>(&self, _game_file: &mut GameFile<F>) -> Result<(), WriteError>
|
|
where
|
|
F: Read + Write + Seek
|
|
{
|
|
/*
|
|
// If the table length is bigger than 0xFFFF, return err
|
|
if self.decks.len() > 0xFFFF { return Err( TableWriteError::TooManyDeck( self.decks.len() ) ); }
|
|
|
|
// Go through all deck and write them
|
|
// Note: We write them in the order they appear in the array,
|
|
// because this is the same way we read them.
|
|
for (id, deck) in self.decks.iter().enumerate()
|
|
{
|
|
// Convert `id` to a u16
|
|
let id = id as u16;
|
|
|
|
// Get the bytes
|
|
let mut bytes = [0u8; Deck::BUF_BYTE_SIZE];
|
|
deck.to_bytes(&mut bytes).map_err(|err| TableWriteError::UnableToConvertDeckToBytes{id, err})?;
|
|
|
|
// Seek to the right address in the table
|
|
Self::seek_deck_table(game_file, id as u16)?;
|
|
|
|
// And write the deck buffer
|
|
game_file.write_all(&bytes).map_err(|err| TableWriteError::UnableToWriteDeckEntry{id, err})?;
|
|
}
|
|
*/
|
|
|
|
Ok(())
|
|
}
|
|
*/
|
|
//--------------------------------------------------------------------------------------------------
|
|
}
|
|
//--------------------------------------------------------------------------------------------------
|