Compare commits
1 Commits
master
...
stabilized
Author | SHA1 | Date | |
---|---|---|---|
048e947763 |
31
.drone.yml
31
.drone.yml
@ -3,23 +3,8 @@ kind: pipeline
|
|||||||
type: docker
|
type: docker
|
||||||
name: test libpso
|
name: test libpso
|
||||||
|
|
||||||
concurrency:
|
|
||||||
limit: 1
|
|
||||||
|
|
||||||
environment:
|
|
||||||
CARGO_INCREMENTAL: false
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: clean cache
|
- name: cargo build
|
||||||
image: rustlang/rust:nightly
|
|
||||||
volumes:
|
|
||||||
- name: cache
|
|
||||||
path: /usr/local/cargo
|
|
||||||
- name: target-cache
|
|
||||||
path: /drone/src/target
|
|
||||||
commands:
|
|
||||||
- cargo prune
|
|
||||||
- name: build
|
|
||||||
image: rustlang/rust:nightly
|
image: rustlang/rust:nightly
|
||||||
volumes:
|
volumes:
|
||||||
- name: cache
|
- name: cache
|
||||||
@ -28,7 +13,7 @@ steps:
|
|||||||
path: /drone/src/target
|
path: /drone/src/target
|
||||||
commands:
|
commands:
|
||||||
- cargo build
|
- cargo build
|
||||||
- name: clippy!
|
- name: cargo test
|
||||||
image: rustlang/rust:nightly
|
image: rustlang/rust:nightly
|
||||||
volumes:
|
volumes:
|
||||||
- name: cache
|
- name: cache
|
||||||
@ -36,16 +21,7 @@ steps:
|
|||||||
- name: target-cache
|
- name: target-cache
|
||||||
path: /drone/src/target
|
path: /drone/src/target
|
||||||
commands:
|
commands:
|
||||||
- cargo clippy -- --deny warnings
|
- cargo test
|
||||||
- name: test
|
|
||||||
image: rustlang/rust:nightly
|
|
||||||
volumes:
|
|
||||||
- name: cache
|
|
||||||
path: /usr/local/cargo
|
|
||||||
- name: target-cache
|
|
||||||
path: /drone/src/target
|
|
||||||
commands:
|
|
||||||
- cargo test --jobs 1
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
- name: cache
|
- name: cache
|
||||||
@ -54,3 +30,4 @@ volumes:
|
|||||||
- name: target-cache
|
- name: target-cache
|
||||||
host:
|
host:
|
||||||
path: /home/drone/cargo-cache
|
path: /home/drone/cargo-cache
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libpso"
|
name = "libpso"
|
||||||
version = "0.0.1"
|
version = "0.1.0"
|
||||||
authors = ["Jake Probst <jake.probst@gmail.com>"]
|
authors = ["Jake Probst <jake.probst@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "psopacket"
|
name = "psopacket"
|
||||||
version = "0.0.1"
|
version = "1.0.0"
|
||||||
authors = ["Jake Probst <jake.probst@gmail.com>"]
|
authors = ["Jake Probst <jake.probst@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
@ -149,14 +149,14 @@ fn generate_psopacket_impl(pkt_cmd: u16, name: syn::Ident, attrs: &Vec<AttrType>
|
|||||||
fn from_bytes(data: &[u8]) -> Result<#name, PacketParseError> {
|
fn from_bytes(data: &[u8]) -> Result<#name, PacketParseError> {
|
||||||
let mut cur = std::io::Cursor::new(data);
|
let mut cur = std::io::Cursor::new(data);
|
||||||
let mut b: [u8; 2] = [0; 2];
|
let mut b: [u8; 2] = [0; 2];
|
||||||
cur.read_exact(&mut b).unwrap();
|
cur.read(&mut b).unwrap();
|
||||||
let len = u16::from_le_bytes(b);
|
let len = u16::from_le_bytes(b);
|
||||||
cur.read_exact(&mut b).unwrap();
|
cur.read(&mut b).unwrap();
|
||||||
let cmd = u16::from_le_bytes(b);
|
let cmd = u16::from_le_bytes(b);
|
||||||
let mut f: [u8; 4] = [0; 4];
|
let mut f: [u8; 4] = [0; 4];
|
||||||
|
|
||||||
let flag = if #include_flag {
|
let flag = if #include_flag {
|
||||||
cur.read_exact(&mut f).unwrap();
|
cur.read(&mut f).unwrap();
|
||||||
u32::from_le_bytes(f)
|
u32::from_le_bytes(f)
|
||||||
}
|
}
|
||||||
else { 0 };
|
else { 0 };
|
||||||
@ -205,59 +205,55 @@ fn generate_psopacket_impl(pkt_cmd: u16, name: syn::Ident, attrs: &Vec<AttrType>
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn generate_debug_impl(name: syn::Ident, attrs: &Vec<AttrType>) -> proc_macro2::TokenStream {
|
fn generate_debug_impl(name: syn::Ident, attrs: &Vec<AttrType>) -> proc_macro2::TokenStream {
|
||||||
let dbg_write = attrs
|
let mut dbg_write = Vec::new();
|
||||||
.iter()
|
for attr in attrs {
|
||||||
.map(|attr| {
|
let element = match attr {
|
||||||
match attr {
|
AttrType::Value(ty, name, meta) => {
|
||||||
AttrType::Value(ty, name, meta) => {
|
let ident_str = name.to_string();
|
||||||
let ident_str = name.to_string();
|
let type_str = ty.path.segments[0].ident.to_string();
|
||||||
let type_str = ty.path.segments[0].ident.to_string();
|
match meta {
|
||||||
match meta {
|
AttrMeta::NoDebug => quote! {
|
||||||
AttrMeta::NoDebug => quote! {
|
write!(f, " {} {}: [...]\n", #ident_str, #type_str)?;
|
||||||
.field(&format!("{} [{}]", #ident_str, #type_str), &format_args!("[...]"))
|
},
|
||||||
},
|
_ => quote! {
|
||||||
_ => quote! {
|
write!(f, " {} {}: {:?}\n", #ident_str, #type_str, self.#name)?;
|
||||||
.field(&format!("{} [{}]", #ident_str, #type_str), &self.#name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
AttrType::Array(ty, name, len, meta) => {
|
|
||||||
let ident_str = name.to_string();
|
|
||||||
let type_str = ty.path.segments[0].ident.to_string();
|
|
||||||
match meta {
|
|
||||||
AttrMeta::Utf8 => quote! {
|
|
||||||
.field(&format!("{} [utf8; {}]", #ident_str, #len),
|
|
||||||
match std::str::from_utf8(&self.#name) {
|
|
||||||
Ok(ref s) => s,
|
|
||||||
Err(_) => &self.#name
|
|
||||||
})
|
|
||||||
},
|
|
||||||
AttrMeta::Utf16 => quote! {
|
|
||||||
.field(&format!("{} [utf16; {}]", #ident_str, #len),
|
|
||||||
match std::str::from_utf16(&self.#name) {
|
|
||||||
Ok(ref s) => s,
|
|
||||||
Err(_) => &self.#name
|
|
||||||
})
|
|
||||||
},
|
|
||||||
AttrMeta::NoDebug => quote! {
|
|
||||||
.field(&format!("{} [{}; {}]", #ident_str, #type_str, #len), &format_args!("[...]"))
|
|
||||||
},
|
|
||||||
_ => quote! {
|
|
||||||
.field(&format!("{} [{}; {}]", #ident_str, #type_str, #len), &format_args!("{:?}", &self.#name))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
AttrType::Array(ty, name, len, meta) => {
|
||||||
|
let ident_str = name.to_string();
|
||||||
|
let type_str = ty.path.segments[0].ident.to_string();
|
||||||
|
match meta {
|
||||||
|
AttrMeta::Utf8 => quote! {
|
||||||
|
match std::str::from_utf8(&self.#name) {
|
||||||
|
Ok(v) => write!(f, " {} [utf8; {}]: {:?}\n", #ident_str, #len, v)?,
|
||||||
|
Err(_) => write!(f, " {} [{}; {}]: {:?}\n", #ident_str, #type_str, #len, self.#name.to_vec())?,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
AttrMeta::Utf16 => quote! {
|
||||||
|
match String::from_utf16(&self.#name) {
|
||||||
|
Ok(v) => write!(f, " {} [utf16; {}]: {:?}\n", #ident_str, #len, v)?,
|
||||||
|
Err(_) => write!(f, " {} [{}; {}]: {:?}\n", #ident_str, #type_str, #len, self.#name.to_vec())?,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
AttrMeta::NoDebug => quote! {
|
||||||
|
write!(f, " {} [{}; {}]: [...]\n", #ident_str, #type_str, #len)?;
|
||||||
|
},
|
||||||
|
_ => quote! {
|
||||||
|
write!(f, " {} [{}; {}]: {:?}\n", #ident_str, #type_str, #len, self.#name.to_vec())?;
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
};
|
||||||
.collect::<Vec<_>>();
|
dbg_write.push(element);
|
||||||
|
}
|
||||||
let name_str = name.to_string();
|
let name_str = name.to_string();
|
||||||
quote! {
|
quote! {
|
||||||
impl std::fmt::Debug for #name {
|
impl std::fmt::Debug for #name {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
f.debug_struct(#name_str)
|
write!(f, "{} {{\n", #name_str)?;
|
||||||
#(#dbg_write)*
|
#(#dbg_write)*
|
||||||
.finish()
|
write!(f, "}}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -542,9 +538,9 @@ fn generate_psomessage_impl(msg_cmd: u8, name: syn::Ident, attrs: &Vec<AttrType>
|
|||||||
const CMD: u8 = #msg_cmd;
|
const CMD: u8 = #msg_cmd;
|
||||||
fn from_bytes<R: std::io::Read + std::io::Seek >(mut cur: &mut R) -> Result<#name, PacketParseError> {
|
fn from_bytes<R: std::io::Read + std::io::Seek >(mut cur: &mut R) -> Result<#name, PacketParseError> {
|
||||||
let mut buf1 = [0u8; 1];
|
let mut buf1 = [0u8; 1];
|
||||||
cur.read_exact(&mut buf1).unwrap();
|
cur.read(&mut buf1).unwrap();
|
||||||
let cmd = buf1[0];
|
let cmd = buf1[0];
|
||||||
cur.read_exact(&mut buf1).unwrap();
|
cur.read(&mut buf1).unwrap();
|
||||||
let size = buf1[0];
|
let size = buf1[0];
|
||||||
|
|
||||||
let mut subbuf = vec![0u8; size as usize * 4 - 2];
|
let mut subbuf = vec![0u8; size as usize * 4 - 2];
|
||||||
|
@ -3,6 +3,91 @@
|
|||||||
// TODO: techniques to enum
|
// TODO: techniques to enum
|
||||||
use psopacket::PSOPacketData;
|
use psopacket::PSOPacketData;
|
||||||
use crate::{PSOPacketData, PacketParseError};
|
use crate::{PSOPacketData, PacketParseError};
|
||||||
|
//use crate::PSOPacketData;
|
||||||
|
|
||||||
|
pub const DEFAULT_PALETTE_CONFIG: [u8; 0xE8] = [
|
||||||
|
0, 0, 0, 0,
|
||||||
|
1, 0, 0, 0,
|
||||||
|
2, 0, 1, 0,
|
||||||
|
2, 1, 1, 0,
|
||||||
|
4, 0, 1, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
1, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0
|
||||||
|
];
|
||||||
|
|
||||||
|
pub const DEFAULT_TECH_MENU: [u8; 40] = [
|
||||||
|
0x00, 0x00,
|
||||||
|
0x06, 0x00,
|
||||||
|
0x03, 0x00,
|
||||||
|
0x01, 0x00,
|
||||||
|
0x07, 0x00,
|
||||||
|
0x04, 0x00,
|
||||||
|
0x02, 0x00,
|
||||||
|
0x08, 0x00,
|
||||||
|
0x05, 0x00,
|
||||||
|
0x09, 0x00,
|
||||||
|
0x12, 0x00,
|
||||||
|
0x0f, 0x00,
|
||||||
|
0x10, 0x00,
|
||||||
|
0x11, 0x00,
|
||||||
|
0x0d, 0x00,
|
||||||
|
0x0a, 0x00,
|
||||||
|
0x0b, 0x00,
|
||||||
|
0x0c, 0x00,
|
||||||
|
0x0e, 0x00,
|
||||||
|
0x00, 0x00,
|
||||||
|
];
|
||||||
|
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
|
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
@ -138,7 +223,7 @@ impl std::default::Default for Character {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PSOPacketData, Default)]
|
#[derive(Copy, Clone, Debug, PartialEq, Default)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct SelectScreenCharacter {
|
pub struct SelectScreenCharacter {
|
||||||
pub exp: u32,
|
pub exp: u32,
|
||||||
@ -169,6 +254,20 @@ pub struct SelectScreenCharacter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SelectScreenCharacter {
|
impl SelectScreenCharacter {
|
||||||
|
pub const SIZE: usize = 0x7C;
|
||||||
|
|
||||||
|
pub fn from_le_bytes(bytes: [u8; 0x7C]) -> Result<SelectScreenCharacter, crate::PacketParseError> {
|
||||||
|
unsafe {
|
||||||
|
Ok(std::mem::transmute(bytes))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_le_bytes(&self) -> [u8; 0x7C] {
|
||||||
|
unsafe {
|
||||||
|
std::mem::transmute(*self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn as_character(&self) -> Character {
|
pub fn as_character(&self) -> Character {
|
||||||
Character {
|
Character {
|
||||||
exp: self.exp,
|
exp: self.exp,
|
||||||
@ -258,8 +357,8 @@ impl std::default::Default for Bank {
|
|||||||
#[derive(PSOPacketData, Copy, Clone)]
|
#[derive(PSOPacketData, Copy, Clone)]
|
||||||
pub struct KeyTeamConfig {
|
pub struct KeyTeamConfig {
|
||||||
pub _unknown: [u8; 0x114],
|
pub _unknown: [u8; 0x114],
|
||||||
pub keyboard_config: [u8; 0x16C],
|
pub key_config: [u8; 0x16C],
|
||||||
pub gamepad_config: [u8; 0x38],
|
pub joystick_config: [u8; 0x38],
|
||||||
pub guildcard: u32,
|
pub guildcard: u32,
|
||||||
pub team_id: u32,
|
pub team_id: u32,
|
||||||
pub team_info: [u32; 2],
|
pub team_info: [u32; 2],
|
||||||
@ -339,8 +438,8 @@ pub struct DBChar {
|
|||||||
#[derive(PSOPacketData, Copy, Clone)]
|
#[derive(PSOPacketData, Copy, Clone)]
|
||||||
pub struct DBOpts {
|
pub struct DBOpts {
|
||||||
pub blocked: [u32; 30],
|
pub blocked: [u32; 30],
|
||||||
pub keyboard_config: [u8; 0x16C],
|
pub key_config: [u8; 0x16C],
|
||||||
pub gamepad_config: [u8; 0x38],
|
pub joystick_config: [u8; 0x38],
|
||||||
pub option_flags: u32,
|
pub option_flags: u32,
|
||||||
pub shortcuts: [u8; 0xA40],
|
pub shortcuts: [u8; 0xA40],
|
||||||
pub symbol_chats: [u8; 0x4E0],
|
pub symbol_chats: [u8; 0x4E0],
|
||||||
|
@ -1,22 +1,53 @@
|
|||||||
use crate::packet::ship::{GuildcardAccept};
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
#[repr(C)]
|
/*
|
||||||
pub struct BlockedGuildCard { // 264
|
typedef struct bb_guildcard_data {
|
||||||
pub id: u32, // 4
|
uint8_t unk1[0x0114];
|
||||||
pub name: [u16; 0x18], // 48
|
struct {
|
||||||
pub team: [u16; 0x10], // 32
|
uint32_t guildcard;
|
||||||
pub desc: [u16; 0x58], // 176
|
uint16_t name[0x18];
|
||||||
pub reserved1: u8, // 1
|
uint16_t team[0x10];
|
||||||
pub language: u8, // 1
|
uint16_t desc[0x58];
|
||||||
pub section_id: u8, // 1
|
uint8_t reserved1;
|
||||||
pub class: u8, // 1
|
uint8_t language;
|
||||||
|
uint8_t section;
|
||||||
|
uint8_t ch_class;
|
||||||
|
} blocked[29];
|
||||||
|
uint8_t unk2[0x78];
|
||||||
|
struct {
|
||||||
|
uint32_t guildcard;
|
||||||
|
uint16_t name[0x18];
|
||||||
|
uint16_t team[0x10];
|
||||||
|
uint16_t desc[0x58];
|
||||||
|
uint8_t reserved1;
|
||||||
|
uint8_t language;
|
||||||
|
uint8_t section;
|
||||||
|
uint8_t ch_class;
|
||||||
|
uint32_t padding;
|
||||||
|
uint16_t comment[0x58];
|
||||||
|
} entries[104];
|
||||||
|
uint8_t unk3[0x01BC];
|
||||||
|
} bb_gc_data_t;
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct BlockedGuildCard {
|
||||||
|
pub guildcard: u32,
|
||||||
|
pub name: [u16; 0x18],
|
||||||
|
pub team: [u16; 0x10],
|
||||||
|
pub desc: [u16; 0x58],
|
||||||
|
pub reserved1: u8,
|
||||||
|
pub language: u8,
|
||||||
|
pub section_id: u8,
|
||||||
|
pub class: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for BlockedGuildCard {
|
impl Default for BlockedGuildCard {
|
||||||
fn default() -> BlockedGuildCard {
|
fn default() -> BlockedGuildCard {
|
||||||
BlockedGuildCard {
|
BlockedGuildCard {
|
||||||
id: 0,
|
guildcard: 0,
|
||||||
name: [0; 0x18],
|
name: [0; 0x18],
|
||||||
team: [0; 0x10],
|
team: [0; 0x10],
|
||||||
desc: [0; 0x58],
|
desc: [0; 0x58],
|
||||||
@ -28,41 +59,25 @@ impl Default for BlockedGuildCard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<GuildCard> for BlockedGuildCard {
|
#[derive(Copy, Clone)]
|
||||||
fn from(g: GuildCard) -> BlockedGuildCard {
|
pub struct GuildCard {
|
||||||
BlockedGuildCard {
|
pub guildcard: u32,
|
||||||
id: g.id,
|
pub name: [u16; 0x18],
|
||||||
name: g.name,
|
pub team: [u16; 0x10],
|
||||||
team: g.team,
|
pub desc: [u16; 0x58],
|
||||||
desc: g.desc,
|
pub reserved1: u8,
|
||||||
reserved1: g.reserved1,
|
pub language: u8,
|
||||||
language: g.language,
|
pub section_id: u8,
|
||||||
section_id: g.section_id,
|
pub class: u8,
|
||||||
class: g.class,
|
pub padding: u32,
|
||||||
}
|
pub comment: [u16; 0x58],
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct GuildCard { // 444
|
|
||||||
pub id: u32, // 4
|
|
||||||
pub name: [u16; 0x18], // 48
|
|
||||||
pub team: [u16; 0x10], // 32
|
|
||||||
pub desc: [u16; 0x58], // 176
|
|
||||||
pub reserved1: u8, // 1
|
|
||||||
pub language: u8, // 1
|
|
||||||
pub section_id: u8, // 1
|
|
||||||
pub class: u8, // 1
|
|
||||||
pub padding: u32, // 4
|
|
||||||
pub comment: [u16; 0x58], // 176
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Default for GuildCard {
|
impl Default for GuildCard {
|
||||||
fn default() -> GuildCard {
|
fn default() -> GuildCard {
|
||||||
GuildCard {
|
GuildCard {
|
||||||
id: 0,
|
guildcard: 0,
|
||||||
name: [0; 0x18],
|
name: [0; 0x18],
|
||||||
team: [0; 0x10],
|
team: [0; 0x10],
|
||||||
desc: [0; 0x58],
|
desc: [0; 0x58],
|
||||||
@ -76,30 +91,13 @@ impl Default for GuildCard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&GuildcardAccept> for GuildCard {
|
#[derive(Copy, Clone)]
|
||||||
fn from(g: &GuildcardAccept) -> GuildCard {
|
pub struct GuildCardData {
|
||||||
GuildCard {
|
pub _unknown1: [u8; 0x114],
|
||||||
id: g.id,
|
pub blocked: [BlockedGuildCard; 29],
|
||||||
name: g.name,
|
pub _unknown2: [u8; 0x78],
|
||||||
team: g.team,
|
pub friends: [GuildCard; 104],
|
||||||
desc: g.desc,
|
pub _unknown3: [u8; 0x1BC],
|
||||||
reserved1: g.one,
|
|
||||||
language: g.language,
|
|
||||||
section_id: g.section_id,
|
|
||||||
class: g.class,
|
|
||||||
padding: 0,
|
|
||||||
comment: [0; 0x58],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct GuildCardData { // 54672 0xd590
|
|
||||||
pub _unknown1: [u8; 0x114], // 276
|
|
||||||
pub blocked: [BlockedGuildCard; 29], // 264 * 29 = 7656
|
|
||||||
pub _unknown2: [u8; 0x78], // 120
|
|
||||||
pub friends: [GuildCard; 105], // 444 * 105 = 46620
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for GuildCardData {
|
impl Default for GuildCardData {
|
||||||
@ -108,7 +106,8 @@ impl Default for GuildCardData {
|
|||||||
_unknown1: [0; 0x114],
|
_unknown1: [0; 0x114],
|
||||||
blocked: [BlockedGuildCard::default(); 29],
|
blocked: [BlockedGuildCard::default(); 29],
|
||||||
_unknown2: [0; 0x78],
|
_unknown2: [0; 0x78],
|
||||||
friends: [GuildCard::default(); 105],
|
friends: [GuildCard::default(); 104],
|
||||||
|
_unknown3: [0; 0x1BC],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
#![allow(clippy::module_inception)]
|
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
pub mod character;
|
pub mod character;
|
||||||
pub mod guildcard;
|
pub mod guildcard;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// TODO: deblobify all of this
|
// TODO: deblobify all of this
|
||||||
|
|
||||||
pub const DEFAULT_KEYBOARD_CONFIG1: [u8; 0x16C] = [
|
const DEFAULT_KEY_CONFIG: [u8; 0x16C] = [
|
||||||
0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00,
|
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00,
|
||||||
@ -39,128 +39,7 @@ pub const DEFAULT_KEYBOARD_CONFIG1: [u8; 0x16C] = [
|
|||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
|
||||||
0x01, 0x00, 0x00, 0x00
|
0x01, 0x00, 0x00, 0x00
|
||||||
];
|
];
|
||||||
|
const DEFAULT_JOYSTICK_CONFIG: [u8; 0x38] = [
|
||||||
pub const DEFAULT_KEYBOARD_CONFIG2: [u8; 364] = [
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
|
|
||||||
0x01, 0x00, 0x00, 0x00
|
|
||||||
];
|
|
||||||
|
|
||||||
pub const DEFAULT_KEYBOARD_CONFIG3: [u8; 364] = [
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
|
|
||||||
0x01, 0x00, 0x00, 0x00
|
|
||||||
];
|
|
||||||
|
|
||||||
pub const DEFAULT_KEYBOARD_CONFIG4: [u8; 364] = [
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
|
|
||||||
0x01, 0x00, 0x00, 0x00
|
|
||||||
];
|
|
||||||
|
|
||||||
pub const DEFAULT_GAMEPAD_CONFIG: [u8; 0x38] = [
|
|
||||||
0x00, 0x01, 0xff, 0xff, 0x00, 0x00,
|
0x00, 0x01, 0xff, 0xff, 0x00, 0x00,
|
||||||
0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00,
|
0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00,
|
||||||
0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00,
|
0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00,
|
||||||
@ -297,96 +176,12 @@ const DEFAULT_SYMBOLCHATS: [u8; 0x4E0] = [
|
|||||||
0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00
|
0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00
|
||||||
];
|
];
|
||||||
|
|
||||||
pub const DEFAULT_PALETTE_CONFIG: [u8; 0xE8] = [
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x01, 0x00, 0x00, 0x00,
|
|
||||||
0x02, 0x00, 0x01, 0x00,
|
|
||||||
0x02, 0x01, 0x01, 0x00,
|
|
||||||
0x04, 0x00, 0x01, 0x00,
|
|
||||||
0x00, 0x00, 0x01, 0x00,
|
|
||||||
0x00, 0x00, 0x01, 0x00,
|
|
||||||
0x00, 0x00, 0x01, 0x00,
|
|
||||||
0x00, 0x00, 0x01, 0x00,
|
|
||||||
0x00, 0x00, 0x01, 0x00,
|
|
||||||
0x00, 0x00, 0x01, 0x00,
|
|
||||||
0x00, 0x00, 0x01, 0x00,
|
|
||||||
0x00, 0x00, 0x01, 0x00,
|
|
||||||
0x00, 0x00, 0x01, 0x00,
|
|
||||||
0x00, 0x00, 0x01, 0x00,
|
|
||||||
0x01, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00
|
|
||||||
];
|
|
||||||
|
|
||||||
pub const DEFAULT_TECH_MENU: [u8; 40] = [
|
|
||||||
0x00, 0x00,
|
|
||||||
0x06, 0x00,
|
|
||||||
0x03, 0x00,
|
|
||||||
0x01, 0x00,
|
|
||||||
0x07, 0x00,
|
|
||||||
0x04, 0x00,
|
|
||||||
0x02, 0x00,
|
|
||||||
0x08, 0x00,
|
|
||||||
0x05, 0x00,
|
|
||||||
0x09, 0x00,
|
|
||||||
0x12, 0x00,
|
|
||||||
0x0f, 0x00,
|
|
||||||
0x10, 0x00,
|
|
||||||
0x11, 0x00,
|
|
||||||
0x0d, 0x00,
|
|
||||||
0x0a, 0x00,
|
|
||||||
0x0b, 0x00,
|
|
||||||
0x0c, 0x00,
|
|
||||||
0x0e, 0x00,
|
|
||||||
0x00, 0x00,
|
|
||||||
];
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct UserSettings {
|
pub struct UserSettings {
|
||||||
pub blocked_users: [u32; 0x1E],
|
pub blocked_users: [u32; 0x1E],
|
||||||
pub keyboard_config: [u8; 0x16C],
|
pub key_config: [u8; 0x16C],
|
||||||
pub gamepad_config: [u8; 0x38],
|
pub joystick_config: [u8; 0x38],
|
||||||
pub option_flags: u32,
|
pub option_flags: u32,
|
||||||
pub shortcuts: [u8; 0xA40],
|
pub shortcuts: [u8; 0xA40],
|
||||||
pub symbol_chats: [u8; 0x4E0],
|
pub symbol_chats: [u8; 0x4E0],
|
||||||
@ -398,8 +193,8 @@ impl Default for UserSettings {
|
|||||||
fn default() -> UserSettings {
|
fn default() -> UserSettings {
|
||||||
UserSettings {
|
UserSettings {
|
||||||
blocked_users: [0; 0x1E],
|
blocked_users: [0; 0x1E],
|
||||||
keyboard_config: DEFAULT_KEYBOARD_CONFIG1,
|
key_config: DEFAULT_KEY_CONFIG,
|
||||||
gamepad_config: DEFAULT_GAMEPAD_CONFIG,
|
joystick_config: DEFAULT_JOYSTICK_CONFIG,
|
||||||
option_flags: 0,
|
option_flags: 0,
|
||||||
shortcuts: [0; 0xA40],
|
shortcuts: [0; 0xA40],
|
||||||
symbol_chats: DEFAULT_SYMBOLCHATS,
|
symbol_chats: DEFAULT_SYMBOLCHATS,
|
||||||
|
@ -48,7 +48,7 @@ impl PSOBBCipher {
|
|||||||
for k in cipher.p_array.iter_mut() {
|
for k in cipher.p_array.iter_mut() {
|
||||||
let mut pt = *k as u16;
|
let mut pt = *k as u16;
|
||||||
pt = ((pt & 0x00FF) << 8) + ((pt & 0xFF00) >> 8);
|
pt = ((pt & 0x00FF) << 8) + ((pt & 0xFF00) >> 8);
|
||||||
*k = (((*k >> 16) ^ pt as u32) << 16) + pt as u32;
|
*k = ((((*k >> 16) ^ pt as u32) << 16)) + pt as u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 0..18 {
|
for i in 0..18 {
|
||||||
@ -85,7 +85,7 @@ impl PSOBBCipher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PSOCipher for PSOBBCipher {
|
impl PSOCipher for PSOBBCipher {
|
||||||
fn encrypt(&mut self, data: &[u8]) -> Result<Vec<u8>, CipherError> {
|
fn encrypt(&mut self, data: &Vec<u8>) -> Result<Vec<u8>, CipherError> {
|
||||||
let mut real_data = data.chunks(4).map(|k| {
|
let mut real_data = data.chunks(4).map(|k| {
|
||||||
u32::from_le_bytes([k[0], k[1], k[2], k[3]])
|
u32::from_le_bytes([k[0], k[1], k[2], k[3]])
|
||||||
}).collect::<Vec<_>>();
|
}).collect::<Vec<_>>();
|
||||||
@ -106,7 +106,9 @@ impl PSOCipher for PSOBBCipher {
|
|||||||
l ^= self.p_array[4];
|
l ^= self.p_array[4];
|
||||||
r ^= self.p_array[5];
|
r ^= self.p_array[5];
|
||||||
|
|
||||||
std::mem::swap(&mut l, &mut r);
|
let tmp = l;
|
||||||
|
l = r;
|
||||||
|
r = tmp;
|
||||||
|
|
||||||
result.extend_from_slice(&l.to_le_bytes());
|
result.extend_from_slice(&l.to_le_bytes());
|
||||||
result.extend_from_slice(&r.to_le_bytes());
|
result.extend_from_slice(&r.to_le_bytes());
|
||||||
@ -115,7 +117,7 @@ impl PSOCipher for PSOBBCipher {
|
|||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decrypt(&mut self, data: &[u8]) -> Result<Vec<u8>, CipherError> {
|
fn decrypt(&mut self, data: &Vec<u8>) -> Result<Vec<u8>, CipherError> {
|
||||||
if data.len() % 8 != 0 {
|
if data.len() % 8 != 0 {
|
||||||
return Err(CipherError::InvalidSize);
|
return Err(CipherError::InvalidSize);
|
||||||
}
|
}
|
||||||
@ -137,8 +139,9 @@ impl PSOCipher for PSOBBCipher {
|
|||||||
l ^= self.p_array[1];
|
l ^= self.p_array[1];
|
||||||
r ^= self.p_array[0];
|
r ^= self.p_array[0];
|
||||||
|
|
||||||
|
let tmp = l;
|
||||||
std::mem::swap(&mut l, &mut r);
|
l = r;
|
||||||
|
r = tmp;
|
||||||
|
|
||||||
result.extend_from_slice(&l.to_le_bytes());
|
result.extend_from_slice(&l.to_le_bytes());
|
||||||
result.extend_from_slice(&r.to_le_bytes());
|
result.extend_from_slice(&r.to_le_bytes());
|
||||||
|
@ -10,8 +10,8 @@ pub enum CipherError {
|
|||||||
|
|
||||||
|
|
||||||
pub trait PSOCipher {
|
pub trait PSOCipher {
|
||||||
fn encrypt(&mut self, data: &[u8]) -> Result<Vec<u8>, CipherError>;
|
fn encrypt(&mut self, data: &Vec<u8>) -> Result<Vec<u8>, CipherError>;
|
||||||
fn decrypt(&mut self, data: &[u8]) -> Result<Vec<u8>, CipherError>;
|
fn decrypt(&mut self, data: &Vec<u8>) -> Result<Vec<u8>, CipherError>;
|
||||||
fn header_size(&self) -> usize;
|
fn header_size(&self) -> usize;
|
||||||
fn block_size(&self) -> usize {
|
fn block_size(&self) -> usize {
|
||||||
self.header_size()
|
self.header_size()
|
||||||
@ -24,12 +24,12 @@ pub struct NullCipher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PSOCipher for NullCipher {
|
impl PSOCipher for NullCipher {
|
||||||
fn encrypt(&mut self, data: &[u8]) -> Result<Vec<u8>, CipherError> {
|
fn encrypt(&mut self, data: &Vec<u8>) -> Result<Vec<u8>, CipherError> {
|
||||||
Ok(data.to_vec())
|
Ok(data.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decrypt(&mut self, data: &[u8]) -> Result<Vec<u8>, CipherError> {
|
fn decrypt(&mut self, data: &Vec<u8>) -> Result<Vec<u8>, CipherError> {
|
||||||
Ok(data.to_vec())
|
Ok(data.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn header_size(&self) -> usize {
|
fn header_size(&self) -> usize {
|
||||||
|
@ -31,15 +31,15 @@ impl PSOPCCipher {
|
|||||||
eax = edi;
|
eax = edi;
|
||||||
var1 = eax / W(55);
|
var1 = eax / W(55);
|
||||||
edx = eax - (var1 * W(55));
|
edx = eax - (var1 * W(55));
|
||||||
ebx -= esi;
|
ebx = ebx - esi;
|
||||||
edi += W(0x15);
|
edi = edi + W(0x15);
|
||||||
stream[edx.0 as usize] = esi.0;
|
stream[edx.0 as usize] = esi.0;
|
||||||
esi = ebx;
|
esi = ebx;
|
||||||
ebx = W(stream[edx.0 as usize]);
|
ebx = W(stream[edx.0 as usize]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cipher = PSOPCCipher {
|
let mut cipher = PSOPCCipher {
|
||||||
stream,
|
stream: stream,
|
||||||
offset: 1,
|
offset: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ impl PSOPCCipher {
|
|||||||
while edx > W(0) {
|
while edx > W(0) {
|
||||||
esi = W(self.stream[eax.0 as usize + 0x1F]);
|
esi = W(self.stream[eax.0 as usize + 0x1F]);
|
||||||
ebp = W(self.stream[eax.0 as usize]);
|
ebp = W(self.stream[eax.0 as usize]);
|
||||||
ebp -= esi;
|
ebp = ebp - esi;
|
||||||
self.stream[eax.0 as usize] = ebp.0;
|
self.stream[eax.0 as usize] = ebp.0;
|
||||||
eax += W(1);
|
eax += W(1);
|
||||||
edx -= W(1);
|
edx -= W(1);
|
||||||
@ -74,7 +74,7 @@ impl PSOPCCipher {
|
|||||||
while edx > W(0) {
|
while edx > W(0) {
|
||||||
esi = W(self.stream[eax.0 as usize - 0x18]);
|
esi = W(self.stream[eax.0 as usize - 0x18]);
|
||||||
ebp = W(self.stream[eax.0 as usize]);
|
ebp = W(self.stream[eax.0 as usize]);
|
||||||
ebp -= esi;
|
ebp = ebp - esi;
|
||||||
self.stream[eax.0 as usize] = ebp.0;
|
self.stream[eax.0 as usize] = ebp.0;
|
||||||
eax += W(1);
|
eax += W(1);
|
||||||
edx -= W(1);
|
edx -= W(1);
|
||||||
@ -94,7 +94,7 @@ impl PSOPCCipher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PSOCipher for PSOPCCipher {
|
impl PSOCipher for PSOPCCipher {
|
||||||
fn encrypt(&mut self, data: &[u8]) -> Result<Vec<u8>, CipherError> {
|
fn encrypt(&mut self, data: &Vec<u8>) -> Result<Vec<u8>, CipherError> {
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
if data.len() % 4 != 0 {
|
if data.len() % 4 != 0 {
|
||||||
return Err(CipherError::InvalidSize)
|
return Err(CipherError::InvalidSize)
|
||||||
@ -108,7 +108,7 @@ impl PSOCipher for PSOPCCipher {
|
|||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decrypt(&mut self, data: &[u8]) -> Result<Vec<u8>, CipherError> {
|
fn decrypt(&mut self, data: &Vec<u8>) -> Result<Vec<u8>, CipherError> {
|
||||||
self.encrypt(data)
|
self.encrypt(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
src/lib.rs
14
src/lib.rs
@ -4,7 +4,7 @@ pub mod crypto;
|
|||||||
pub mod packet;
|
pub mod packet;
|
||||||
pub mod character;
|
pub mod character;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
//pub mod item;
|
pub mod item;
|
||||||
|
|
||||||
use std::io::{Read, Seek};
|
use std::io::{Read, Seek};
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
@ -109,7 +109,7 @@ impl PSOPacketData for String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct ConsumingBlob {
|
pub struct ConsumingBlob {
|
||||||
pub blob: Vec<u8>,
|
pub blob: Vec<u8>,
|
||||||
}
|
}
|
||||||
@ -119,7 +119,7 @@ impl PSOPacketData for ConsumingBlob {
|
|||||||
let mut blob: Vec<u8> = Vec::new();
|
let mut blob: Vec<u8> = Vec::new();
|
||||||
cursor.read_to_end(&mut blob).map_err(|_| PacketParseError::ReadError)?;
|
cursor.read_to_end(&mut blob).map_err(|_| PacketParseError::ReadError)?;
|
||||||
Ok(ConsumingBlob {
|
Ok(ConsumingBlob {
|
||||||
blob,
|
blob: blob,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn as_bytes(&self) -> Vec<u8> {
|
fn as_bytes(&self) -> Vec<u8> {
|
||||||
@ -127,14 +127,6 @@ impl PSOPacketData for ConsumingBlob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for ConsumingBlob {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
f.debug_struct("ConsumingBlob")
|
|
||||||
.field("blob", &"[...]")
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait PSOPacket: std::fmt::Debug {
|
pub trait PSOPacket: std::fmt::Debug {
|
||||||
// const CMD: u16;
|
// const CMD: u16;
|
||||||
fn from_bytes(data: &[u8]) -> Result<Self, PacketParseError> where Self: Sized;
|
fn from_bytes(data: &[u8]) -> Result<Self, PacketParseError> where Self: Sized;
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
|
|
||||||
use psopacket::{pso_packet, PSOPacketData};
|
use psopacket::{pso_packet, PSOPacketData};
|
||||||
use crate::{PSOPacket, PacketParseError, PSOPacketData};
|
use crate::{PSOPacket, PacketParseError, PSOPacketData, utf8_to_utf16_array};
|
||||||
use crate::util::utf8_to_utf16_array;
|
|
||||||
|
|
||||||
use crate::character::character::SelectScreenCharacter;
|
use crate::character::character::SelectScreenCharacter;
|
||||||
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
|
pub const PATCH_FILE_CHUNK_SIZE: u16 = 0x8000; // 32kb
|
||||||
pub const GUILD_CARD_CHUNK_SIZE: usize = 0x6800;
|
pub const GUILD_CARD_CHUNK_SIZE: usize = 0x6800;
|
||||||
pub const PARAM_DATA_CHUNK_SIZE: usize = 0x6800;
|
pub const PARAM_DATA_CHUNK_SIZE: usize = 0x6800;
|
||||||
|
|
||||||
@ -24,9 +24,9 @@ impl LoginWelcome {
|
|||||||
let mut copyright = [0u8; 0x60];
|
let mut copyright = [0u8; 0x60];
|
||||||
copyright[..0x4B].clone_from_slice(b"Phantasy Star Online Blue Burst Game Server. Copyright 1999-2004 SONICTEAM.");
|
copyright[..0x4B].clone_from_slice(b"Phantasy Star Online Blue Burst Game Server. Copyright 1999-2004 SONICTEAM.");
|
||||||
LoginWelcome {
|
LoginWelcome {
|
||||||
copyright,
|
copyright: copyright,
|
||||||
server_key,
|
server_key: server_key,
|
||||||
client_key,
|
client_key: client_key,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,8 +76,8 @@ pub struct Session {
|
|||||||
pub character_slot: u8, // 1..=4
|
pub character_slot: u8, // 1..=4
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Session {
|
impl Session {
|
||||||
fn default() -> Session {
|
pub fn new() -> Session {
|
||||||
Session {
|
Session {
|
||||||
version: [0; 30],
|
version: [0; 30],
|
||||||
session_id: 0,
|
session_id: 0,
|
||||||
@ -180,12 +180,12 @@ pub struct LoginResponse {
|
|||||||
impl LoginResponse {
|
impl LoginResponse {
|
||||||
pub fn by_status(status: AccountStatus, session: Session) -> LoginResponse {
|
pub fn by_status(status: AccountStatus, session: Session) -> LoginResponse {
|
||||||
LoginResponse {
|
LoginResponse {
|
||||||
status,
|
status: status,
|
||||||
tag: 0x00010000,
|
tag: 0x00010000,
|
||||||
//tag: 0x00000100,
|
//tag: 0x00000100,
|
||||||
guildcard: 0,
|
guildcard: 0,
|
||||||
team_id: 0,
|
team_id: 0,
|
||||||
session,
|
session: session,
|
||||||
caps: 0x00000102,
|
caps: 0x00000102,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,9 +194,9 @@ impl LoginResponse {
|
|||||||
status: AccountStatus::Ok,
|
status: AccountStatus::Ok,
|
||||||
tag: 0x00010000,
|
tag: 0x00010000,
|
||||||
//tag: 0x00000100,
|
//tag: 0x00000100,
|
||||||
guildcard,
|
guildcard: guildcard,
|
||||||
team_id,
|
team_id: team_id,
|
||||||
session,
|
session: session,
|
||||||
caps: 0x00000102,
|
caps: 0x00000102,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -210,8 +210,8 @@ pub struct RequestSettings {
|
|||||||
#[pso_packet(0xE2)]
|
#[pso_packet(0xE2)]
|
||||||
pub struct SendKeyAndTeamSettings {
|
pub struct SendKeyAndTeamSettings {
|
||||||
unknown: [u8; 0x114],
|
unknown: [u8; 0x114],
|
||||||
keyboard_config: [u8; 0x16C],
|
key_config: [u8; 0x16C],
|
||||||
gamepad_config: [u8; 0x38],
|
joystick_config: [u8; 0x38],
|
||||||
guildcard: u32,
|
guildcard: u32,
|
||||||
team_id: u32,
|
team_id: u32,
|
||||||
//team_info: [u32; 2],
|
//team_info: [u32; 2],
|
||||||
@ -226,13 +226,13 @@ pub struct SendKeyAndTeamSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SendKeyAndTeamSettings {
|
impl SendKeyAndTeamSettings {
|
||||||
pub fn new(keyboard_config: [u8; 0x16C], gamepad_config: [u8; 0x38], guildcard: u32, team_id: u32) -> SendKeyAndTeamSettings {
|
pub fn new(key_config: [u8; 0x16C], joystick_config: [u8; 0x38], guildcard: u32, team_id: u32) -> SendKeyAndTeamSettings {
|
||||||
SendKeyAndTeamSettings {
|
SendKeyAndTeamSettings {
|
||||||
unknown: [0; 0x114],
|
unknown: [0; 0x114],
|
||||||
keyboard_config,
|
key_config: key_config,
|
||||||
gamepad_config,
|
joystick_config: joystick_config,
|
||||||
guildcard,
|
guildcard: guildcard,
|
||||||
team_id,
|
team_id: team_id,
|
||||||
//team_info: [0; 2],
|
//team_info: [0; 2],
|
||||||
team_info: [0; 8],
|
team_info: [0; 8],
|
||||||
team_priv: 0,
|
team_priv: 0,
|
||||||
@ -255,8 +255,8 @@ pub struct RedirectClient {
|
|||||||
impl RedirectClient {
|
impl RedirectClient {
|
||||||
pub fn new(ip: u32, port: u16) -> RedirectClient {
|
pub fn new(ip: u32, port: u16) -> RedirectClient {
|
||||||
RedirectClient {
|
RedirectClient {
|
||||||
ip,
|
ip: ip,
|
||||||
port,
|
port: port,
|
||||||
padding: 0,
|
padding: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -276,7 +276,7 @@ pub struct ChecksumAck {
|
|||||||
impl ChecksumAck {
|
impl ChecksumAck {
|
||||||
pub fn new(ack: u32) -> ChecksumAck {
|
pub fn new(ack: u32) -> ChecksumAck {
|
||||||
ChecksumAck {
|
ChecksumAck {
|
||||||
ack,
|
ack: ack,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -293,6 +293,18 @@ pub struct CharAck {
|
|||||||
pub code: u32, // TODO: enum?
|
pub code: u32, // TODO: enum?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PSOPacketData for SelectScreenCharacter {
|
||||||
|
fn from_bytes<R: Read>(cursor: &mut R) -> Result<Self, PacketParseError> {
|
||||||
|
let mut buf = [0u8; SelectScreenCharacter::SIZE];
|
||||||
|
cursor.read(&mut buf).map_err(|_| PacketParseError::ReadError)?;
|
||||||
|
SelectScreenCharacter::from_le_bytes(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_bytes(&self) -> Vec<u8> {
|
||||||
|
self.to_le_bytes().to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[pso_packet(0xE5)]
|
#[pso_packet(0xE5)]
|
||||||
pub struct CharacterPreview {
|
pub struct CharacterPreview {
|
||||||
pub slot: u32,
|
pub slot: u32,
|
||||||
@ -315,7 +327,7 @@ impl GuildcardDataHeader {
|
|||||||
GuildcardDataHeader {
|
GuildcardDataHeader {
|
||||||
one: 1,
|
one: 1,
|
||||||
len: len as u32,
|
len: len as u32,
|
||||||
checksum,
|
checksum: checksum
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -331,6 +343,7 @@ pub struct GuildcardDataChunk {
|
|||||||
_unknown: u32,
|
_unknown: u32,
|
||||||
chunk: u32,
|
chunk: u32,
|
||||||
pub buffer: [u8; GUILD_CARD_CHUNK_SIZE],
|
pub buffer: [u8; GUILD_CARD_CHUNK_SIZE],
|
||||||
|
|
||||||
len: usize,
|
len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,9 +351,9 @@ impl GuildcardDataChunk {
|
|||||||
pub fn new(chunk: u32, buffer: [u8; GUILD_CARD_CHUNK_SIZE], len: usize) -> GuildcardDataChunk {
|
pub fn new(chunk: u32, buffer: [u8; GUILD_CARD_CHUNK_SIZE], len: usize) -> GuildcardDataChunk {
|
||||||
GuildcardDataChunk {
|
GuildcardDataChunk {
|
||||||
_unknown: 0,
|
_unknown: 0,
|
||||||
chunk,
|
chunk: chunk as u32,
|
||||||
buffer,
|
buffer: buffer,
|
||||||
len,
|
len: len,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -371,12 +384,12 @@ impl PSOPacket for GuildcardDataChunk {
|
|||||||
|
|
||||||
impl std::fmt::Debug for GuildcardDataChunk {
|
impl std::fmt::Debug for GuildcardDataChunk {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
writeln!(f, "packet GuildcardDataChunk {{").unwrap();
|
write!(f, "packet GuildcardDataChunk {{\n").unwrap();
|
||||||
writeln!(f, " flag: {:?}", 0).unwrap();
|
write!(f, " flag: {:?}\n", 0).unwrap();
|
||||||
writeln!(f, " _unknown: {:#X?}", self._unknown).unwrap();
|
write!(f, " _unknown: {:X?}\n", self._unknown).unwrap();
|
||||||
writeln!(f, " chunk: {:#X?}", self.chunk).unwrap();
|
write!(f, " chunk: {:X?}\n", self.chunk).unwrap();
|
||||||
writeln!(f, " buffer: [0..{:#X}]", self.len).unwrap();
|
write!(f, " buffer: [0..{:X}]\n", self.len).unwrap();
|
||||||
writeln!(f, "}}")
|
write!(f, "}}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,9 +441,9 @@ impl PSOPacket for ParamDataHeader {
|
|||||||
|
|
||||||
impl std::fmt::Debug for ParamDataHeader {
|
impl std::fmt::Debug for ParamDataHeader {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
writeln!(f, "packet ParamDataHeader{{").unwrap();
|
write!(f, "packet ParamDataHeader{{\n").unwrap();
|
||||||
writeln!(f, " files: [..]").unwrap();
|
write!(f, " files: [..]\n").unwrap();
|
||||||
writeln!(f, "}}")
|
write!(f, "}}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -492,9 +505,9 @@ impl ShipList {
|
|||||||
menu: ships.get(0).map(|s| s.menu).unwrap_or(0),
|
menu: ships.get(0).map(|s| s.menu).unwrap_or(0),
|
||||||
item: 0,
|
item: 0,
|
||||||
flags: 0,
|
flags: 0,
|
||||||
name: utf8_to_utf16_array("Ship"),
|
name: utf8_to_utf16_array!("Ship", 0x11),
|
||||||
},
|
},
|
||||||
ships,
|
ships: ships,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -517,7 +530,7 @@ mod tests {
|
|||||||
tag: 0,
|
tag: 0,
|
||||||
guildcard: 0,
|
guildcard: 0,
|
||||||
team_id: 0,
|
team_id: 0,
|
||||||
session: Session::default(),
|
session: Session::new(),
|
||||||
caps: 0,
|
caps: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -537,17 +550,17 @@ mod tests {
|
|||||||
|
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
let mut keyboard_config = [0u8; 0x16C];
|
let mut key_config = [0u8; 0x16C];
|
||||||
let mut gamepad_config = [0u8; 0x38];
|
let mut joystick_config = [0u8; 0x38];
|
||||||
|
|
||||||
rng.fill(&mut keyboard_config[..]);
|
rng.fill(&mut key_config[..]);
|
||||||
rng.fill(&mut gamepad_config[..]);
|
rng.fill(&mut joystick_config[..]);
|
||||||
let pkt = super::SendKeyAndTeamSettings::new(keyboard_config, gamepad_config, 123, 456);
|
let pkt = super::SendKeyAndTeamSettings::new(key_config, joystick_config, 123, 456);
|
||||||
let bytes = pkt.as_bytes();
|
let bytes = pkt.as_bytes();
|
||||||
|
|
||||||
assert!(bytes[2] == 0xe2);
|
assert!(bytes[2] == 0xe2);
|
||||||
assert!(bytes[8 + 0x114] == keyboard_config[0]);
|
assert!(bytes[8 + 0x114] == key_config[0]);
|
||||||
assert!(bytes[8 + 0x114 + 0x16C] == gamepad_config[0]);
|
assert!(bytes[8 + 0x114 + 0x16C] == joystick_config[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -560,7 +573,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_session_size() {
|
fn test_session_size() {
|
||||||
use super::PSOPacketData;
|
use super::PSOPacketData;
|
||||||
let session = super::Session::default();
|
let session = super::Session::new();
|
||||||
assert!(session.as_bytes().len() == 40);
|
assert!(session.as_bytes().len() == 40);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#![allow(unused_must_use)]
|
#![allow(unused_must_use)]
|
||||||
use std::io::{SeekFrom};
|
use std::io::{SeekFrom};
|
||||||
use std::convert::TryInto;
|
|
||||||
|
|
||||||
use psopacket::{pso_message, PSOPacketData};
|
use psopacket::{pso_message, PSOPacketData};
|
||||||
use crate::{PSOPacketData, PacketParseError};
|
use crate::{PSOPacketData, PacketParseError};
|
||||||
@ -44,7 +43,7 @@ pub struct SymbolChat {
|
|||||||
pub struct MobAttack {
|
pub struct MobAttack {
|
||||||
enemy_id: u16,
|
enemy_id: u16,
|
||||||
damage: u16,
|
damage: u16,
|
||||||
flags: [u8; 4],
|
flags: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pso_message(0x0B)]
|
#[pso_message(0x0B)]
|
||||||
@ -501,11 +500,12 @@ pub struct MagAnimation {
|
|||||||
unknown1: u16,
|
unknown1: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pso_message(0x63)]
|
//#[pso_message(0x63)]
|
||||||
pub struct FloorItemLimitItemDeletion {
|
//pub struct FloorItemLimitItemDeletion {
|
||||||
item_id: u32,
|
// client_id: u16,
|
||||||
map_area: u16,
|
// item_id: u8,
|
||||||
}
|
// amount: u8,
|
||||||
|
//}
|
||||||
|
|
||||||
#[pso_message(0x66)]
|
#[pso_message(0x66)]
|
||||||
pub struct PlayerUsedStarAtomizer {
|
pub struct PlayerUsedStarAtomizer {
|
||||||
@ -535,12 +535,6 @@ pub struct NpcSpawn {
|
|||||||
data: [u8; 8],
|
data: [u8; 8],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[pso_message(0x6A)]
|
|
||||||
pub struct ActivateBossWarp {
|
|
||||||
unknown: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pso_message(0x6F)]
|
#[pso_message(0x6F)]
|
||||||
pub struct PlayerJoiningGame {
|
pub struct PlayerJoiningGame {
|
||||||
data: [u32; 0x81],
|
data: [u32; 0x81],
|
||||||
@ -690,122 +684,11 @@ pub struct BoxDropRequest {
|
|||||||
|
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
|
||||||
pub enum TradeRequestInitializeCommand {
|
|
||||||
Initialize,
|
|
||||||
Respond,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
|
||||||
pub enum TradeRequestCommand {
|
|
||||||
Initialize(TradeRequestInitializeCommand, u32),
|
|
||||||
AddItem(u32, u32),
|
|
||||||
RemoveItem(u32, u32),
|
|
||||||
Confirm,
|
|
||||||
FinalConfirm,
|
|
||||||
Cancel,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PSOPacketData for TradeRequestCommand {
|
|
||||||
fn from_bytes<R: std::io::Read + std::io::Seek>(cursor: &mut R) -> Result<Self, PacketParseError> {
|
|
||||||
let mut bytes = [0u8; 12];
|
|
||||||
let len = cursor.read(&mut bytes).map_err(|_| PacketParseError::ReadError)?;
|
|
||||||
if len != 12 {
|
|
||||||
return Err(PacketParseError::NotEnoughBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
match bytes[0] {
|
|
||||||
0 => {
|
|
||||||
let meseta = u32::from_le_bytes(bytes[8..12].try_into().map_err(|_| PacketParseError::InvalidValue)?);
|
|
||||||
match bytes[1] {
|
|
||||||
0 => Ok(TradeRequestCommand::Initialize(TradeRequestInitializeCommand::Initialize, meseta)),
|
|
||||||
2 => Ok(TradeRequestCommand::Initialize(TradeRequestInitializeCommand::Respond, meseta)),
|
|
||||||
_ => Err(PacketParseError::InvalidValue)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
1 => {
|
|
||||||
Ok(TradeRequestCommand::AddItem(
|
|
||||||
u32::from_le_bytes(bytes[4..8].try_into().map_err(|_| PacketParseError::InvalidValue)?),
|
|
||||||
u32::from_le_bytes(bytes[8..12].try_into().map_err(|_| PacketParseError::InvalidValue)?),
|
|
||||||
))
|
|
||||||
},
|
|
||||||
2 => {
|
|
||||||
Ok(TradeRequestCommand::RemoveItem(
|
|
||||||
u32::from_le_bytes(bytes[4..8].try_into().map_err(|_| PacketParseError::InvalidValue)?),
|
|
||||||
u32::from_le_bytes(bytes[8..12].try_into().map_err(|_| PacketParseError::InvalidValue)?),
|
|
||||||
))
|
|
||||||
},
|
|
||||||
3 => {
|
|
||||||
Ok(TradeRequestCommand::Confirm)
|
|
||||||
},
|
|
||||||
4 => {
|
|
||||||
Ok(TradeRequestCommand::FinalConfirm)
|
|
||||||
},
|
|
||||||
5 => {
|
|
||||||
Ok(TradeRequestCommand::Cancel)
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
Err(PacketParseError::InvalidValue)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_bytes(&self) -> Vec<u8> {
|
|
||||||
match self {
|
|
||||||
TradeRequestCommand::Initialize(cmd, meseta) => {
|
|
||||||
vec![0u8,
|
|
||||||
match cmd {
|
|
||||||
TradeRequestInitializeCommand::Initialize => 0,
|
|
||||||
TradeRequestInitializeCommand::Respond => 2,
|
|
||||||
},
|
|
||||||
0, 0,
|
|
||||||
0, 0, 0, 0]
|
|
||||||
.into_iter()
|
|
||||||
.chain(meseta.to_le_bytes().iter().copied())
|
|
||||||
.collect()
|
|
||||||
},
|
|
||||||
TradeRequestCommand::AddItem(item_id, amount) => {
|
|
||||||
vec![1u8, 0, 0, 0]
|
|
||||||
.into_iter()
|
|
||||||
.chain(item_id.to_le_bytes().iter().copied())
|
|
||||||
.chain(amount.to_le_bytes().iter().copied())
|
|
||||||
.collect()
|
|
||||||
},
|
|
||||||
TradeRequestCommand::RemoveItem(item_id, amount) => {
|
|
||||||
vec![2u8, 0, 0, 0]
|
|
||||||
.into_iter()
|
|
||||||
.chain(item_id.to_le_bytes().iter().copied())
|
|
||||||
.chain(amount.to_le_bytes().iter().copied())
|
|
||||||
.collect()
|
|
||||||
},
|
|
||||||
TradeRequestCommand::Confirm => {
|
|
||||||
vec![3u8]
|
|
||||||
.into_iter()
|
|
||||||
.chain(std::iter::repeat(0).take(11))
|
|
||||||
.collect()
|
|
||||||
},
|
|
||||||
TradeRequestCommand::FinalConfirm => {
|
|
||||||
vec![4u8]
|
|
||||||
.into_iter()
|
|
||||||
.chain(std::iter::repeat(0).take(11))
|
|
||||||
.collect()
|
|
||||||
},
|
|
||||||
TradeRequestCommand::Cancel=> {
|
|
||||||
vec![5u8]
|
|
||||||
.into_iter()
|
|
||||||
.chain(std::iter::repeat(0).take(11))
|
|
||||||
.collect()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pso_message(0xA6)]
|
#[pso_message(0xA6)]
|
||||||
pub struct TradeRequest {
|
pub struct TradeRequest {
|
||||||
pub trade: TradeRequestCommand,
|
unknown1: u32,
|
||||||
|
unknown2: u32,
|
||||||
|
unknown3: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
//#[pso_message(0xA8)]
|
//#[pso_message(0xA8)]
|
||||||
@ -953,7 +836,6 @@ pub struct DropCoordinates {
|
|||||||
x: f32,
|
x: f32,
|
||||||
z: f32,
|
z: f32,
|
||||||
item_id: u32,
|
item_id: u32,
|
||||||
amount: u32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pso_message(0xC4)]
|
#[pso_message(0xC4)]
|
||||||
@ -966,12 +848,10 @@ pub struct PlayerUsedMedicalCenter {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pso_message(0xC6)]
|
//#[pso_message(0xC6)]
|
||||||
pub struct ExperienceSteal {
|
//pub struct ExperienceSteal {
|
||||||
client2: u8,
|
|
||||||
target2: u8,
|
//}
|
||||||
enemy_id: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pso_message(0xC7)]
|
#[pso_message(0xC7)]
|
||||||
pub struct ChargeAttack {
|
pub struct ChargeAttack {
|
||||||
@ -1172,13 +1052,12 @@ pub enum GameMessage {
|
|||||||
ItemDrop(ItemDrop),
|
ItemDrop(ItemDrop),
|
||||||
RequestItem(RequestItem),
|
RequestItem(RequestItem),
|
||||||
MagAnimation(MagAnimation),
|
MagAnimation(MagAnimation),
|
||||||
FloorItemLimitItemDeletion(FloorItemLimitItemDeletion),
|
//FloorItemLimitItemDeletion(FloorItemLimitItemDeletion),
|
||||||
PlayerUsedStarAtomizer(PlayerUsedStarAtomizer),
|
PlayerUsedStarAtomizer(PlayerUsedStarAtomizer),
|
||||||
SpawningMonsters(SpawningMonsters),
|
SpawningMonsters(SpawningMonsters),
|
||||||
PlayerTelepipe(PlayerTelepipe),
|
PlayerTelepipe(PlayerTelepipe),
|
||||||
NpcSpawn(NpcSpawn),
|
NpcSpawn(NpcSpawn),
|
||||||
ActivateBossWarp(ActivateBossWarp),
|
PlayerJoiningGame(PlayerJoiningGame),
|
||||||
PlayerJoiningGame(Box<PlayerJoiningGame>),
|
|
||||||
PlayerJoiningGame2(PlayerJoiningGame2),
|
PlayerJoiningGame2(PlayerJoiningGame2),
|
||||||
BurstDone(BurstDone),
|
BurstDone(BurstDone),
|
||||||
WordSelect(WordSelect),
|
WordSelect(WordSelect),
|
||||||
@ -1231,7 +1110,7 @@ pub enum GameMessage {
|
|||||||
DropCoordinates(DropCoordinates),
|
DropCoordinates(DropCoordinates),
|
||||||
SortItems(SortItems),
|
SortItems(SortItems),
|
||||||
PlayerUsedMedicalCenter(PlayerUsedMedicalCenter),
|
PlayerUsedMedicalCenter(PlayerUsedMedicalCenter),
|
||||||
ExperienceSteal(ExperienceSteal),
|
//ExperienceSteal(ExperienceSteal),
|
||||||
ChargeAttack(ChargeAttack),
|
ChargeAttack(ChargeAttack),
|
||||||
RequestExp(RequestExp),
|
RequestExp(RequestExp),
|
||||||
//QuestRewardMeseta(QuestRewardMeseta),
|
//QuestRewardMeseta(QuestRewardMeseta),
|
||||||
@ -1340,13 +1219,12 @@ impl PSOPacketData for GameMessage {
|
|||||||
ItemDrop::CMD => Ok(GameMessage::ItemDrop(ItemDrop::from_bytes(&mut cur)?)),
|
ItemDrop::CMD => Ok(GameMessage::ItemDrop(ItemDrop::from_bytes(&mut cur)?)),
|
||||||
RequestItem::CMD => Ok(GameMessage::RequestItem(RequestItem::from_bytes(&mut cur)?)),
|
RequestItem::CMD => Ok(GameMessage::RequestItem(RequestItem::from_bytes(&mut cur)?)),
|
||||||
MagAnimation::CMD => Ok(GameMessage::MagAnimation(MagAnimation::from_bytes(&mut cur)?)),
|
MagAnimation::CMD => Ok(GameMessage::MagAnimation(MagAnimation::from_bytes(&mut cur)?)),
|
||||||
FloorItemLimitItemDeletion::CMD => Ok(GameMessage::FloorItemLimitItemDeletion(FloorItemLimitItemDeletion::from_bytes(&mut cur)?)),
|
//FloorItemLimitItemDeletion::CMD => Ok(GameMessage::FloorItemLimitItemDeletion(FloorItemLimitItemDeletion::from_bytes(&mut cur)?)),
|
||||||
PlayerUsedStarAtomizer::CMD => Ok(GameMessage::PlayerUsedStarAtomizer(PlayerUsedStarAtomizer::from_bytes(&mut cur)?)),
|
PlayerUsedStarAtomizer::CMD => Ok(GameMessage::PlayerUsedStarAtomizer(PlayerUsedStarAtomizer::from_bytes(&mut cur)?)),
|
||||||
SpawningMonsters::CMD => Ok(GameMessage::SpawningMonsters(SpawningMonsters::from_bytes(&mut cur)?)),
|
SpawningMonsters::CMD => Ok(GameMessage::SpawningMonsters(SpawningMonsters::from_bytes(&mut cur)?)),
|
||||||
PlayerTelepipe::CMD => Ok(GameMessage::PlayerTelepipe(PlayerTelepipe::from_bytes(&mut cur)?)),
|
PlayerTelepipe::CMD => Ok(GameMessage::PlayerTelepipe(PlayerTelepipe::from_bytes(&mut cur)?)),
|
||||||
NpcSpawn::CMD => Ok(GameMessage::NpcSpawn(NpcSpawn::from_bytes(&mut cur)?)),
|
NpcSpawn::CMD => Ok(GameMessage::NpcSpawn(NpcSpawn::from_bytes(&mut cur)?)),
|
||||||
ActivateBossWarp::CMD => Ok(GameMessage::ActivateBossWarp(ActivateBossWarp::from_bytes(&mut cur)?)),
|
PlayerJoiningGame::CMD => Ok(GameMessage::PlayerJoiningGame(PlayerJoiningGame::from_bytes(&mut cur)?)),
|
||||||
PlayerJoiningGame::CMD => Ok(GameMessage::PlayerJoiningGame(Box::new(PlayerJoiningGame::from_bytes(&mut cur)?))),
|
|
||||||
PlayerJoiningGame2::CMD => Ok(GameMessage::PlayerJoiningGame2(PlayerJoiningGame2::from_bytes(&mut cur)?)),
|
PlayerJoiningGame2::CMD => Ok(GameMessage::PlayerJoiningGame2(PlayerJoiningGame2::from_bytes(&mut cur)?)),
|
||||||
BurstDone::CMD => Ok(GameMessage::BurstDone(BurstDone::from_bytes(&mut cur)?)),
|
BurstDone::CMD => Ok(GameMessage::BurstDone(BurstDone::from_bytes(&mut cur)?)),
|
||||||
WordSelect::CMD => Ok(GameMessage::WordSelect(WordSelect::from_bytes(&mut cur)?)),
|
WordSelect::CMD => Ok(GameMessage::WordSelect(WordSelect::from_bytes(&mut cur)?)),
|
||||||
@ -1399,7 +1277,7 @@ impl PSOPacketData for GameMessage {
|
|||||||
DropCoordinates::CMD => Ok(GameMessage::DropCoordinates(DropCoordinates::from_bytes(&mut cur)?)),
|
DropCoordinates::CMD => Ok(GameMessage::DropCoordinates(DropCoordinates::from_bytes(&mut cur)?)),
|
||||||
SortItems::CMD => Ok(GameMessage::SortItems(SortItems::from_bytes(&mut cur)?)),
|
SortItems::CMD => Ok(GameMessage::SortItems(SortItems::from_bytes(&mut cur)?)),
|
||||||
PlayerUsedMedicalCenter::CMD => Ok(GameMessage::PlayerUsedMedicalCenter(PlayerUsedMedicalCenter::from_bytes(&mut cur)?)),
|
PlayerUsedMedicalCenter::CMD => Ok(GameMessage::PlayerUsedMedicalCenter(PlayerUsedMedicalCenter::from_bytes(&mut cur)?)),
|
||||||
ExperienceSteal::CMD => Ok(GameMessage::ExperienceSteal(ExperienceSteal::from_bytes(&mut cur)?)),
|
//ExperienceSteal::CMD => Ok(GameMessage::ExperienceSteal(ExperienceSteal::from_bytes(&mut cur)?)),
|
||||||
ChargeAttack::CMD => Ok(GameMessage::ChargeAttack(ChargeAttack::from_bytes(&mut cur)?)),
|
ChargeAttack::CMD => Ok(GameMessage::ChargeAttack(ChargeAttack::from_bytes(&mut cur)?)),
|
||||||
RequestExp::CMD => Ok(GameMessage::RequestExp(RequestExp::from_bytes(&mut cur)?)),
|
RequestExp::CMD => Ok(GameMessage::RequestExp(RequestExp::from_bytes(&mut cur)?)),
|
||||||
//QuestRewardMeseta::CMD => Ok(GameMessage::QuestRewardMeseta(QuestRewardMeseta::from_bytes(&mut cur)?)),
|
//QuestRewardMeseta::CMD => Ok(GameMessage::QuestRewardMeseta(QuestRewardMeseta::from_bytes(&mut cur)?)),
|
||||||
@ -1427,7 +1305,7 @@ impl PSOPacketData for GameMessage {
|
|||||||
_ => Err(PacketParseError::UnknownMessage(byte[0],
|
_ => Err(PacketParseError::UnknownMessage(byte[0],
|
||||||
{
|
{
|
||||||
let mut b = vec![0; len[0] as usize * 4];
|
let mut b = vec![0; len[0] as usize * 4];
|
||||||
cur.read_exact(&mut b).unwrap();
|
cur.read(&mut b).unwrap();
|
||||||
b.to_vec()
|
b.to_vec()
|
||||||
}
|
}
|
||||||
)),
|
)),
|
||||||
@ -1510,12 +1388,11 @@ impl PSOPacketData for GameMessage {
|
|||||||
GameMessage::ItemDrop(data) => data.as_bytes(),
|
GameMessage::ItemDrop(data) => data.as_bytes(),
|
||||||
GameMessage::RequestItem(data) => data.as_bytes(),
|
GameMessage::RequestItem(data) => data.as_bytes(),
|
||||||
GameMessage::MagAnimation(data) => data.as_bytes(),
|
GameMessage::MagAnimation(data) => data.as_bytes(),
|
||||||
GameMessage::FloorItemLimitItemDeletion(data) => data.as_bytes(),
|
//GameMessage::FloorItemLimitItemDeletion(data) => data.as_bytes(),
|
||||||
GameMessage::PlayerUsedStarAtomizer(data) => data.as_bytes(),
|
GameMessage::PlayerUsedStarAtomizer(data) => data.as_bytes(),
|
||||||
GameMessage::SpawningMonsters(data) => data.as_bytes(),
|
GameMessage::SpawningMonsters(data) => data.as_bytes(),
|
||||||
GameMessage::PlayerTelepipe(data) => data.as_bytes(),
|
GameMessage::PlayerTelepipe(data) => data.as_bytes(),
|
||||||
GameMessage::NpcSpawn(data) => data.as_bytes(),
|
GameMessage::NpcSpawn(data) => data.as_bytes(),
|
||||||
GameMessage::ActivateBossWarp(data) => data.as_bytes(),
|
|
||||||
GameMessage::PlayerJoiningGame(data) => data.as_bytes(),
|
GameMessage::PlayerJoiningGame(data) => data.as_bytes(),
|
||||||
GameMessage::PlayerJoiningGame2(data) => data.as_bytes(),
|
GameMessage::PlayerJoiningGame2(data) => data.as_bytes(),
|
||||||
GameMessage::BurstDone(data) => data.as_bytes(),
|
GameMessage::BurstDone(data) => data.as_bytes(),
|
||||||
@ -1569,7 +1446,7 @@ impl PSOPacketData for GameMessage {
|
|||||||
GameMessage::DropCoordinates(data) => data.as_bytes(),
|
GameMessage::DropCoordinates(data) => data.as_bytes(),
|
||||||
GameMessage::SortItems(data) => data.as_bytes(),
|
GameMessage::SortItems(data) => data.as_bytes(),
|
||||||
GameMessage::PlayerUsedMedicalCenter(data) => data.as_bytes(),
|
GameMessage::PlayerUsedMedicalCenter(data) => data.as_bytes(),
|
||||||
GameMessage::ExperienceSteal(data) => data.as_bytes(),
|
//GameMessage::ExperienceSteal(data) => data.as_bytes(),
|
||||||
GameMessage::ChargeAttack(data) => data.as_bytes(),
|
GameMessage::ChargeAttack(data) => data.as_bytes(),
|
||||||
GameMessage::RequestExp(data) => data.as_bytes(),
|
GameMessage::RequestExp(data) => data.as_bytes(),
|
||||||
//GameMessage::QuestRewardMeseta(data) => data.as_bytes(),
|
//GameMessage::QuestRewardMeseta(data) => data.as_bytes(),
|
||||||
@ -1597,15 +1474,3 @@ impl PSOPacketData for GameMessage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_trade_request_cancel() {
|
|
||||||
let data = vec![166, 4, 0, 0, 5, 4, 0, 0, 157, 58, 113, 0, 1, 0, 0, 0];
|
|
||||||
let _pkt = GameMessage::from_bytes(&mut std::io::Cursor::new(data)).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -3,7 +3,7 @@ use crate::{PSOPacket, PacketParseError, PSOPacketData};
|
|||||||
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
pub const PATCH_FILE_CHUNK_SIZE: u16 = 0x6000; // 24kb
|
pub const PATCH_FILE_CHUNK_SIZE: u16 = 0x8000; // 32kb
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
type u8_str = u8;
|
type u8_str = u8;
|
||||||
@ -19,10 +19,10 @@ pub struct PatchWelcome {
|
|||||||
impl PatchWelcome {
|
impl PatchWelcome {
|
||||||
pub fn new(server_key: u32, client_key: u32) -> PatchWelcome {
|
pub fn new(server_key: u32, client_key: u32) -> PatchWelcome {
|
||||||
PatchWelcome {
|
PatchWelcome {
|
||||||
copyright: *b"Patch Server. Copyright SonicTeam, LTD. 2001",
|
copyright: b"Patch Server. Copyright SonicTeam, LTD. 2001".clone(),
|
||||||
padding: [0; 20],
|
padding: [0; 20],
|
||||||
server_key,
|
server_key: server_key,
|
||||||
client_key,
|
client_key: client_key,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,8 +58,8 @@ impl StartFileSend {
|
|||||||
*dst = *src
|
*dst = *src
|
||||||
}
|
}
|
||||||
StartFileSend {
|
StartFileSend {
|
||||||
id,
|
id: id,
|
||||||
size,
|
size: size,
|
||||||
filename: f,
|
filename: f,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,22 +106,31 @@ impl PSOPacket for FileSend {
|
|||||||
|
|
||||||
impl std::fmt::Debug for FileSend {
|
impl std::fmt::Debug for FileSend {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
writeln!(f, "packet FileSend {{").unwrap();
|
write!(f, "packet FileSend {{\n").unwrap();
|
||||||
writeln!(f, " chunk_num: {:?}", self.chunk_num).unwrap();
|
write!(f, " chunk_num: {:?}\n", self.chunk_num).unwrap();
|
||||||
writeln!(f, " checksum: {:X?}", self.checksum).unwrap();
|
write!(f, " checksum: {:X?}\n", self.checksum).unwrap();
|
||||||
writeln!(f, " chunk_size: {:X?}", self.chunk_size).unwrap();
|
write!(f, " chunk_size: {:X?}\n", self.chunk_size).unwrap();
|
||||||
writeln!(f, " buffer: [...a large array ...]").unwrap();
|
write!(f, " buffer: [...a large array ...]\n").unwrap();
|
||||||
writeln!(f, "}}")
|
write!(f, "}}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
#[pso_packet(0x08, no_flag)]
|
#[pso_packet(0x08, no_flag)]
|
||||||
pub struct EndFileSend {
|
pub struct EndFileSend {
|
||||||
padding: u32,
|
padding: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl EndFileSend {
|
||||||
|
pub fn new() -> EndFileSend {
|
||||||
|
EndFileSend {
|
||||||
|
padding: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[pso_packet(0x0B, no_flag)]
|
#[pso_packet(0x0B, no_flag)]
|
||||||
pub struct PatchStartList {
|
pub struct PatchStartList {
|
||||||
}
|
}
|
||||||
@ -160,7 +169,7 @@ impl FileInfo {
|
|||||||
*dst = *src
|
*dst = *src
|
||||||
};
|
};
|
||||||
FileInfo {
|
FileInfo {
|
||||||
id,
|
id: id,
|
||||||
filename: f,
|
filename: f,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,8 +200,8 @@ pub struct FilesToPatchMetadata {
|
|||||||
impl FilesToPatchMetadata {
|
impl FilesToPatchMetadata {
|
||||||
pub fn new(data_size: u32, file_count: u32) -> FilesToPatchMetadata {
|
pub fn new(data_size: u32, file_count: u32) -> FilesToPatchMetadata {
|
||||||
FilesToPatchMetadata {
|
FilesToPatchMetadata {
|
||||||
data_size,
|
data_size: data_size,
|
||||||
file_count,
|
file_count: file_count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -212,7 +221,7 @@ impl Message {
|
|||||||
pub fn new(mut msg: String) -> Message {
|
pub fn new(mut msg: String) -> Message {
|
||||||
msg.push('\0');
|
msg.push('\0');
|
||||||
Message {
|
Message {
|
||||||
msg,
|
msg: msg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -228,8 +237,8 @@ pub struct RedirectClient {
|
|||||||
impl RedirectClient {
|
impl RedirectClient {
|
||||||
pub fn new(ip: u32, port: u16) -> RedirectClient {
|
pub fn new(ip: u32, port: u16) -> RedirectClient {
|
||||||
RedirectClient {
|
RedirectClient {
|
||||||
ip,
|
ip: ip,
|
||||||
port,
|
port: port,
|
||||||
padding: 0,
|
padding: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use psopacket::{pso_packet, PSOPacketData};
|
use psopacket::{pso_packet, PSOPacketData};
|
||||||
use crate::{PSOPacket, PacketParseError, PSOPacketData};
|
use crate::{PSOPacket, PacketParseError, PSOPacketData};
|
||||||
use crate::util::utf8_to_utf16_array;
|
use crate::utf8_to_utf16_array;
|
||||||
use crate::packet::messages::GameMessage;
|
use crate::packet::messages::GameMessage;
|
||||||
//use character::character::FullCharacter;
|
//use character::character::FullCharacter;
|
||||||
use crate::character::character as character;
|
use crate::character::character as character;
|
||||||
@ -26,9 +26,9 @@ impl ShipWelcome {
|
|||||||
let mut copyright = [0u8; 0x60];
|
let mut copyright = [0u8; 0x60];
|
||||||
copyright[..0x4B].clone_from_slice(b"Phantasy Star Online Blue Burst Game Server. Copyright 1999-2004 SONICTEAM.");
|
copyright[..0x4B].clone_from_slice(b"Phantasy Star Online Blue Burst Game Server. Copyright 1999-2004 SONICTEAM.");
|
||||||
ShipWelcome {
|
ShipWelcome {
|
||||||
copyright,
|
copyright: copyright,
|
||||||
server_key,
|
server_key: server_key,
|
||||||
client_key,
|
client_key: client_key,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,13 +82,13 @@ impl ShipBlockList {
|
|||||||
menu: BLOCK_MENU_ID,
|
menu: BLOCK_MENU_ID,
|
||||||
item: 0,
|
item: 0,
|
||||||
flags: 0,
|
flags: 0,
|
||||||
name: utf8_to_utf16_array(shipname)
|
name: utf8_to_utf16_array!(shipname, 0x11)
|
||||||
},
|
},
|
||||||
blocks: (0..num_blocks).map(|i| BlockEntry {
|
blocks: (0..num_blocks).map(|i| BlockEntry {
|
||||||
menu: BLOCK_MENU_ID,
|
menu: BLOCK_MENU_ID,
|
||||||
item: i as u32 + 1,
|
item: i as u32 + 1,
|
||||||
flags: 0,
|
flags: 0,
|
||||||
name: utf8_to_utf16_array(format!("Block {}", i+1))
|
name: utf8_to_utf16_array!(format!("Block {}", i+1), 0x11)
|
||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,7 +124,7 @@ pub struct LobbySelect {
|
|||||||
|
|
||||||
#[pso_packet(0xE7)]
|
#[pso_packet(0xE7)]
|
||||||
pub struct FullCharacter {
|
pub struct FullCharacter {
|
||||||
#[nodebug]
|
#[no_debug]
|
||||||
character: character::FullCharacter,
|
character: character::FullCharacter,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,8 +149,8 @@ pub struct BurstDone72 {
|
|||||||
target: u8,
|
target: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for BurstDone72 {
|
impl BurstDone72 {
|
||||||
fn default() -> BurstDone72 {
|
pub fn new() -> BurstDone72 {
|
||||||
BurstDone72 {
|
BurstDone72 {
|
||||||
msg: 0x72,
|
msg: 0x72,
|
||||||
len: 3,
|
len: 3,
|
||||||
@ -169,7 +169,7 @@ pub struct Message {
|
|||||||
impl Message {
|
impl Message {
|
||||||
pub fn new(msg: GameMessage) -> Message {
|
pub fn new(msg: GameMessage) -> Message {
|
||||||
Message {
|
Message {
|
||||||
msg,
|
msg: msg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -184,7 +184,7 @@ impl DirectMessage {
|
|||||||
pub fn new(target: u32, msg: GameMessage) -> DirectMessage {
|
pub fn new(target: u32, msg: GameMessage) -> DirectMessage {
|
||||||
DirectMessage {
|
DirectMessage {
|
||||||
flag: target,
|
flag: target,
|
||||||
msg,
|
msg: msg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -280,26 +280,7 @@ impl SmallDialog {
|
|||||||
}
|
}
|
||||||
SmallDialog {
|
SmallDialog {
|
||||||
padding: [0; 0x02],
|
padding: [0; 0x02],
|
||||||
msg,
|
msg: msg,
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is literally the same struct as 0x01.
|
|
||||||
#[pso_packet(0xB0)]
|
|
||||||
pub struct RightText {
|
|
||||||
padding: [u32; 0x02],
|
|
||||||
msg: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RightText {
|
|
||||||
pub fn new(mut msg: String) -> RightText {
|
|
||||||
if !msg.ends_with('\0') {
|
|
||||||
msg.push('\0');
|
|
||||||
}
|
|
||||||
RightText {
|
|
||||||
padding: [0; 0x02],
|
|
||||||
msg,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -311,31 +292,10 @@ pub struct SmallLeftDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SmallLeftDialog {
|
impl SmallLeftDialog {
|
||||||
pub fn new(mut msg: String) -> SmallLeftDialog {
|
pub fn new(msg: String) -> SmallLeftDialog {
|
||||||
if !msg.ends_with('\0') {
|
|
||||||
msg.push('\0');
|
|
||||||
}
|
|
||||||
SmallLeftDialog {
|
SmallLeftDialog {
|
||||||
padding: [0x00004500, 0x45004500],
|
padding: [0x00004500, 0x45004500],
|
||||||
msg,
|
msg: msg,
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pso_packet(0x1A)]
|
|
||||||
pub struct LargeDialog {
|
|
||||||
padding: [u32; 0x02],
|
|
||||||
msg: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LargeDialog {
|
|
||||||
pub fn new(mut msg: String) -> LargeDialog {
|
|
||||||
if !msg.ends_with('\0') {
|
|
||||||
msg.push('\0');
|
|
||||||
}
|
|
||||||
LargeDialog {
|
|
||||||
padding: [0, 0x45000000],
|
|
||||||
msg,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -383,8 +343,8 @@ pub struct LeaveLobby {
|
|||||||
impl LeaveLobby {
|
impl LeaveLobby {
|
||||||
pub fn new(client: u8, leader: u8) -> LeaveLobby {
|
pub fn new(client: u8, leader: u8) -> LeaveLobby {
|
||||||
LeaveLobby {
|
LeaveLobby {
|
||||||
client,
|
client: client,
|
||||||
leader,
|
leader: leader,
|
||||||
_padding: 0,
|
_padding: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -400,8 +360,8 @@ pub struct LeaveRoom {
|
|||||||
impl LeaveRoom {
|
impl LeaveRoom {
|
||||||
pub fn new(client: u8, leader: u8) -> LeaveRoom {
|
pub fn new(client: u8, leader: u8) -> LeaveRoom {
|
||||||
LeaveRoom {
|
LeaveRoom {
|
||||||
client,
|
client: client,
|
||||||
leader,
|
leader: leader,
|
||||||
_padding: 0,
|
_padding: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -418,8 +378,8 @@ impl PlayerChat {
|
|||||||
pub fn new(guildcard: u32, message: String) -> PlayerChat {
|
pub fn new(guildcard: u32, message: String) -> PlayerChat {
|
||||||
PlayerChat {
|
PlayerChat {
|
||||||
unknown: 0x00010000,
|
unknown: 0x00010000,
|
||||||
guildcard,
|
guildcard: guildcard,
|
||||||
message,
|
message: message,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -434,11 +394,6 @@ pub struct RoomNameResponse {
|
|||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pso_packet(0x6ED)]
|
|
||||||
pub struct UpdateTechMenu {
|
|
||||||
pub config: [u8; 0x28],
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pso_packet(0x7ED)]
|
#[pso_packet(0x7ED)]
|
||||||
pub struct UpdateConfig{
|
pub struct UpdateConfig{
|
||||||
pub config: [u8; 0xE8],
|
pub config: [u8; 0xE8],
|
||||||
@ -501,7 +456,7 @@ pub struct LobbyEntry {
|
|||||||
impl LobbyEntry {
|
impl LobbyEntry {
|
||||||
pub fn new(menu_id: u32, lobby_id: u32) -> LobbyEntry {
|
pub fn new(menu_id: u32, lobby_id: u32) -> LobbyEntry {
|
||||||
LobbyEntry {
|
LobbyEntry {
|
||||||
menu_id,
|
menu_id: menu_id,
|
||||||
item_id: lobby_id,
|
item_id: lobby_id,
|
||||||
padding: 0,
|
padding: 0,
|
||||||
}
|
}
|
||||||
@ -514,8 +469,8 @@ pub struct LobbyList {
|
|||||||
entries: [LobbyEntry; 16],
|
entries: [LobbyEntry; 16],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LobbyList {
|
impl LobbyList {
|
||||||
fn default() -> LobbyList {
|
pub fn new() -> LobbyList {
|
||||||
let lobbies = (0..16).fold([LobbyEntry::default(); 16],
|
let lobbies = (0..16).fold([LobbyEntry::default(); 16],
|
||||||
|mut acc, index| {
|
|mut acc, index| {
|
||||||
acc[index].menu_id = LOBBY_MENU_ID;
|
acc[index].menu_id = LOBBY_MENU_ID;
|
||||||
@ -542,9 +497,8 @@ pub struct ClientCharacterData {
|
|||||||
pub data: [u8; 2088],
|
pub data: [u8; 2088],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pso_packet(0xA2, manual_flag)]
|
#[pso_packet(0xA2)]
|
||||||
pub struct RequestQuestList {
|
pub struct RequestQuestList {
|
||||||
pub flag: u32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PSOPacketData, Clone, Copy)]
|
#[derive(PSOPacketData, Clone, Copy)]
|
||||||
@ -612,7 +566,6 @@ pub struct QuestFileRequest {
|
|||||||
pub struct QuestChunk {
|
pub struct QuestChunk {
|
||||||
pub chunk_num: u32,
|
pub chunk_num: u32,
|
||||||
pub filename: [u8; 16],
|
pub filename: [u8; 16],
|
||||||
#[nodebug]
|
|
||||||
pub blob: [u8; 0x400],
|
pub blob: [u8; 0x400],
|
||||||
pub blob_length: u32,
|
pub blob_length: u32,
|
||||||
pub unknown: u32,
|
pub unknown: u32,
|
||||||
@ -669,43 +622,15 @@ pub struct TradeConfirmed {
|
|||||||
pub struct CancelTrade {
|
pub struct CancelTrade {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pso_packet(0xD4, manual_flag)]
|
#[pso_packet(0xD4)]
|
||||||
pub struct TradeSuccessful {
|
pub struct TradeSuccessful {
|
||||||
flag: u32,
|
success: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::default::Default for TradeSuccessful {
|
impl std::default::Default for TradeSuccessful {
|
||||||
fn default() -> TradeSuccessful {
|
fn default() -> TradeSuccessful {
|
||||||
TradeSuccessful {
|
TradeSuccessful {
|
||||||
flag: 1,
|
success: 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pso_packet(0xDA, no_flag)]
|
|
||||||
pub struct LobbyEvent {
|
|
||||||
pub event: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pso_packet(0x4ED)]
|
|
||||||
pub struct KeyboardConfig {
|
|
||||||
pub keyboard_config: [u8; 364],
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pso_packet(0x5ED)]
|
|
||||||
pub struct GamepadConfig {
|
|
||||||
pub gamepad_config: [u8; 56],
|
|
||||||
}
|
|
||||||
|
|
||||||
// same struct as libpso::packet::messages::GuildcardRecv
|
|
||||||
#[pso_packet(0x4E8)]
|
|
||||||
pub struct GuildcardAccept {
|
|
||||||
id: u32,
|
|
||||||
name: [u16; 0x18],
|
|
||||||
team: [u16; 0x10],
|
|
||||||
desc: [u16; 0x58],
|
|
||||||
one: u8,
|
|
||||||
language: u8,
|
|
||||||
section_id: u8,
|
|
||||||
class: u8,
|
|
||||||
}
|
|
||||||
|
50
src/util.rs
50
src/util.rs
@ -2,7 +2,7 @@
|
|||||||
pub fn array_to_utf8<const X: usize>(array: [u8; X]) -> Result<String, std::string::FromUtf8Error> {
|
pub fn array_to_utf8<const X: usize>(array: [u8; X]) -> Result<String, std::string::FromUtf8Error> {
|
||||||
String::from_utf8(array.to_vec())
|
String::from_utf8(array.to_vec())
|
||||||
.map(|mut s| {
|
.map(|mut s| {
|
||||||
if let Some(index) = s.find('\u{0}') {
|
if let Some(index) = s.find("\u{0}") {
|
||||||
s.truncate(index);
|
s.truncate(index);
|
||||||
}
|
}
|
||||||
s
|
s
|
||||||
@ -12,23 +12,35 @@ pub fn array_to_utf8<const X: usize>(array: [u8; X]) -> Result<String, std::stri
|
|||||||
pub fn array_to_utf16(array: &[u8]) -> String {
|
pub fn array_to_utf16(array: &[u8]) -> String {
|
||||||
unsafe {
|
unsafe {
|
||||||
let (_, data, _) = array.align_to();
|
let (_, data, _) = array.align_to();
|
||||||
String::from_utf16_lossy(data).trim_matches(char::from(0)).into()
|
String::from_utf16_lossy(&data).trim_matches(char::from(0)).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn utf8_to_array<const N: usize>(s: impl Into<String>) -> [u8; N] {
|
|
||||||
let mut array = [0u8; N];
|
// TODO: const fn version of this! (helpful with tests)
|
||||||
let s = s.into();
|
#[macro_export]
|
||||||
let bytes = s.as_bytes();
|
macro_rules! utf8_to_array {
|
||||||
array[..bytes.len()].clone_from_slice(bytes);
|
($s: expr, $size: expr) => {
|
||||||
array
|
{
|
||||||
|
let mut array = [0u8; $size];
|
||||||
|
let bytes = $s.as_bytes();
|
||||||
|
array[..bytes.len()].clone_from_slice(&bytes);
|
||||||
|
array
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn utf8_to_utf16_array<const N: usize>(s: impl Into<String>) -> [u16; N] {
|
#[macro_export]
|
||||||
let mut array = [0u16; N];
|
macro_rules! utf8_to_utf16_array {
|
||||||
let bytes = s.into().encode_utf16().collect::<Vec<_>>();
|
($s: expr, $size: expr) => {
|
||||||
array[..bytes.len()].clone_from_slice(&bytes);
|
{
|
||||||
array
|
let mut array = [0u16; $size];
|
||||||
|
//let bytes = $s.as_bytes();
|
||||||
|
let bytes = $s.encode_utf16().collect::<Vec<_>>();
|
||||||
|
array[..bytes.len()].clone_from_slice(&bytes);
|
||||||
|
array
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vec_to_array<T: Default + Copy, const N: usize>(vec: Vec<T>) -> [T; N] {
|
pub fn vec_to_array<T: Default + Copy, const N: usize>(vec: Vec<T>) -> [T; N] {
|
||||||
@ -41,12 +53,10 @@ pub fn vec_to_array<T: Default + Copy, const N: usize>(vec: Vec<T>) -> [T; N] {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_utf8_to_array() {
|
fn test_utf8_to_array() {
|
||||||
let s = "asdf".to_owned();
|
let s = "asdf".to_owned();
|
||||||
let a = utf8_to_array(s);
|
let a = utf8_to_array!(s, 8);
|
||||||
|
|
||||||
let mut e = [0u8; 8];
|
let mut e = [0u8; 8];
|
||||||
e[..4].clone_from_slice(b"asdf");
|
e[..4].clone_from_slice(b"asdf");
|
||||||
@ -54,14 +64,14 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_utf8_to_utf16_array() {
|
fn utf8_to_utf16_array() {
|
||||||
let utf16 = utf8_to_utf16_array("asdf");
|
let utf16 = utf8_to_utf16_array!("asdf", 16);
|
||||||
assert!(utf16 == [97, 115, 100, 102, 0,0,0,0,0,0,0,0,0,0,0,0])
|
assert!(utf16 == [97, 115, 100, 102, 0,0,0,0,0,0,0,0,0,0,0,0])
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_utf8_to_utf16_array_unicode() {
|
fn utf8_to_utf16_array_unicode() {
|
||||||
let utf16 = utf8_to_utf16_array("あいうえお");
|
let utf16 = utf8_to_utf16_array!("あいうえお", 16);
|
||||||
assert!(utf16 == [0x3042 , 0x3044, 0x3046, 0x3048, 0x304A, 0,0,0,0,0,0,0,0,0,0,0])
|
assert!(utf16 == [0x3042 , 0x3044, 0x3046, 0x3048, 0x304A, 0,0,0,0,0,0,0,0,0,0,0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user