From a756af5f307a6a59e7fbc99068c3e7ba4bdce9af Mon Sep 17 00:00:00 2001 From: jake Date: Sun, 8 Sep 2019 23:43:07 -0700 Subject: [PATCH] character/guildcard structs --- src/character/character.rs | 21 +++++++- src/character/guildcard.rs | 27 ++++++++++ src/packet/login.rs | 100 +++++++++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+), 1 deletion(-) diff --git a/src/character/character.rs b/src/character/character.rs index 6c2cf3f..a2f384a 100644 --- a/src/character/character.rs +++ b/src/character/character.rs @@ -2,7 +2,8 @@ // TODO: section_id to SectionId enum // TODO: techniques to enum? -#[derive(Default)] +#[derive(Default, Copy, Clone, PartialEq, Debug)] +#[repr(C)] pub struct Character { pub atp: u16, pub mst: u16, @@ -75,6 +76,8 @@ impl Character { } } +#[derive(Copy, Clone, PartialEq, Debug)] +#[repr(C)] pub struct SelectScreenCharacter { pub exp: u32, pub level: u32, @@ -102,3 +105,19 @@ pub struct SelectScreenCharacter { pub name: [u16; 16], pub play_time: u32, } + +impl SelectScreenCharacter { + pub const SIZE: usize = 0x7C; + + pub fn from_le_bytes(bytes: [u8; 0x7C]) -> Result { + unsafe { + Ok(std::mem::transmute(bytes)) + } + } + + pub fn to_le_bytes(&self) -> [u8; 0x7C] { + unsafe { + std::mem::transmute(*self) + } + } +} diff --git a/src/character/guildcard.rs b/src/character/guildcard.rs index 82c01dd..6c456c9 100644 --- a/src/character/guildcard.rs +++ b/src/character/guildcard.rs @@ -112,3 +112,30 @@ impl Default for GuildCardData { } } +impl GuildCardData { + pub fn from_bytes(bytes: [u8; 0xD590]) -> GuildCardData { + unsafe { + std::mem::transmute(bytes) + } + } + + pub fn as_bytes(&self) -> [u8; 0xD590] { + unsafe { + std::mem::transmute(*self) + } + } +} + + + +#[cfg(test)] +mod tests { + #[test] + fn guildcard_default_zero() { + let gc = super::GuildCardData::default(); + let bytes = gc.as_bytes(); + for k in bytes.iter() { + assert!(*k == 0); + } + } +} diff --git a/src/packet/login.rs b/src/packet/login.rs index 589faac..988eeac 100644 --- a/src/packet/login.rs +++ b/src/packet/login.rs @@ -1,9 +1,12 @@ use psopacket::pso_packet; use crate::{PSOPacket, PacketParseError}; +use crate::character::character::SelectScreenCharacter; + use std::io::{Read, Seek, SeekFrom}; pub const PATCH_FILE_CHUNK_SIZE: u16 = 0x8000; // 32kb +pub const GUILD_CARD_CHUNK_SIZE: usize = 0x6800; #[allow(non_camel_case_types)] type u8_str = u8; @@ -228,6 +231,103 @@ pub struct CharAck { } +#[pso_packet(0xE5)] +pub struct CharacterPreview { + pub flag: u32, + pub slot: u32, + pub character: SelectScreenCharacter, +} + +#[pso_packet(0x3E8)] +pub struct GuildcardDataRequest { + flag: u32, +} + +#[pso_packet(0x1DC)] +pub struct GuildcardDataHeader { + flag: u32, + one: u32, + len: u32, + checksum: u32, +} + +impl GuildcardDataHeader { + pub fn new(len: usize, checksum: u32) -> GuildcardDataHeader { + GuildcardDataHeader { + flag: 0, + one: 1, + len: len as u32, + checksum: checksum + } + } +} + +#[pso_packet(0x3DC)] +pub struct GuildcardDataChunkRequest { + flag: u32, + _unknown: u32, + pub chunk: u32, + pub again: u32, +} + +pub struct GuildcardDataChunk { + flag: u32, + _unknown: u32, + chunk: u32, + pub buffer: [u8; GUILD_CARD_CHUNK_SIZE], + + len: usize, +} + +impl GuildcardDataChunk { + pub fn new(chunk: u32, buffer: [u8; GUILD_CARD_CHUNK_SIZE], len: usize) -> GuildcardDataChunk { + GuildcardDataChunk { + flag: 0, + _unknown: 0, + chunk: chunk as u32, + buffer: buffer, + len: len, + } + } +} + +impl PSOPacket for GuildcardDataChunk { + fn from_bytes(_data: &[u8]) -> Result { + unimplemented!(); + } + + fn as_bytes(&self) -> Vec { + let mut buf: Vec = Vec::new(); + buf.extend_from_slice(&u32::to_le_bytes(self.flag)); + buf.extend_from_slice(&u32::to_le_bytes(self._unknown)); + buf.extend_from_slice(&u32::to_le_bytes(self.chunk)); + buf.extend_from_slice(&self.buffer[0..self.len]); + while buf.len() % 4 != 0 { + buf.push(0); + } + + let pkt_len = (buf.len() + 4) as u16; + let mut prebuf: Vec = Vec::new(); + prebuf.extend_from_slice(&u16::to_le_bytes(pkt_len)); + prebuf.extend_from_slice(&u16::to_le_bytes(0x2DC)); + prebuf.append(&mut buf); + prebuf + } +} + +impl std::fmt::Debug for GuildcardDataChunk { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "packet GuildcardDataChunk {{\n").unwrap(); + write!(f, " flag: {:?}\n", self.flag).unwrap(); + write!(f, " _unknown: {:X?}\n", self._unknown).unwrap(); + write!(f, " chunk: {:X?}\n", self.chunk).unwrap(); + write!(f, " buffer: [0..{:X}]\n", self.len).unwrap(); + write!(f, "}}") + } +} + + + #[cfg(test)] mod tests { #[test]