1use core::cmp;
84use std::fmt;
85use std::fs;
86use std::path::Path;
87use std::time::{Duration, SystemTime, UNIX_EPOCH};
88
89use anyhow::Result;
90use binrw::binrw;
91use binrw::helpers::{until, until_eof};
92use chrono::{
93 DateTime, Datelike, Local, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Timelike, Utc,
94};
95use rabbitizer::{InstrCategory, Instruction};
96use unicode_segmentation::UnicodeSegmentation;
97
98use crate::display::DisplayWithOptions;
99
100pub mod cli;
101pub mod display;
102pub mod io;
103pub mod link;
104
105#[binrw]
127#[brw(little, magic = b"LIB", assert(!objs.is_empty()))]
128#[repr(C)]
129#[derive(Debug, PartialEq)]
130pub struct LIB {
131 version: u8,
132
133 #[br(parse_with = until_eof)]
134 objs: Vec<Module>,
135}
136
137impl LIB {
138 pub fn new(objs: Vec<Module>) -> Self {
140 Self { version: 1, objs }
141 }
142
143 pub fn modules(&self) -> &Vec<Module> {
148 &self.objs
149 }
150}
151
152impl fmt::Display for LIB {
153 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
154 self.fmt_with_options(f, &display::Options::default())
155 }
156}
157
158impl display::DisplayWithOptions for LIB {
159 fn fmt_with_options(&self, f: &mut fmt::Formatter, options: &display::Options) -> fmt::Result {
160 writeln!(f, "Module Date Time Externals defined")?;
161 writeln!(f)?;
162 for obj in &self.objs {
163 obj.fmt_with_options(f, options)?;
164 writeln!(f)?;
165 }
166 Ok(())
167 }
168}
169
170#[binrw]
175#[brw(little)]
176#[repr(C)]
177#[derive(Clone, PartialEq)]
178pub struct Export {
179 name_size: u8,
180 #[br(count = name_size)]
181 name: Vec<u8>,
182}
183
184impl Export {
188 pub fn new(name: String) -> Self {
189 let mut utf8 = name.as_bytes().to_vec();
191 utf8.truncate(u8::MAX.into());
192 Self {
193 name_size: name.len() as u8,
194 name: utf8,
195 }
196 }
197
198 pub fn empty() -> Self {
199 Self {
200 name_size: 0,
201 name: Vec::new(),
202 }
203 }
204
205 pub fn name(&self) -> String {
209 if !self.name.is_empty() && self.name[0] == 0 {
211 format!("*{}", String::from_utf8_lossy(&self.name[1..]).into_owned())
212 } else {
213 String::from_utf8_lossy(&self.name).into_owned()
214 }
215 }
216}
217
218pub trait FromPSYQTimestamp {
248 fn from_psyq_timestamp(t: u32) -> Option<Self>
252 where
253 Self: Sized;
254
255 fn to_psyq_timestamp(&self) -> u32;
257}
258
259impl FromPSYQTimestamp for NaiveDate {
260 fn from_psyq_timestamp(t: u32) -> Option<Self> {
261 let date = t & 0xFFFF;
262 let year = ((date >> 9) & 0x7F) + 1980;
263 let month = (date >> 5) & 0xF;
264 let day = date & 0x1F;
265 NaiveDate::from_ymd_opt(year as i32, month, day)
266 }
267
268 fn to_psyq_timestamp(&self) -> u32 {
269 let year = (self.year() as u32 - 1980) & 0x7F;
270 let month = (self.month()) & 0xF;
271 let day = (self.day()) & 0x1F;
272
273 (year << 9) | (month << 5) | day
274 }
275}
276
277impl FromPSYQTimestamp for NaiveTime {
278 fn from_psyq_timestamp(t: u32) -> Option<Self> {
279 let time = t >> 16;
280 let hour = (time >> 11) & 0x1F;
281 let minute = (time >> 5) & 0x3F;
282 let second = (time & 0x1F) * 2;
283 NaiveTime::from_hms_opt(hour, minute, second)
284 }
285
286 fn to_psyq_timestamp(&self) -> u32 {
287 let hour = self.hour() & 0x1F;
288 let minute = self.minute() & 0x3F;
289 let second = self.second() / 2;
290
291 (hour << 27) | (minute << 21) | (second << 16)
292 }
293}
294
295impl FromPSYQTimestamp for NaiveDateTime {
296 fn from_psyq_timestamp(t: u32) -> Option<Self> {
297 Some(NaiveDateTime::new(
300 NaiveDate::from_psyq_timestamp(t)?,
301 NaiveTime::from_psyq_timestamp(t)?,
302 ))
303 }
304
305 fn to_psyq_timestamp(&self) -> u32 {
306 self.date().to_psyq_timestamp() | self.time().to_psyq_timestamp()
307 }
308}
309
310impl FromPSYQTimestamp for SystemTime {
311 fn from_psyq_timestamp(t: u32) -> Option<Self> {
312 let dt = NaiveDateTime::from_psyq_timestamp(t)?;
313 let datetime_utc = Utc.from_utc_datetime(&dt);
315 Some(UNIX_EPOCH + Duration::from_secs(datetime_utc.timestamp() as u64))
316 }
317
318 fn to_psyq_timestamp(&self) -> u32 {
319 let datetime = DateTime::<Local>::from(*self);
320 datetime.naive_utc().to_psyq_timestamp()
321 }
322}
323
324#[binrw]
329#[brw(little)]
330#[repr(C)]
331#[derive(Clone, PartialEq)]
332pub struct ModuleMetadata {
333 name: [u8; 8],
334 created: u32,
335 offset: u32,
336 size: u32,
337
338 #[br(parse_with=until(|e: &Export| e.name_size == 0))]
339 exports: Vec<Export>,
340}
341
342#[inline]
360fn path_to_module_name(path: &Path) -> [u8; 8] {
361 let Some(prefix) = path.file_prefix() else {
362 panic!("Module paths must contain a file name: {:?}", path);
363 };
364
365 let mut module_name: [u8; 8] = [0x20; 8];
366 let binding = prefix.to_ascii_uppercase();
367
368 if prefix.is_ascii() {
369 let bytes = binding.as_encoded_bytes();
371 let len = cmp::min(bytes.len(), module_name.len());
372 module_name[0..len].copy_from_slice(&bytes[0..len]);
373 } else {
374 let Some(prefix_str) = binding.to_str() else {
377 panic!("Module path is not valid unicode: {:?}", path);
378 };
379
380 let mut size = 0;
381 for (offset, cluster) in prefix_str.grapheme_indices(false) {
382 if offset > 7 || (offset + cluster.len()) > 8 {
383 break;
384 }
385 size = offset + cluster.len();
386 }
387
388 module_name[..size].copy_from_slice(&prefix_str.as_bytes()[..size]);
389 }
390 module_name
391}
392
393impl ModuleMetadata {
394 fn new_from_path(path: &Path, obj: &OBJ) -> Result<Self> {
395 let name = path_to_module_name(path);
396
397 let file_metadata = fs::metadata(path)?;
398
399 let created = if let Ok(creation_time) = file_metadata.created() {
400 creation_time.to_psyq_timestamp()
401 } else {
402 SystemTime::now().to_psyq_timestamp()
403 };
404 let mut exports = obj
405 .exports()
406 .into_iter()
407 .map(Export::new)
408 .collect::<Vec<Export>>();
409 exports.push(Export::empty());
410
411 let offset: u32 = 20 + exports.iter().map(|e| 1 + e.name_size as u32).sum::<u32>();
412 let size = offset + file_metadata.len() as u32;
413
414 Ok(Self {
415 name,
416 created,
417 offset,
418 size,
419 exports,
420 })
421 }
422
423 pub fn name(&self) -> String {
427 let end = self
429 .name
430 .iter()
431 .rposition(|x| !x.is_ascii_whitespace())
432 .expect("Module.name trim_end")
433 + 1;
434 String::from_utf8_lossy(&self.name[..end]).into_owned()
435 }
436
437 pub fn exports(&self) -> Vec<String> {
441 self.exports
442 .iter()
443 .filter_map(|e| {
444 if e.name.is_empty() {
445 None
446 } else {
447 Some(e.name())
448 }
449 })
450 .collect()
451 }
452
453 pub fn created(&self) -> String {
462 self.created_datetime()
475 .expect("created")
476 .format("%d-%m-%y %H:%M:%S")
477 .to_string()
478 }
479
480 pub fn created_datetime(&self) -> Option<NaiveDateTime> {
484 NaiveDateTime::from_psyq_timestamp(self.created)
485 }
486
487 pub fn created_at(&self) -> Option<SystemTime> {
494 SystemTime::from_psyq_timestamp(self.created)
495 }
496}
497
498#[binrw]
503#[brw(little)]
504#[repr(C)]
505#[derive(Clone, PartialEq)]
506pub struct Module {
507 metadata: ModuleMetadata,
508 obj: OBJ,
509}
510
511impl Module {
512 pub fn new_from_path(path: &Path) -> Result<Self> {
516 let obj = io::read_obj(path)?;
517 let metadata = ModuleMetadata::new_from_path(path, &obj)?;
518 Ok(Self { metadata, obj })
519 }
520
521 pub fn name(&self) -> String {
523 self.metadata.name()
524 }
525
526 pub fn exports(&self) -> Vec<String> {
528 self.metadata.exports()
529 }
530
531 pub fn created(&self) -> String {
533 self.metadata.created()
534 }
535
536 pub fn created_at(&self) -> Option<SystemTime> {
538 self.metadata.created_at()
539 }
540
541 pub fn created_datetime(&self) -> Option<NaiveDateTime> {
543 self.metadata.created_datetime()
544 }
545
546 pub fn object(&self) -> &OBJ {
548 &self.obj
549 }
550}
551
552impl fmt::Display for Module {
553 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
554 self.fmt_with_options(f, &display::Options::default())
555 }
556}
557
558impl display::DisplayWithOptions for Module {
559 fn fmt_with_options(&self, f: &mut fmt::Formatter, _options: &display::Options) -> fmt::Result {
560 write!(
561 f,
562 "{:<8} {} {}",
563 self.name(),
564 self.created(),
565 self.exports()
566 .into_iter()
567 .map(|e| format!("{e} "))
568 .collect::<Vec<_>>()
569 .join("")
570 )?;
571 Ok(())
572 }
573}
574
575impl fmt::Debug for Module {
576 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
577 write!(
578 f,
579 "Module {{name: \"{}\", huh: {}, offset: {}, size: {}, exports: \"{:?}\", lnk: {:?}}}",
580 self.name(),
581 self.metadata.created,
582 self.metadata.offset,
583 self.metadata.size,
584 self.exports(),
585 self.obj
586 )
587 }
588}
589
590#[binrw]
595#[brw(little)]
596#[repr(C)]
597pub struct OpaqueModule {
598 metadata: ModuleMetadata,
599
600 #[br(count = metadata.size - 16)]
601 obj: Vec<u8>,
602}
603
604#[binrw]
634#[brw(little, magic = b"LNK")]
635#[repr(C)]
636#[derive(Clone, Debug, PartialEq)]
637pub struct OBJ {
638 version: u8,
639 #[br(parse_with=until(|section: &Section| matches!(section, Section::NOP)))]
640 pub sections: Vec<Section>,
641}
642
643impl OBJ {
644 pub fn version(&self) -> u8 {
646 self.version
647 }
648
649 pub fn sections(&self) -> &Vec<Section> {
654 &self.sections
655 }
656
657 pub fn exports(&self) -> Vec<String> {
661 self.sections()
662 .iter()
663 .filter_map({
664 |s| match s {
665 Section::XDEF(xdef) => {
666 if xdef.symbol_name_size > 0 {
667 Some(xdef.symbol_name())
668 } else {
669 None
670 }
671 }
672 Section::XBSS(xbss) => {
673 if xbss.name_size > 0 {
674 Some(xbss.name())
675 } else {
676 None
677 }
678 }
679 _ => None,
680 }
681 })
682 .collect()
683 }
684}
685
686impl fmt::Display for OBJ {
687 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
688 writeln!(f, "Header : LNK version {}", self.version)?;
689 for section in &self.sections {
690 writeln!(f, "{}", section)?;
691 }
692 Ok(())
693 }
694}
695
696impl display::DisplayWithOptions for OBJ {
697 fn fmt_with_options(&self, f: &mut fmt::Formatter, options: &display::Options) -> fmt::Result {
698 writeln!(f, "Header : LNK version {}", self.version)?;
699 for section in &self.sections {
700 section.fmt_with_options(f, options)?;
701 writeln!(f)?;
702 }
703 Ok(())
704 }
705}
706
707#[binrw]
711#[brw(little)]
712#[derive(Clone, Debug, PartialEq)]
713pub struct Code {
714 size: u16,
715 #[br(count = size)]
716 code: Vec<u8>,
717}
718
719impl Code {
720 pub fn code(&self) -> &Vec<u8> {
723 &self.code
724 }
725}
726
727#[binrw]
731#[brw(little)]
732#[derive(Clone, Debug, PartialEq)]
733pub struct SectionSwitch {
734 id: u16,
735}
736
737#[binrw]
750#[brw(little)]
751#[derive(Clone, Debug, PartialEq)]
752pub enum Expression {
753 #[brw(magic(0u8))]
755 Constant(u32),
756
757 #[brw(magic(2u8))]
759 SymbolAddressIndex(u16),
760
761 #[brw(magic(4u8))]
763 SectionAddressIndex(u16),
764
765 #[brw(magic(6u8))]
768 Bank(u16),
769
770 #[brw(magic(8u8))]
773 SectOf(u16),
774
775 #[brw(magic(10u8))]
778 Offset(u16),
779
780 #[brw(magic(12u8))]
782 SectionStart(u16),
783
784 #[brw(magic(14u8))]
787 GroupStart(u16),
788
789 #[brw(magic(16u8))]
792 GroupOf(u16),
793
794 #[brw(magic(18u8))]
797 Segment(u16),
798
799 #[brw(magic(20u8))]
802 GroupOrg(u16),
803
804 #[brw(magic(22u8))]
806 SectionEnd(u16),
807
808 #[brw(magic(32u8))]
811 Equals(Box<Expression>, Box<Expression>),
812
813 #[brw(magic(34u8))]
815 NotEquals(Box<Expression>, Box<Expression>),
816
817 #[brw(magic(36u8))]
819 LTE(Box<Expression>, Box<Expression>),
820
821 #[brw(magic(38u8))]
823 LessThan(Box<Expression>, Box<Expression>),
824
825 #[brw(magic(40u8))]
827 GTE(Box<Expression>, Box<Expression>),
828
829 #[brw(magic(42u8))]
831 GreaterThan(Box<Expression>, Box<Expression>),
832
833 #[brw(magic(44u8))]
836 Add(Box<Expression>, Box<Expression>),
837
838 #[brw(magic(46u8))]
840 Subtract(Box<Expression>, Box<Expression>),
841
842 #[brw(magic(48u8))]
844 Multiply(Box<Expression>, Box<Expression>),
845
846 #[brw(magic(50u8))]
848 Divide(Box<Expression>, Box<Expression>),
849
850 #[brw(magic(52u8))]
852 And(Box<Expression>, Box<Expression>),
853
854 #[brw(magic(54u8))]
856 Or(Box<Expression>, Box<Expression>),
857
858 #[brw(magic(56u8))]
860 XOR(Box<Expression>, Box<Expression>),
861
862 #[brw(magic(58u8))]
864 LeftShift(Box<Expression>, Box<Expression>),
865
866 #[brw(magic(60u8))]
868 RightShift(Box<Expression>, Box<Expression>),
869
870 #[brw(magic(62u8))]
872 Mod(Box<Expression>, Box<Expression>),
873
874 #[brw(magic(64u8))]
876 Dashes(Box<Expression>, Box<Expression>),
877
878 #[brw(magic(66u8))]
881 Revword(Box<Expression>, Box<Expression>),
882
883 #[brw(magic(68u8))]
885 Check0(Box<Expression>, Box<Expression>),
886
887 #[brw(magic(70u8))]
889 Check1(Box<Expression>, Box<Expression>),
890
891 #[brw(magic(72u8))]
893 BitRange(Box<Expression>, Box<Expression>),
894
895 #[brw(magic(74u8))]
897 ArshiftChk(Box<Expression>, Box<Expression>),
898}
899
900impl fmt::Display for Expression {
901 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
902 match self {
903 Self::Constant(value) => write!(f, "${value:x}"),
904 Self::SymbolAddressIndex(addr) => write!(f, "[{addr:x}]"),
905 Self::SectionAddressIndex(base) => write!(f, "sectbase({base:x})"),
906 Self::Bank(bank) => write!(f, "bank({bank:x})"),
908 Self::SectOf(bank) => write!(f, "sectof({bank:x})"),
910 Self::Offset(bank) => write!(f, "offs({bank:x})"),
912 Self::SectionStart(offset) => write!(f, "sectstart({offset:x})"),
913 Self::GroupStart(group) => write!(f, "groupstart({group:x})"),
915 Self::GroupOf(group) => write!(f, "groupstart({group:x})"),
917 Self::Segment(segment) => write!(f, "seg({segment:x})"),
919 Self::GroupOrg(group) => write!(f, "grouporg({group:x})"),
921 Self::SectionEnd(offset) => write!(f, "sectend({offset:x})"),
922
923 Self::Equals(lhs, rhs) => write!(f, "({}={})", lhs, rhs),
925 Self::NotEquals(lhs, rhs) => write!(f, "({}<>{})", lhs, rhs),
926 Self::LTE(lhs, rhs) => write!(f, "({}<={})", lhs, rhs),
927 Self::LessThan(lhs, rhs) => write!(f, "({}<{})", lhs, rhs),
928 Self::GTE(lhs, rhs) => write!(f, "({}>={})", lhs, rhs),
929 Self::GreaterThan(lhs, rhs) => write!(f, "({}>{})", lhs, rhs),
930
931 Self::Add(lhs, rhs) => write!(f, "({}+{})", lhs, rhs),
933 Self::Subtract(lhs, rhs) => write!(f, "({}-{})", lhs, rhs),
934 Self::Multiply(lhs, rhs) => write!(f, "({}*{})", lhs, rhs),
935 Self::Divide(lhs, rhs) => write!(f, "({}/{})", lhs, rhs),
936 Self::And(lhs, rhs) => write!(f, "({}&{})", lhs, rhs),
937 Self::Or(lhs, rhs) => write!(f, "({}!{})", lhs, rhs),
938 Self::XOR(lhs, rhs) => write!(f, "({}^{})", lhs, rhs),
939 Self::LeftShift(lhs, rhs) => write!(f, "({}<<{})", lhs, rhs),
940 Self::RightShift(lhs, rhs) => write!(f, "({}>>{})", lhs, rhs),
941 Self::Mod(lhs, rhs) => write!(f, "({}%%{})", lhs, rhs),
942 Self::Dashes(lhs, rhs) => write!(f, "({}---{})", lhs, rhs),
943
944 Self::Revword(lhs, rhs) => write!(f, "({}-revword-{})", lhs, rhs),
946 Self::Check0(lhs, rhs) => write!(f, "({}-check0-{})", lhs, rhs),
947 Self::Check1(lhs, rhs) => write!(f, "({}-check1-{})", lhs, rhs),
948 Self::BitRange(lhs, rhs) => write!(f, "({}-bitrange-{})", lhs, rhs),
949 Self::ArshiftChk(lhs, rhs) => write!(f, "({}-arshift_chk-{})", lhs, rhs),
950 }
951 }
952}
953
954#[binrw]
958#[brw(little)]
959#[derive(Clone, Debug, PartialEq)]
960pub struct Patch {
961 tag: u8,
963 offset: u16,
965 expression: Expression,
967}
968
969#[binrw]
973#[brw(little)]
974#[derive(Clone, PartialEq)]
975pub struct LNKHeader {
976 section: u16,
977 group: u16,
978 align: u8,
979 type_name_size: u8,
980
981 #[br(count = type_name_size)]
982 type_name: Vec<u8>,
983}
984
985impl LNKHeader {
986 pub fn type_name(&self) -> String {
988 String::from_utf8_lossy(&self.type_name).into_owned()
989 }
990}
991
992impl fmt::Debug for LNKHeader {
993 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
994 write!(
995 f,
996 "LNKHeader {{section: {}, group: {}, align: {}, type_name: \"{}\"}}",
997 self.section,
998 self.group,
999 self.align,
1000 self.type_name(),
1001 )
1002 }
1003}
1004
1005#[binrw]
1009#[brw(little)]
1010#[derive(Clone, PartialEq)]
1011pub struct LocalSymbol {
1012 section: u16,
1013 offset: u32,
1014 name_size: u8,
1015
1016 #[br(count = name_size)]
1017 name: Vec<u8>,
1018}
1019
1020impl LocalSymbol {
1021 pub fn name(&self) -> String {
1022 String::from_utf8_lossy(&self.name).into_owned()
1023 }
1024}
1025
1026impl fmt::Debug for LocalSymbol {
1027 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1028 write!(
1029 f,
1030 "LocalSymbol {{section: {}, offset: {}, name: \"{}\"}}",
1031 self.section,
1032 self.offset,
1033 self.name(),
1034 )
1035 }
1036}
1037
1038#[binrw]
1042#[brw(little)]
1043#[derive(Clone, PartialEq)]
1044pub struct GroupSymbol {
1045 number: u16,
1046 sym_type: u8,
1047 name_size: u8,
1048
1049 #[br(count = name_size)]
1050 name: Vec<u8>,
1051}
1052
1053impl GroupSymbol {
1054 pub fn name(&self) -> String {
1055 String::from_utf8_lossy(&self.name).into_owned()
1056 }
1057}
1058
1059impl fmt::Debug for GroupSymbol {
1060 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1061 write!(
1062 f,
1063 "GroupSymbol {{number: {}, type: {}, name: \"{}\"}}",
1064 self.number,
1065 self.sym_type,
1066 self.name(),
1067 )
1068 }
1069}
1070
1071#[binrw]
1076#[brw(little)]
1077#[derive(Clone, Debug, PartialEq)]
1078pub struct XDEF {
1079 number: u16,
1080 section: u16,
1081 offset: u32,
1082 symbol_name_size: u8,
1083
1084 #[br(count = symbol_name_size)]
1085 symbol_name: Vec<u8>,
1086}
1087
1088impl XDEF {
1089 pub fn symbol_name(&self) -> String {
1090 String::from_utf8_lossy(&self.symbol_name).into_owned()
1092 }
1093}
1094
1095#[binrw]
1100#[brw(little)]
1101#[derive(Clone, Debug, PartialEq)]
1102pub struct XREF {
1103 number: u16,
1104 symbol_name_size: u8,
1105
1106 #[br(count = symbol_name_size)]
1107 symbol_name: Vec<u8>,
1108}
1109
1110impl XREF {
1111 pub fn symbol_name(&self) -> String {
1112 String::from_utf8_lossy(&self.symbol_name).into_owned()
1113 }
1114}
1115
1116pub mod cputype {
1118 pub const MOTOROLA_68000: u8 = 0;
1120
1121 pub const MIPS_R300GTE: u8 = 7;
1123
1124 pub const HITACHI_SH2: u8 = 8;
1126}
1127
1128#[binrw]
1130#[brw(little)]
1131#[derive(Clone, PartialEq)]
1132pub struct Filename {
1133 number: u16,
1134 size: u8,
1135 #[br(count = size)]
1136 name: Vec<u8>,
1137}
1138
1139impl Filename {
1140 pub fn name(&self) -> String {
1141 String::from_utf8_lossy(&self.name).into_owned()
1142 }
1143}
1144
1145impl fmt::Debug for Filename {
1146 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1147 write!(
1148 f,
1149 "Filename {{number: {}, name: \"{}\"}}",
1150 self.number,
1151 self.name(),
1152 )
1153 }
1154}
1155
1156#[binrw]
1158#[brw(little)]
1159#[derive(Clone, Debug, PartialEq)]
1160pub struct SetMXInfo {
1161 offset: u16,
1162 value: u8,
1163}
1164
1165#[binrw]
1167#[brw(little)]
1168#[derive(Clone, Debug, PartialEq)]
1169pub struct XBSS {
1170 number: u16,
1171 section: u16,
1172 size: u32,
1173 name_size: u8,
1174
1175 #[br(count = name_size)]
1176 name: Vec<u8>,
1177}
1178
1179impl XBSS {
1180 pub fn name(&self) -> String {
1181 String::from_utf8_lossy(&self.name).into_owned()
1182 }
1183}
1184
1185#[binrw]
1187#[brw(little)]
1188#[derive(Clone, Debug, PartialEq)]
1189pub struct SetSLDLineNum {
1190 offset: u16,
1191 linenum: u32,
1192}
1193
1194#[binrw]
1196#[brw(little)]
1197#[derive(Clone, Debug, PartialEq)]
1198pub struct SetSLDLineNumFile {
1199 offset: u16,
1200 linenum: u32,
1201 file: u16,
1202}
1203
1204#[binrw]
1208#[brw(little)]
1209#[derive(Clone, Debug, PartialEq)]
1210pub struct FunctionStart {
1211 section: u16,
1212 offset: u32,
1213 file: u16,
1214 linenum: u32,
1215 frame_register: u16,
1216 frame_size: u32,
1217 return_pc_register: u16,
1218 mask: u32,
1219 mask_offset: i32,
1220 name_size: u8,
1221
1222 #[br(count = name_size)]
1223 name: Vec<u8>,
1224}
1225
1226impl FunctionStart {
1227 pub fn name(&self) -> String {
1229 String::from_utf8_lossy(&self.name).into_owned()
1230 }
1231}
1232
1233#[binrw]
1235#[brw(little)]
1236#[derive(Clone, Debug, PartialEq)]
1237pub struct FunctionEnd {
1238 section: u16,
1239 offset: u32,
1240 linenum: u32,
1241}
1242
1243#[binrw]
1245#[brw(little)]
1246#[derive(Clone, Debug, PartialEq)]
1247pub struct BlockStart {
1248 section: u16,
1249 offset: u32,
1250 linenum: u32,
1251}
1252
1253#[binrw]
1255#[brw(little)]
1256#[derive(Clone, Debug, PartialEq)]
1257pub struct BlockEnd {
1258 section: u16,
1259 offset: u32,
1260 linenum: u32,
1261}
1262
1263#[binrw]
1265#[brw(little)]
1266#[derive(Clone, Debug, PartialEq)]
1267pub struct Def {
1268 section: u16,
1269 value: u32,
1270 class: u16,
1271 def_type: u16,
1272 size: u32,
1273 name_size: u8,
1274 #[br(count = name_size)]
1275 name: Vec<u8>,
1276}
1277
1278impl Def {
1279 pub fn name(&self) -> String {
1281 String::from_utf8_lossy(&self.name).into_owned()
1282 }
1283}
1284
1285#[binrw]
1287#[brw(little)]
1288#[derive(Clone, Debug, PartialEq)]
1289pub enum Dim {
1290 #[br(magic = 0u16)]
1292 None,
1293
1294 #[br(magic = 1u16)]
1296 Value(u32),
1297}
1298
1299impl fmt::Display for Dim {
1300 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1301 match self {
1302 Self::None => write!(f, "0"),
1303 Self::Value(v) => write!(f, "1 {v}"),
1304 }
1305 }
1306}
1307
1308#[binrw]
1310#[brw(little)]
1311#[derive(Clone, Debug, PartialEq)]
1312pub struct Def2 {
1313 section: u16,
1314 value: u32,
1315 class: u16,
1316 def_type: u16, size: u32, dims: Dim,
1319 tag_size: u8,
1320 #[br(count = tag_size)]
1321 tag: Vec<u8>,
1322 name_size: u8, #[br(count = name_size)]
1324 name: Vec<u8>, }
1326
1327impl Def2 {
1328 pub fn tag(&self) -> String {
1329 String::from_utf8_lossy(&self.tag).into_owned()
1330 }
1331
1332 pub fn name(&self) -> String {
1333 String::from_utf8_lossy(&self.name).into_owned()
1334 }
1335}
1336
1337#[binrw]
1350#[brw(little)]
1351#[derive(Clone, Debug, PartialEq)]
1352pub enum Section {
1353 #[brw(magic(0u8))]
1355 NOP,
1356
1357 #[brw(magic(2u8))]
1359 Code(Code),
1360
1361 #[brw(magic(4u8))]
1363 RunAtOffset(u16, u16),
1364
1365 #[brw(magic(6u8))]
1367 SectionSwitch(SectionSwitch),
1368
1369 #[brw(magic(8u8))]
1371 BSS(u32),
1372
1373 #[brw(magic(10u8))]
1375 Patch(Patch),
1376
1377 #[brw(magic(12u8))]
1379 XDEF(XDEF),
1380
1381 #[brw(magic(14u8))]
1383 XREF(XREF),
1384
1385 #[brw(magic(16u8))]
1387 LNKHeader(LNKHeader),
1388
1389 #[brw(magic(18u8))]
1391 LocalSymbol(LocalSymbol),
1392
1393 #[brw(magic(20u8))]
1395 GroupSymbol(GroupSymbol),
1396
1397 #[brw(magic(28u8))]
1403 Filename(Filename),
1404
1405 #[brw(magic(44u8))]
1415 SetMXInfo(SetMXInfo),
1416
1417 #[brw(magic(46u8))]
1419 CPU(u8),
1420
1421 #[brw(magic(48u8))]
1423 XBSS(XBSS),
1424
1425 #[brw(magic(50u8))]
1428 IncSLDLineNum(u16),
1429
1430 #[brw(magic(52u8))]
1432 IncSLDLineNumByte(u16, u8),
1433
1434 #[brw(magic(56u8))]
1437 SetSLDLineNum(SetSLDLineNum),
1438
1439 #[brw(magic(58u8))]
1441 SetSLDLineNumFile(SetSLDLineNumFile),
1442
1443 #[brw(magic(60u8))]
1445 EndSLDInfo(u16),
1446
1447 #[brw(magic(74u8))]
1458 FunctionStart(FunctionStart),
1459
1460 #[brw(magic(76u8))]
1462 FunctionEnd(FunctionEnd),
1463
1464 #[brw(magic(78u8))]
1466 BlockStart(BlockStart),
1467
1468 #[brw(magic(80u8))]
1470 BlockEnd(BlockEnd),
1471
1472 #[brw(magic(82u8))]
1475 Def(Def),
1476
1477 #[brw(magic(84u8))]
1479 Def2(Def2),
1480}
1481
1482fn is_en_gb() -> bool {
1484 let lang = if let Ok(l) = std::env::var("LC_ALL") {
1485 l
1486 } else if let Ok(l) = std::env::var("LANG") {
1487 l
1488 } else {
1489 "".to_string()
1490 };
1491
1492 lang.starts_with("en_GB")
1493}
1494
1495impl fmt::Display for Section {
1496 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1497 self.fmt_with_options(f, &display::Options::default())
1498 }
1499}
1500
1501impl display::DisplayWithOptions for Section {
1502 fn fmt_with_options(&self, f: &mut fmt::Formatter, options: &display::Options) -> fmt::Result {
1503 match self {
1504 Self::NOP => write!(f, "0 : End of file"),
1505 Self::Code(code) => {
1506 write!(f, "2 : Code {} bytes", code.code.len())?;
1507 match options.code_format {
1508 display::CodeFormat::Disassembly => {
1509 writeln!(f, "\n")?;
1510 for instruction in code.code.chunks(4) {
1511 let ins = u32::from_le_bytes(instruction.try_into().unwrap());
1512 let asm = Instruction::new(ins, 0x80000000, InstrCategory::CPU)
1513 .disassemble(None, 0);
1514 writeln!(f, " /* {ins:08x} */ {asm}")?;
1515 }
1516 }
1517 display::CodeFormat::Hex => {
1518 writeln!(f, "\n")?;
1519 for (i, chunk) in code.code.chunks(16).enumerate() {
1520 write!(f, "{:04x}:", i * 16)?;
1521 for byte in chunk {
1522 write!(f, " {:02x}", byte)?;
1523 }
1524 writeln!(f)?;
1525 }
1526 }
1527 display::CodeFormat::None => (),
1528 }
1529 Ok(())
1530 }
1531 Self::SectionSwitch(switch) => write!(f, "6 : Switch to section {:x}", switch.id),
1532 Self::BSS(size) => {
1533 let uninit = if is_en_gb() {
1534 "Uninitialised"
1535 } else {
1536 "Uninitialized"
1537 };
1538 write!(f, "8 : {} data, {} bytes", uninit, size)
1539 }
1540 Self::Patch(patch) => write!(
1541 f,
1542 "10 : Patch type {} at offset {:x} with {}",
1543 patch.tag, patch.offset, patch.expression
1544 ),
1545 Self::XDEF(xdef) => write!(
1546 f,
1547 "12 : XDEF symbol number {:x} '{}' at offset {:x} in section {:x}",
1548 xdef.number,
1549 xdef.symbol_name(),
1550 xdef.offset,
1551 xdef.section
1552 ),
1553 Self::XREF(xref) => write!(
1554 f,
1555 "14 : XREF symbol number {:x} '{}'",
1556 xref.number,
1557 xref.symbol_name()
1558 ),
1559 Self::LNKHeader(section) => write!(
1560 f,
1561 "16 : Section symbol number {:x} '{}' in group {} alignment {}",
1562 section.section,
1563 section.type_name(),
1564 section.group,
1565 section.align
1566 ),
1567 Self::LocalSymbol(symbol) => write!(
1568 f,
1569 "18 : Local symbol '{}' at offset {:x} in section {:x}",
1570 symbol.name(),
1571 symbol.offset,
1572 symbol.section
1573 ),
1574 Self::GroupSymbol(symbol) => write!(
1575 f,
1576 "20 : Group symbol number {:x} `{}` type {}",
1577 symbol.number,
1578 symbol.name(),
1579 symbol.sym_type,
1580 ),
1581 Self::Filename(filename) => write!(
1582 f,
1583 "28 : Define file number {:x} as \"{}\"",
1584 filename.number,
1585 filename.name()
1586 ),
1587 Self::SetMXInfo(set_mx_info) => write!(
1588 f,
1589 "44 : Set MX info at offset {:x} to {:x}",
1590 set_mx_info.offset, set_mx_info.value,
1591 ),
1592 Self::CPU(cpu) => write!(f, "46 : Processor type {}", { *cpu }),
1593 Self::XBSS(xbss) => write!(
1594 f,
1595 "48 : XBSS symbol number {:x} '{}' size {:x} in section {:x}",
1596 xbss.number,
1597 xbss.name(),
1598 xbss.size,
1599 xbss.section
1600 ),
1601 Self::IncSLDLineNum(offset) => write!(f, "50 : Inc SLD linenum at offset {offset:x}"),
1602 Self::IncSLDLineNumByte(offset, byte) => write!(
1603 f,
1604 "52 : Inc SLD linenum by byte {byte} at offset {offset:x}"
1605 ),
1606 Self::SetSLDLineNum(line) => write!(
1607 f,
1608 "56 : Set SLD linenum to {} at offset {:x}",
1609 line.linenum, line.offset
1610 ),
1611 Self::SetSLDLineNumFile(line) => write!(
1612 f,
1613 "58 : Set SLD linenum to {} at offset {:x} in file {:x}",
1614 line.linenum, line.offset, line.file
1615 ),
1616 Self::EndSLDInfo(offset) => write!(f, "60 : End SLD info at offset {offset:x}"),
1617 Self::FunctionStart(start) => write!(
1618 f,
1619 "74 : Function start :\n\
1620 \x20 section {:04x}\n\
1621 \x20 offset ${:08x}\n\
1622 \x20 file {:04x}\n\
1623 \x20 start line {}\n\
1624 \x20 frame reg {}\n\
1625 \x20 frame size {}\n\
1626 \x20 return pc reg {}\n\
1627 \x20 mask ${:08x}\n\
1628 \x20 mask offset {}\n\
1629 \x20 name {}",
1630 start.section,
1631 start.offset,
1632 start.file,
1633 start.linenum,
1634 start.frame_register,
1635 start.frame_size,
1636 start.return_pc_register,
1637 start.mask,
1638 start.mask_offset,
1639 start.name()
1640 ),
1641 Self::FunctionEnd(end) => write!(
1642 f,
1643 "76 : Function end :\n\
1644 \x20 section {:04x}\n\
1645 \x20 offset ${:08x}\n\
1646 \x20 end line {}",
1647 end.section, end.offset, end.linenum
1648 ),
1649 Self::BlockStart(start) => write!(
1651 f,
1652 "78 : Block start :\
1653 \x20 section {:04x}\n\
1654 \x20 offset ${:08x}\n\
1655 \x20 start line {}",
1656 start.section, start.offset, start.linenum
1657 ),
1658 Self::BlockEnd(end) => write!(
1659 f,
1660 "80 : Block end\n\
1661 \x20 section {:04x}\n\
1662 \x20 offset ${:08x}\n\
1663 \x20 end line {}",
1664 end.section, end.offset, end.linenum
1665 ),
1666 Self::Def(def) => write!(
1667 f,
1668 "82 : Def :\n\
1669 \x20 section {:04x}\n\
1670 \x20 value ${:08x}\n\
1671 \x20 class {}\n\
1672 \x20 type {}\n\
1673 \x20 size {}\n\
1674 \x20 name : {}",
1675 def.section,
1676 def.value,
1677 def.class,
1678 def.def_type,
1679 def.size,
1680 def.name()
1681 ),
1682 Self::Def2(def) => write!(
1683 f,
1684 "84 : Def2 :\n\
1685 \x20 section {:04x}\n\
1686 \x20 value ${:08x}\n\
1687 \x20 class {}\n\
1688 \x20 type {}\n\
1689 \x20 size {}\n\
1690 \x20 dims {} \n\
1691 \x20 tag {}\n\
1692 {}",
1693 def.section,
1694 def.value,
1695 def.class,
1696 def.def_type,
1697 def.size,
1698 def.dims,
1699 def.tag(),
1700 def.name()
1701 ),
1702 _ => write!(f, "{self:?}"),
1703 }
1704 }
1705}
1706
1707#[cfg(test)]
1708mod test {
1709 use std::ffi::OsStr;
1710 use std::time::UNIX_EPOCH;
1711
1712 use super::*;
1713 use binrw::io::Cursor;
1714 use binrw::{BinRead, BinWrite};
1715
1716 #[test]
1717 fn test_datetime() {
1718 let t: u32 = 0x813320af;
1719 let dt = NaiveDateTime::from_psyq_timestamp(t).expect("datetime");
1720 assert_eq!(dt.year_ce().1, 1996);
1721 assert_eq!(dt.month(), 5);
1722 assert_eq!(dt.day(), 15);
1723 assert_eq!(dt.hour(), 16);
1724 assert_eq!(dt.minute(), 9);
1725 assert_eq!(dt.second(), 38);
1726 assert_eq!(t, dt.to_psyq_timestamp());
1727 let st = SystemTime::from_psyq_timestamp(t).expect("systemtime");
1728 assert_eq!(
1729 832176578u64,
1730 st.duration_since(UNIX_EPOCH).expect("duration").as_secs()
1731 );
1732 assert_eq!(t, st.to_psyq_timestamp());
1733
1734 let t: u32 = 0x8d061f4c;
1735 let dt = NaiveDateTime::from_psyq_timestamp(t).expect("datetime");
1736 assert_eq!(dt.year_ce().1, 1995);
1737 assert_eq!(dt.month(), 10);
1738 assert_eq!(dt.day(), 12);
1739 assert_eq!(dt.hour(), 17);
1740 assert_eq!(dt.minute(), 40);
1741 assert_eq!(dt.second(), 12);
1742 assert_eq!(t, dt.to_psyq_timestamp());
1743 let st = SystemTime::from_psyq_timestamp(t).expect("systemtime");
1744 assert_eq!(
1745 813519612u64,
1746 st.duration_since(UNIX_EPOCH).expect("duration").as_secs()
1747 );
1748 assert_eq!(t, st.to_psyq_timestamp());
1749 }
1750
1751 #[test]
1752 fn test_path_to_module_name() {
1753 assert_eq!(
1754 *b"OUTPUT ",
1755 path_to_module_name(Path::new("some/output.obj"))
1756 );
1757 assert_eq!(
1758 *b"LONGNAME",
1759 path_to_module_name(Path::new("some/longname.obj"))
1760 );
1761 assert_eq!(
1763 *b"LONGERNA",
1764 path_to_module_name(Path::new("some/longername.obj"))
1765 );
1766 let name: [u8; 8] = "👾 ".as_bytes().try_into().unwrap();
1768 assert_eq!(name, path_to_module_name(Path::new("some/👾.obj")));
1769 let name: [u8; 8] = "👾☕ ".as_bytes().try_into().unwrap();
1771 assert_eq!(name, path_to_module_name(Path::new("some/👾☕☕.obj")));
1772 let name: [u8; 8] = "👾👾".as_bytes().try_into().unwrap();
1774 assert_eq!(name, path_to_module_name(Path::new("some/👾👾.obj")));
1775 let name: [u8; 8] = "AÍ¢B ".as_bytes().try_into().unwrap();
1777 assert_eq!(name, path_to_module_name(Path::new("some/a͢b.obj")));
1778 }
1779
1780 #[test]
1781 #[should_panic]
1782 fn test_path_to_module_name_missing_file_name() {
1783 path_to_module_name(Path::new("."));
1784 }
1785
1786 #[test]
1787 #[should_panic]
1788 fn test_path_to_module_name_invalid_unicode() {
1789 let s: &OsStr;
1791 unsafe {
1792 s = OsStr::from_encoded_bytes_unchecked(&[
1793 0xC0, 0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x2e, 0x6f, 0x62, 0x6a,
1794 ]);
1795 }
1796 path_to_module_name(Path::new(s));
1797 }
1798
1799 #[test]
1800 fn test_lib() {
1801 let bytes = b"\
1802 \x4C\x49\x42\x01\x41\x35\x36\x20\x20\x20\x20\x20\xAF\x20\x2C\x81\
1803 \x1A\x00\x00\x00\x8E\x00\x00\x00\x04\x65\x78\x69\x74\x00\x4C\x4E\
1804 \x4B\x02\x2E\x07\x10\x04\xF0\x00\x00\x08\x06\x2E\x72\x64\x61\x74\
1805 \x61\x10\x00\xF0\x00\x00\x08\x05\x2E\x74\x65\x78\x74\x10\x01\xF0\
1806 \x00\x00\x08\x05\x2E\x64\x61\x74\x61\x10\x03\xF0\x00\x00\x08\x06\
1807 \x2E\x73\x64\x61\x74\x61\x10\x05\xF0\x00\x00\x08\x04\x2E\x62\x73\
1808 \x73\x10\x02\xF0\x00\x00\x08\x05\x2E\x73\x62\x73\x73\x0C\x01\x00\
1809 \x00\xF0\x00\x00\x00\x00\x04\x65\x78\x69\x74\x06\x00\xF0\x02\x10\
1810 \x00\xB0\x00\x0A\x24\x08\x00\x40\x01\x38\x00\x09\x24\x00\x00\x00\
1811 \x00\x00"
1812 .to_vec();
1813 let mut data = Cursor::new(&bytes);
1815 let lib = LIB::read(&mut data).unwrap();
1816 assert_eq!(lib.version, 1);
1817 let obj = lib.modules().first().expect("obj[0]");
1820 assert_eq!(obj.name(), "A56");
1821 assert_eq!(obj.metadata.created, 2167152815);
1822 assert_eq!(obj.metadata.offset, 26);
1823 assert_eq!(obj.metadata.size, 142);
1824 assert_eq!(obj.metadata.exports.len(), 2);
1825 assert_eq!(obj.exports().len(), 1);
1826
1827 let export = obj.metadata.exports.first().expect("obj[0].exports[0]");
1828 assert_eq!(export.name_size, 4);
1829 assert_eq!(export.name(), "exit");
1830
1831 let lnk = &obj.obj;
1832 assert_eq!(lnk.version, 2);
1833
1834 let Section::CPU(cpu) = lnk.sections.first().expect("obj[0].obj.sections[0]") else {
1835 panic!("expected a section");
1836 };
1837 assert_eq!(*cpu, cputype::MIPS_R300GTE);
1838 assert_eq!(data.position(), bytes.len() as u64);
1847
1848 let mut writer = Cursor::new(Vec::new());
1850 lib.write_le(&mut writer).unwrap();
1851 assert_eq!(writer.into_inner(), bytes);
1852 }
1853
1854 #[test]
1855 fn test_object_entry() {
1856 let bytes = b"\
1857 \x53\x50\x52\x49\x4E\x54\x46\x20\xAF\x20\x33\x81\x1D\x00\x00\x00\
1858 \x25\x0E\x00\x00\x07\x73\x70\x72\x69\x6E\x74\x66\x00\x4C\x4E\x4B\
1859 \x02\x2E\x07\x10\x01\x00\x00\x00\x08\x06\x2E\x72\x64\x61\x74\x61\
1860 \x10\x02\x00\x00\x00\x08\x05\x2E\x74\x65\x78\x74\x10\x03\x00\x00\
1861 \x00\x08\x05\x2E\x64\x61\x74\x61\x10\x04\x00\x00\x00\x08\x06\x2E\
1862 \x73\x64\x61\x74\x61\x10\x05\x00\x00\x00\x08\x05\x2E\x73\x62\x73\
1863 \x73\x10\x06\x00\x00\x00\x08\x04\x2E\x62\x73\x73\x10\x07\x00\x00\
1864 \x00\x08\x06\x2E\x63\x74\x6F\x72\x73\x10\x08\x00\x00\x00\x08\x06\
1865 \x2E\x64\x74\x6F\x72\x73\x1C\x09\x00\x17\x43\x3A\x5C\x50\x53\x58\
1866 \x5C\x53\x52\x43\x5C\x43\x32\x5C\x53\x50\x52\x49\x4E\x54\x46\x2E\
1867 \x43\x06\x02\x00\x06\x03\x00\x02\x01\x00\x00\x08\x0B\x00\x00\x00\
1868 \x06\x01\x00\x02\x25\x00\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\
1869 \x41\x42\x43\x44\x45\x46\x00\x00\x00\x00\x30\x31\x32\x33\x34\x35\
1870 \x36\x37\x38\x39\x61\x62\x63\x64\x65\x66\x00\x06\x02\x00\x02\xC8\
1871 \x02\x04\x00\xA5\xAF\x08\x00\xA6\xAF\x0C\x00\xA7\xAF\xB8\xFD\xBD\
1872 \x27\x34\x02\xB3\xAF\x21\x98\x80\x00\x50\x02\xA2\x27\x44\x02\xBF\
1873 \xAF\x40\x02\xB6\xAF\x3C\x02\xB5\xAF\x38\x02\xB4\xAF\x30\x02\xB2\
1874 \xAF\x2C\x02\xB1\xAF\x28\x02\xB0\xAF\x4C\x02\xA5\xAF\x20\x02\xA2\
1875 \xAF\x00\x00\xA5\x90\x00\x00\x00\x00\xF6\x01\xA0\x10\x21\x90\x00\
1876 \x00\x2D\x00\x16\x34\x2B\x00\x15\x34\x20\x00\x14\x34\x25\x00\x02\
1877 \x34\xC0\x01\xA2\x14\x21\x10\x72\x02\x00\x00\x05\x3C\x00\x00\xA5\
1878 \x24\x00\x00\xA2\x8C\x04\x00\xA3\x8C\x08\x00\xA4\x8C\x10\x02\xA2\
1879 \xAF\x14\x02\xA3\xAF\x18\x02\xA4\xAF\x23\x00\x06\x34\x30\x00\x03\
1880 \x34\x4C\x02\xA4\x8F\x00\x00\x00\x00\x01\x00\x82\x24\x4C\x02\xA2\
1881 \xAF\x01\x00\x85\x90\x00\x00\x00\x00\x06\x00\xB6\x14\x00\x00\x00\
1882 \x00\x10\x02\xA2\x8F\x00\x00\x00\x00\x01\x00\x42\x34\x00\x00\x00\
1883 \x08\x10\x02\xA2\xAF\x06\x00\xB5\x14\x00\x00\x00\x00\x10\x02\xA2\
1884 \x8F\x00\x00\x00\x00\x02\x00\x42\x34\x00\x00\x00\x08\x10\x02\xA2\
1885 \xAF\x03\x00\xB4\x14\x00\x00\x00\x00\x00\x00\x00\x08\x11\x02\xA5\
1886 \xA3\x06\x00\xA6\x14\x00\x00\x00\x00\x10\x02\xA2\x8F\x00\x00\x00\
1887 \x00\x04\x00\x42\x34\x00\x00\x00\x08\x10\x02\xA2\xAF\x06\x00\xA3\
1888 \x14\x2A\x00\x02\x34\x10\x02\xA2\x8F\x00\x00\x00\x00\x08\x00\x42\
1889 \x34\x00\x00\x00\x08\x10\x02\xA2\xAF\x22\x00\xA2\x14\xD0\xFF\xA2\
1890 \x24\x20\x02\xA3\x8F\x00\x00\x00\x00\x04\x00\x62\x24\x20\x02\xA2\
1891 \xAF\x00\x00\x62\x8C\x00\x00\x00\x00\x06\x00\x41\x04\x14\x02\xA2\
1892 \xAF\x10\x02\xA3\x8F\x23\x10\x02\x00\x14\x02\xA2\xAF\x01\x00\x63\
1893 \x34\x10\x02\xA3\xAF\x02\x00\x82\x24\x4C\x02\xA2\xAF\x02\x00\x85\
1894 \x90\x00\x00\x00\x08\x2E\x00\x02\x34\x14\x02\xA3\x8F\x00\x00\x00\
1895 \x00\x80\x10\x03\x00\x21\x10\x43\x00\x40\x10\x02\x00\xD0\xFF\x42\
1896 \x24\x21\x10\x45\x00\x14\x02\xA2\xAF\x4C\x02\xA3\x8F\x00\x00\x00\
1897 \x00\x01\x00\x62\x24\x4C\x02\xA2\xAF\x01\x00\x65\x90\x00\x00\x00\
1898 \x00\xD0\xFF\xA2\x24\x0A\x00\x42\x2C\xEF\xFF\x40\x14\x2E\x00\x02\
1899 \x34\x2F\x00\xA2\x14\x00\x00\x00\x00\x4C\x02\xA4\x8F\x00\x00\x00\
1900 \x00\x01\x00\x82\x24\x4C\x02\xA2\xAF\x01\x00\x85\x90\x2A\x00\x02\
1901 \x34\x1C\x00\xA2\x14\xD0\xFF\xA2\x24\x20\x02\xA3\x8F\x00\x00\x00\
1902 \x00\x04\x00\x62\x24\x20\x02\xA2\xAF\x00\x00\x62\x8C\x00\x00\x00\
1903 \x00\x18\x02\xA2\xAF\x02\x00\x82\x24\x4C\x02\xA2\xAF\x02\x00\x85\
1904 \x90\x00\x00\x00\x08\x00\x00\x00\x00\x18\x02\xA3\x8F\x00\x00\x00\
1905 \x00\x80\x10\x03\x00\x21\x10\x43\x00\x40\x10\x02\x00\xD0\xFF\x42\
1906 \x24\x21\x10\x45\x00\x18\x02\xA2\xAF\x4C\x02\xA3\x8F\x00\x00\x00\
1907 \x00\x01\x00\x62\x24\x4C\x02\xA2\xAF\x01\x00\x65\x90\x00\x00\x00\
1908 \x00\xD0\xFF\xA2\x24\x0A\x00\x42\x2C\xEF\xFF\x40\x14\x00\x00\x00\
1909 \x00\x18\x02\xA2\x8F\x00\x00\x00\x00\x05\x00\x40\x04\x00\x00\x00\
1910 \x00\x10\x02\xA2\x8F\x00\x00\x00\x00\x10\x00\x42\x34\x10\x02\xA2\
1911 \xAF\x10\x02\xA3\x8F\x00\x00\x00\x00\x01\x00\x62\x30\x04\x00\x40\
1912 \x10\x10\x02\xB1\x27\xF7\xFF\x02\x24\x24\x10\x62\x00\x10\x02\xA2\
1913 \xAF\xB4\xFF\xA3\x24\x2D\x00\x62\x2C\x2B\x01\x40\x10\x80\x10\x03\
1914 \x00\x00\x00\x01\x3C\x21\x08\x22\x00\x00\x00\x22\x8C\x00\x00\x00\
1915 \x00\x08\x00\x40\x00\x00\x00\x00\x00\x0A\x52\x68\x00\x2C\x04\x03\
1916 \x00\x00\x00\x00\x00\x00\x0A\x54\x6C\x00\x2C\x04\x03\x00\x00\x00\
1917 \x00\x00\x00\x0A\x4A\xBC\x00\x2C\x04\x02\x00\x00\x90\x00\x00\x00\
1918 \x0A\x4A\xD8\x00\x2C\x04\x02\x00\x00\x90\x00\x00\x00\x0A\x4A\xE8\
1919 \x00\x2C\x04\x02\x00\x00\x90\x00\x00\x00\x0A\x4A\x04\x01\x2C\x04\
1920 \x02\x00\x00\x90\x00\x00\x00\x0A\x4A\x20\x01\x2C\x04\x02\x00\x00\
1921 \x90\x00\x00\x00\x0A\x4A\x70\x01\x2C\x04\x02\x00\x00\xC0\x01\x00\
1922 \x00\x0A\x4A\x10\x02\x2C\x04\x02\x00\x00\x60\x02\x00\x00\x0A\x52\
1923 \xB0\x02\x2C\x04\x01\x00\x00\x28\x00\x00\x00\x0A\x54\xB8\x02\x2C\
1924 \x04\x01\x00\x00\x28\x00\x00\x00\x06\x01\x00\x02\xB7\x00\x00\x00\
1925 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
1926 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
1927 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
1928 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
1929 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
1930 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
1931 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
1932 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
1933 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
1934 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
1935 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
1936 \x00\x00\x00\x00\x00\x0A\x10\x03\x00\x2C\x04\x02\x00\x00\xE0\x02\
1937 \x00\x00\x0A\x10\x07\x00\x2C\x04\x02\x00\x00\x58\x07\x00\x00\x0A\
1938 \x10\x0B\x00\x2C\x04\x02\x00\x00\x58\x07\x00\x00\x0A\x10\x0F\x00\
1939 \x2C\x04\x02\x00\x00\x58\x07\x00\x00\x0A\x10\x13\x00\x2C\x04\x02\
1940 \x00\x00\x58\x07\x00\x00\x0A\x10\x17\x00\x2C\x04\x02\x00\x00\x58\
1941 \x07\x00\x00\x0A\x10\x1B\x00\x2C\x04\x02\x00\x00\x58\x07\x00\x00\
1942 \x0A\x10\x1F\x00\x2C\x04\x02\x00\x00\x58\x07\x00\x00\x0A\x10\x23\
1943 \x00\x2C\x04\x02\x00\x00\x58\x07\x00\x00\x0A\x10\x27\x00\x2C\x04\
1944 \x02\x00\x00\x58\x07\x00\x00\x0A\x10\x2B\x00\x2C\x04\x02\x00\x00\
1945 \x58\x07\x00\x00\x0A\x10\x2F\x00\x2C\x04\x02\x00\x00\x58\x07\x00\
1946 \x00\x0A\x10\x33\x00\x2C\x04\x02\x00\x00\x78\x05\x00\x00\x0A\x10\
1947 \x37\x00\x2C\x04\x02\x00\x00\x58\x07\x00\x00\x0A\x10\x3B\x00\x2C\
1948 \x04\x02\x00\x00\x58\x07\x00\x00\x0A\x10\x3F\x00\x2C\x04\x02\x00\
1949 \x00\x58\x07\x00\x00\x0A\x10\x43\x00\x2C\x04\x02\x00\x00\x58\x07\
1950 \x00\x00\x0A\x10\x47\x00\x2C\x04\x02\x00\x00\x58\x07\x00\x00\x0A\
1951 \x10\x4B\x00\x2C\x04\x02\x00\x00\x58\x07\x00\x00\x0A\x10\x4F\x00\
1952 \x2C\x04\x02\x00\x00\x58\x07\x00\x00\x0A\x10\x53\x00\x2C\x04\x02\
1953 \x00\x00\x58\x07\x00\x00\x0A\x10\x57\x00\x2C\x04\x02\x00\x00\x58\
1954 \x07\x00\x00\x0A\x10\x5B\x00\x2C\x04\x02\x00\x00\x58\x07\x00\x00\
1955 \x0A\x10\x5F\x00\x2C\x04\x02\x00\x00\x80\x06\x00\x00\x0A\x10\x63\
1956 \x00\x2C\x04\x02\x00\x00\x0C\x03\x00\x00\x0A\x10\x67\x00\x2C\x04\
1957 \x02\x00\x00\x58\x07\x00\x00\x0A\x10\x6B\x00\x2C\x04\x02\x00\x00\
1958 \x58\x07\x00\x00\x0A\x10\x6F\x00\x2C\x04\x02\x00\x00\x58\x07\x00\
1959 \x00\x0A\x10\x73\x00\x2C\x04\x02\x00\x00\xC8\x02\x00\x00\x0A\x10\
1960 \x77\x00\x2C\x04\x02\x00\x00\x0C\x03\x00\x00\x0A\x10\x7B\x00\x2C\
1961 \x04\x02\x00\x00\x58\x07\x00\x00\x0A\x10\x7F\x00\x2C\x04\x02\x00\
1962 \x00\x58\x07\x00\x00\x0A\x10\x83\x00\x2C\x04\x02\x00\x00\xD4\x02\
1963 \x00\x00\x0A\x10\x87\x00\x2C\x04\x02\x00\x00\x58\x07\x00\x00\x0A\
1964 \x10\x8B\x00\x2C\x04\x02\x00\x00\x24\x07\x00\x00\x0A\x10\x8F\x00\
1965 \x2C\x04\x02\x00\x00\x74\x04\x00\x00\x0A\x10\x93\x00\x2C\x04\x02\
1966 \x00\x00\x64\x05\x00\x00\x0A\x10\x97\x00\x2C\x04\x02\x00\x00\x58\
1967 \x07\x00\x00\x0A\x10\x9B\x00\x2C\x04\x02\x00\x00\x58\x07\x00\x00\
1968 \x0A\x10\x9F\x00\x2C\x04\x02\x00\x00\xA0\x06\x00\x00\x0A\x10\xA3\
1969 \x00\x2C\x04\x02\x00\x00\x58\x07\x00\x00\x0A\x10\xA7\x00\x2C\x04\
1970 \x02\x00\x00\x5C\x03\x00\x00\x0A\x10\xAB\x00\x2C\x04\x02\x00\x00\
1971 \x58\x07\x00\x00\x0A\x10\xAF\x00\x2C\x04\x02\x00\x00\x58\x07\x00\
1972 \x00\x0A\x10\xB3\x00\x2C\x04\x02\x00\x00\x88\x05\x00\x00\x06\x02\
1973 \x00\x02\x94\x05\x10\x02\xA2\x8F\x00\x00\x00\x08\x20\x00\x42\x34\
1974 \x10\x02\xA2\x8F\x00\x00\x00\x08\x40\x00\x42\x34\x10\x02\xA2\x8F\
1975 \x00\x00\x00\x00\x80\x00\x42\x34\x10\x02\xA2\xAF\x4C\x02\xA3\x8F\
1976 \x00\x00\x00\x00\x01\x00\x62\x24\x4C\x02\xA2\xAF\x01\x00\x65\x90\
1977 \x00\x00\x00\x08\xB4\xFF\xA3\x24\x20\x02\xA3\x8F\x00\x00\x00\x00\
1978 \x04\x00\x62\x24\x20\x02\xA2\xAF\x00\x00\x64\x8C\x10\x02\xA3\x8F\
1979 \x00\x00\x00\x00\x20\x00\x62\x30\x02\x00\x40\x10\x00\x14\x04\x00\
1980 \x03\x24\x02\x00\x04\x00\x81\x04\x02\x00\x62\x30\x23\x20\x04\x00\
1981 \x00\x00\x00\x08\x11\x02\xB6\xA3\x0E\x00\x40\x10\x00\x00\x00\x00\
1982 \x00\x00\x00\x08\x11\x02\xB5\xA3\x20\x02\xA3\x8F\x00\x00\x00\x00\
1983 \x04\x00\x62\x24\x20\x02\xA2\xAF\x00\x00\x64\x8C\x10\x02\xA2\x8F\
1984 \x00\x00\x00\x00\x20\x00\x42\x30\x02\x00\x40\x10\x11\x02\xA0\xA3\
1985 \xFF\xFF\x84\x30\x10\x02\xA3\x8F\x00\x00\x00\x00\x10\x00\x62\x30\
1986 \x0F\x00\x40\x14\x08\x00\x62\x30\x08\x00\x40\x10\x00\x00\x00\x00\
1987 \x14\x02\xA3\x8F\x11\x02\xA2\x93\x00\x00\x00\x00\x03\x00\x40\x10\
1988 \x18\x02\xA3\xAF\xFF\xFF\x62\x24\x18\x02\xA2\xAF\x18\x02\xA2\x8F\
1989 \x00\x00\x00\x00\x02\x00\x40\x1C\x01\x00\x02\x34\x18\x02\xA2\xAF\
1990 \x10\x00\x80\x10\x21\x80\x00\x00\xCC\xCC\x05\x3C\xCD\xCC\xA5\x34\
1991 \x19\x00\x85\x00\xFF\xFF\x31\x26\x01\x00\x10\x26\x10\x18\x00\x00\
1992 \xC2\x18\x03\x00\x80\x10\x03\x00\x21\x10\x43\x00\x40\x10\x02\x00\
1993 \x23\x10\x82\x00\x30\x00\x42\x24\x21\x20\x60\x00\xF4\xFF\x80\x14\
1994 \x00\x00\x22\xA2\x18\x02\xA2\x8F\x00\x00\x00\x00\x2A\x10\x02\x02\
1995 \x0A\x00\x40\x10\x00\x00\x00\x00\x30\x00\x03\x34\xFF\xFF\x31\x26\
1996 \x00\x00\x23\xA2\x18\x02\xA2\x8F\x01\x00\x10\x26\x2A\x10\x02\x02\
1997 \xFB\xFF\x40\x14\xFF\xFF\x31\x26\x01\x00\x31\x26\x11\x02\xA2\x93\
1998 \x00\x00\x00\x00\xC5\x00\x40\x10\x00\x00\x00\x00\xFF\xFF\x31\x26\
1999 \x11\x02\xA2\x93\x01\x00\x10\x26\x00\x00\x00\x08\x00\x00\x22\xA2\
2000 \x20\x02\xA3\x8F\x00\x00\x00\x00\x04\x00\x62\x24\x20\x02\xA2\xAF\
2001 \x00\x00\x64\x8C\x10\x02\xA3\x8F\x00\x00\x00\x00\x20\x00\x62\x30\
2002 \x02\x00\x40\x10\x10\x00\x62\x30\xFF\xFF\x84\x30\x0B\x00\x40\x14\
2003 \x08\x00\x62\x30\x04\x00\x40\x10\x00\x00\x00\x00\x14\x02\xA2\x8F\
2004 \x00\x00\x00\x00\x18\x02\xA2\xAF\x18\x02\xA2\x8F\x00\x00\x00\x00\
2005 \x02\x00\x40\x1C\x01\x00\x02\x34\x18\x02\xA2\xAF\x08\x00\x80\x10\
2006 \x21\x80\x00\x00\xFF\xFF\x31\x26\x07\x00\x82\x30\x30\x00\x42\x24\
2007 \x00\x00\x22\xA2\xC2\x20\x04\x00\xFA\xFF\x80\x14\x01\x00\x10\x26\
2008 \x10\x02\xA2\x8F\x00\x00\x00\x00\x04\x00\x42\x30\x0A\x00\x40\x10\
2009 \x00\x00\x00\x00\x08\x00\x00\x12\x30\x00\x02\x34\x00\x00\x23\x92\
2010 \x00\x00\x00\x00\x04\x00\x62\x10\x30\x00\x02\x34\xFF\xFF\x31\x26\
2011 \x00\x00\x22\xA2\x01\x00\x10\x26\x18\x02\xA2\x8F\x00\x00\x00\x00\
2012 \x2A\x10\x02\x02\x8D\x00\x40\x10\x30\x00\x03\x34\xFF\xFF\x31\x26\
2013 \x00\x00\x23\xA2\x18\x02\xA2\x8F\x01\x00\x10\x26\x2A\x10\x02\x02\
2014 \xFB\xFF\x40\x14\xFF\xFF\x31\x26\x00\x00\x00\x08\x01\x00\x31\x26\
2015 \x10\x02\xA3\x8F\x08\x00\x02\x34\x18\x02\xA2\xAF\x50\x00\x63\x34\
2016 \x10\x02\xA3\xAF\x00\x00\x07\x3C\x00\x00\xE7\x24\x00\x00\x00\x08\
2017 \x00\x00\x00\x00\x00\x00\x07\x3C\x00\x00\xE7\x24\x20\x02\xA3\x8F\
2018 \x00\x00\x00\x00\x04\x00\x62\x24\x20\x02\xA2\xAF\x00\x00\x64\x8C\
2019 \x10\x02\xA3\x8F\x00\x00\x00\x00\x20\x00\x62\x30\x02\x00\x40\x10\
2020 \x10\x00\x62\x30\xFF\xFF\x84\x30\x0D\x00\x40\x14\x08\x00\x62\x30\
2021 \x06\x00\x40\x10\x04\x00\x62\x30\x14\x02\xA6\x8F\x03\x00\x40\x10\
2022 \x18\x02\xA6\xAF\xFE\xFF\xC2\x24\x18\x02\xA2\xAF\x18\x02\xA2\x8F\
2023 \x00\x00\x00\x00\x02\x00\x40\x1C\x01\x00\x02\x34\x18\x02\xA2\xAF\
2024 \x09\x00\x80\x10\x21\x80\x00\x00\xFF\xFF\x31\x26\x0F\x00\x82\x30\
2025 \x02\x21\x04\x00\x21\x10\xE2\x00\x00\x00\x42\x90\x01\x00\x10\x26\
2026 \xF9\xFF\x80\x14\x00\x00\x22\xA2\x18\x02\xA2\x8F\x00\x00\x00\x00\
2027 \x2A\x10\x02\x02\x0A\x00\x40\x10\x00\x00\x00\x00\x30\x00\x03\x34\
2028 \xFF\xFF\x31\x26\x00\x00\x23\xA2\x18\x02\xA2\x8F\x01\x00\x10\x26\
2029 \x2A\x10\x02\x02\xFB\xFF\x40\x14\xFF\xFF\x31\x26\x01\x00\x31\x26\
2030 \x10\x02\xA2\x8F\x00\x00\x00\x00\x04\x00\x42\x30\x43\x00\x40\x10\
2031 \x30\x00\x02\x34\xFF\xFF\x31\x26\x00\x00\x25\xA2\xFF\xFF\x31\x26\
2032 \x02\x00\x10\x26\x00\x00\x00\x08\x00\x00\x22\xA2\x20\x02\xA2\x8F\
2033 \xFF\xFF\x31\x26\x04\x00\x43\x24\x20\x02\xA3\xAF\x00\x00\x42\x90\
2034 \x01\x00\x10\x34\x00\x00\x00\x08\x00\x00\x22\xA2\x20\x02\xA2\x8F\
2035 \x00\x00\x00\x00\x04\x00\x43\x24\x20\x02\xA3\xAF\x10\x02\xA3\x8F\
2036 \x00\x00\x51\x8C\x04\x00\x62\x30\x0B\x00\x40\x10\x10\x00\x62\x30\
2037 \x00\x00\x30\x92\x29\x00\x40\x10\x01\x00\x31\x26\x18\x02\xA3\x8F\
2038 \x00\x00\x00\x00\x2A\x10\x70\x00\x24\x00\x40\x10\x00\x00\x00\x00\
2039 \x00\x00\x00\x08\x21\x80\x60\x00\x05\x00\x40\x14\x21\x20\x20\x02\
2040 \x00\x00\x00\x0C\x21\x20\x20\x02\x00\x00\x00\x08\x21\x80\x40\x00\
2041 \x18\x02\xA6\x8F\x00\x00\x00\x0C\x21\x28\x00\x00\x17\x00\x40\x14\
2042 \x23\x80\x51\x00\x18\x02\xB0\x8F\x00\x00\x00\x08\x00\x00\x00\x00\
2043 \x20\x02\xA2\x8F\x00\x00\x00\x00\x04\x00\x43\x24\x20\x02\xA3\xAF\
2044 \x10\x02\xA3\x8F\x00\x00\x51\x8C\x20\x00\x62\x30\x03\x00\x40\x10\
2045 \x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x32\xA6\x00\x00\x00\x08\
2046 \x00\x00\x32\xAE\x25\x00\x02\x34\x31\x00\xA2\x14\x21\x10\x72\x02\
2047 \x00\x00\x45\xA0\x00\x00\x00\x08\x01\x00\x52\x26\x14\x02\xA2\x8F\
2048 \x00\x00\x00\x00\x2A\x10\x02\x02\x11\x00\x40\x10\x21\x20\x72\x02\
2049 \x10\x02\xA2\x8F\x00\x00\x00\x00\x01\x00\x42\x30\x0D\x00\x40\x14\
2050 \x21\x28\x20\x02\x21\x18\x53\x02\x00\x00\x74\xA0\x01\x00\x63\x24\
2051 \x14\x02\xA2\x8F\x00\x00\x00\x00\xFF\xFF\x42\x24\x14\x02\xA2\xAF\
2052 \x2A\x10\x02\x02\xF8\xFF\x40\x14\x01\x00\x52\x26\x21\x20\x72\x02\
2053 \x21\x28\x20\x02\x00\x00\x00\x0C\x21\x30\x00\x02\x14\x02\xA2\x8F\
2054 \x00\x00\x00\x00\x2A\x10\x02\x02\x09\x00\x40\x10\x21\x90\x50\x02\
2055 \x21\x18\x53\x02\x00\x00\x74\xA0\x01\x00\x63\x24\x14\x02\xA2\x8F\
2056 \x01\x00\x10\x26\x2A\x10\x02\x02\xFA\xFF\x40\x14\x01\x00\x52\x26\
2057 \x4C\x02\xA3\x8F\x00\x00\x00\x00\x01\x00\x62\x24\x4C\x02\xA2\xAF\
2058 \x01\x00\x65\x90\x00\x00\x00\x00\x10\xFE\xA0\x14\x25\x00\x02\x34\
2059 \x21\x10\x72\x02\x00\x00\x40\xA0\x21\x10\x40\x02\x44\x02\xBF\x8F\
2060 \x40\x02\xB6\x8F\x3C\x02\xB5\x8F\x38\x02\xB4\x8F\x34\x02\xB3\x8F\
2061 \x30\x02\xB2\x8F\x2C\x02\xB1\x8F\x28\x02\xB0\x8F\x48\x02\xBD\x27\
2062 \x08\x00\xE0\x03\x00\x00\x00\x00\x0A\x4A\x04\x00\x2C\x04\x02\x00\
2063 \x00\xEC\x02\x00\x00\x0A\x4A\x10\x00\x2C\x04\x02\x00\x00\xEC\x02\
2064 \x00\x00\x0A\x4A\x3C\x00\x2C\x04\x02\x00\x00\xA4\x02\x00\x00\x0A\
2065 \x4A\x7C\x00\x2C\x04\x02\x00\x00\x88\x03\x00\x00\x0A\x4A\x8C\x00\
2066 \x2C\x04\x02\x00\x00\x88\x03\x00\x00\x0A\x4A\xA4\x01\x2C\x04\x02\
2067 \x00\x00\x70\x07\x00\x00\x0A\x4A\x94\x02\x2C\x04\x02\x00\x00\x70\
2068 \x07\x00\x00\x0A\x52\xB0\x02\x2C\x04\x01\x00\x00\x00\x00\x00\x00\
2069 \x0A\x54\xB4\x02\x2C\x04\x01\x00\x00\x00\x00\x00\x00\x0A\x4A\xB8\
2070 \x02\x2C\x04\x02\x00\x00\x90\x05\x00\x00\x0A\x52\xC0\x02\x2C\x04\
2071 \x01\x00\x00\x14\x00\x00\x00\x0A\x54\xC4\x02\x2C\x04\x01\x00\x00\
2072 \x14\x00\x00\x00\x0A\x4A\xB0\x03\x2C\x04\x02\x00\x00\x70\x07\x00\
2073 \x00\x0A\x4A\xD0\x03\x2C\x04\x02\x00\x00\x70\x07\x00\x00\x0A\x4A\
2074 \x1C\x04\x2C\x04\x02\x00\x00\x70\x07\x00\x00\x0A\x4A\x2C\x04\x02\
2075 \x0B\x00\x0A\x4A\x34\x04\x2C\x04\x02\x00\x00\x70\x07\x00\x00\x0A\
2076 \x4A\x40\x04\x02\x0C\x00\x0A\x4A\x54\x04\x2C\x04\x02\x00\x00\x70\
2077 \x07\x00\x00\x0A\x4A\x80\x04\x2C\x04\x02\x00\x00\x04\x08\x00\x00\
2078 \x0A\x4A\x88\x04\x2C\x04\x02\x00\x00\x04\x08\x00\x00\x0A\x4A\xA0\
2079 \x04\x2C\x04\x02\x00\x00\x04\x08\x00\x00\x0A\x4A\x00\x05\x02\x0D\
2080 \x00\x06\x02\x00\x0C\x0A\x00\x02\x00\x00\x00\x00\x00\x07\x73\x70\
2081 \x72\x69\x6E\x74\x66\x0E\x0C\x00\x06\x6D\x65\x6D\x63\x68\x72\x0E\
2082 \x0B\x00\x06\x73\x74\x72\x6C\x65\x6E\x0E\x0D\x00\x07\x6D\x65\x6D\
2083 \x6D\x6F\x76\x65\x00"
2084 .to_vec();
2085 let mut data = Cursor::new(&bytes);
2087 let obj = Module::read(&mut data).unwrap();
2088
2089 eprintln!("obj: {:?}", obj);
2090
2091 assert_eq!(obj.name(), "SPRINTF");
2092 assert_eq!(obj.created(), "15-05-96 16:09:38");
2095 assert_eq!(obj.metadata.offset, 29);
2096 assert_eq!(obj.metadata.size, 3621);
2097 assert_eq!(obj.metadata.exports.len(), 2);
2098
2099 let export = obj.metadata.exports.first().expect("obj[0].exports[0]");
2100 assert_eq!(export.name_size, 7);
2101 assert_eq!(export.name(), "sprintf");
2102
2103 let lnk = &obj.obj;
2104 assert_eq!(lnk.version, 2);
2105
2106 let Section::CPU(cpu) = lnk.sections.first().expect("obj[0].obj.sections[0]") else {
2107 panic!("expected a section");
2108 };
2109 assert_eq!(*cpu, cputype::MIPS_R300GTE);
2110 assert_eq!(data.position(), bytes.len() as u64);
2119
2120 let mut writer = Cursor::new(Vec::new());
2121 obj.write_le(&mut writer).unwrap();
2122 assert_eq!(writer.into_inner(), bytes);
2123 }
2124
2125 #[test]
2126 fn test_2_mbyte() {
2127 let bytes = b"\
2128 \x4C\x4E\x4B\x02\x2E\x07\x10\x08\x28\x00\x00\x08\x06\x2E\x72\x64\
2129 \x61\x74\x61\x10\x09\x28\x00\x00\x08\x05\x2E\x74\x65\x78\x74\x10\
2130 \x0A\x28\x00\x00\x08\x05\x2E\x64\x61\x74\x61\x10\x0B\x28\x00\x00\
2131 \x08\x06\x2E\x73\x64\x61\x74\x61\x10\x0C\x28\x00\x00\x08\x05\x2E\
2132 \x73\x62\x73\x73\x10\x0D\x28\x00\x00\x08\x04\x2E\x62\x73\x73\x06\
2133 \x08\x28\x06\x09\x28\x06\x0A\x28\x06\x0B\x28\x06\x0C\x28\x06\x0D\
2134 \x28\x06\x09\x28\x02\xC4\x00\x08\x00\xE0\x03\x00\x00\x00\x00\x00\
2135 \x00\x02\x3C\x00\x00\x42\x24\x00\x00\x03\x3C\x00\x00\x63\x24\x00\
2136 \x00\x40\xAC\x04\x00\x42\x24\x2B\x08\x43\x00\xFC\xFF\x20\x14\x00\
2137 \x00\x00\x00\x04\x00\x02\x24\x00\x00\x00\x00\x00\x00\x00\x00\x00\
2138 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x3C\x00\x00\x84\x24\x21\
2139 \x20\x82\x00\x00\x00\x82\x8C\x00\x80\x08\x3C\x25\xE8\x48\x00\x00\
2140 \x00\x04\x3C\x00\x00\x84\x24\xC0\x20\x04\x00\xC2\x20\x04\x00\x00\
2141 \x00\x03\x3C\x00\x00\x63\x8C\x00\x00\x00\x00\x23\x28\x43\x00\x23\
2142 \x28\xA4\x00\x25\x20\x88\x00\x00\x00\x01\x3C\x00\x00\x3F\xAC\x00\
2143 \x00\x1C\x3C\x00\x00\x9C\x27\x21\xF0\xA0\x03\x00\x00\x00\x0C\x04\
2144 \x00\x84\x20\x00\x00\x1F\x3C\x00\x00\xFF\x8F\x00\x00\x00\x00\x00\
2145 \x00\x00\x0C\x00\x00\x00\x00\x4D\x00\x00\x00\x00\x00\x20\x00\x00\
2146 \x00\x20\x00\x00\x00\x20\x00\x00\x00\x20\x00\x0A\x52\x08\x00\x0C\
2147 \x0C\x28\x0A\x54\x0C\x00\x0C\x0C\x28\x0A\x52\x10\x00\x16\x0D\x28\
2148 \x0A\x54\x14\x00\x16\x0D\x28\x0A\x52\x40\x00\x2C\x04\x09\x28\x00\
2149 \xB4\x00\x00\x00\x0A\x54\x44\x00\x2C\x04\x09\x28\x00\xB4\x00\x00\
2150 \x00\x0A\x52\x58\x00\x16\x0D\x28\x0A\x54\x5C\x00\x16\x0D\x28\x0A\
2151 \x52\x68\x00\x02\x17\x28\x0A\x54\x6C\x00\x02\x17\x28\x0A\x52\x80\
2152 \x00\x2C\x04\x0C\x28\x00\x00\x00\x00\x00\x0A\x54\x84\x00\x2C\x04\
2153 \x0C\x28\x00\x00\x00\x00\x00\x0A\x52\x88\x00\x0C\x0B\x28\x0A\x54\
2154 \x8C\x00\x0C\x0B\x28\x0A\x4A\x94\x00\x02\x14\x28\x0A\x52\x9C\x00\
2155 \x2C\x04\x0C\x28\x00\x00\x00\x00\x00\x0A\x54\xA0\x00\x2C\x04\x0C\
2156 \x28\x00\x00\x00\x00\x00\x0A\x4A\xA8\x00\x02\x16\x28\x06\x0C\x28\
2157 \x08\x04\x00\x00\x00\x0E\x14\x28\x08\x49\x6E\x69\x74\x48\x65\x61\
2158 \x70\x0E\x17\x28\x0A\x5F\x73\x74\x61\x63\x6B\x73\x69\x7A\x65\x0C\
2159 \x0F\x28\x09\x28\x08\x00\x00\x00\x10\x5F\x5F\x53\x4E\x5F\x45\x4E\
2160 \x54\x52\x59\x5F\x50\x4F\x49\x4E\x54\x0C\x0E\x28\x09\x28\x00\x00\
2161 \x00\x00\x06\x5F\x5F\x6D\x61\x69\x6E\x0E\x16\x28\x04\x6D\x61\x69\
2162 \x6E\x0C\x11\x28\x09\x28\xA8\x00\x00\x00\x05\x73\x74\x75\x70\x30\
2163 \x0C\x12\x28\x09\x28\x2C\x00\x00\x00\x05\x73\x74\x75\x70\x31\x0C\
2164 \x13\x28\x09\x28\x08\x00\x00\x00\x05\x73\x74\x75\x70\x32\x00";
2165 let mut data = Cursor::new(&bytes);
2166 let lnk = OBJ::read(&mut data).unwrap();
2167
2168 eprintln!("obj: {:?}", lnk);
2169 }
2170
2171 #[test]
2172 fn test_section() {
2173 let bytes = b"\x3A\x00\x00\x26\x00\x00\x00\x09\x00";
2174 let mut data = Cursor::new(&bytes);
2175 let _ = Section::read(&mut data).unwrap();
2176 }
2177
2178 #[test]
2179 fn test_expression() {
2180 let bytes = b"\x0A\x52\x08\x00\x0C\x0C\x28";
2188 let mut data = Cursor::new(&bytes);
2189 let _ = Section::read(&mut data).unwrap();
2190
2191 let bytes = b"\x0A\x52\x10\x00\x16\x0D\x28";
2192 let mut data = Cursor::new(&bytes);
2193 let _ = Section::read(&mut data).unwrap();
2194
2195 let bytes = b"\x0A\x52\x10\x00\x16\x0D\x28\x04\x04\x00\x00\x00\x00\x00\x00";
2196 let mut data = Cursor::new(&bytes);
2197 let _ = Section::read(&mut data).unwrap();
2198
2199 let bytes = b"\x0A\x52\xD0\x00\x32\x00\x04\x00\x00\x00\x2E\x0C\xFA\x62\x16\xFA\x62";
2200 let mut data = Cursor::new(&bytes);
2201 let _ = Section::read(&mut data).unwrap();
2202 }
2203
2204 #[test]
2205 fn test_function_start() {
2206 let bytes = b"\
2207 \x4A\x7C\x55\xB4\x05\x00\x00\xA7\x59\x00\x00\x00\x00\x1D\x00\x20\
2208 \x00\x00\x00\x1F\x00\x00\x00\x03\x80\xF8\xFF\xFF\xFF\x06\x63\x61\
2209 \x6C\x6C\x6F\x63\x4C"
2210 .to_vec();
2211
2212 let mut data = Cursor::new(&bytes);
2213 let _ = Section::read(&mut data).unwrap();
2214
2215 let bytes = b"\x0A\x52\x10\x00\x16\x0D\x28".to_vec();
2216 let mut data = Cursor::new(&bytes);
2217 let _ = Section::read(&mut data).unwrap();
2218 }
2219
2220 #[test]
2221 fn test_def2() {
2222 let bytes = b"\
2223 \x54\x00\x00\x04\x00\x00\x00\x66\x00\x00\x00\x04\x00\x00\x00\x00\
2224 \x00\x08\x5F\x70\x68\x79\x73\x61\x64\x72\x04\x2E\x65\x6F\x73";
2225
2226 let mut data = Cursor::new(&bytes);
2227 let section = Section::read(&mut data).unwrap();
2228
2229 let Section::Def2(def2) = section else {
2230 panic!("expected a def2");
2231 };
2232
2233 assert_eq!(def2.section, 0);
2234 assert_eq!(def2.value, 4);
2235 assert_eq!(def2.class, 102);
2236 assert_eq!(def2.def_type, 0);
2237 assert_eq!(def2.size, 4);
2238 assert_eq!(def2.tag(), "_physadr");
2240 assert_eq!(def2.name(), ".eos");
2241 }
2242
2243 #[test]
2244 fn test_libsn_sat() {
2245 let bytes =
2246b"\x68\x00\x2F\x86\x2F\x96\x2F\xA6\x2F\xB6\x2F\xC6\x2F\xD6\x2F\xE6\x4F\x22\x6E\xF3\x6D\x43\x6B\x53\x69\x63\x29\x98\x8D\x16\xEA\x00\xDC\x00\x39\xC6\x8F\x01\x68\x93\x68\xC3\x66\x83\x65\xB3\xD1\x00\x41\x0B\x64\xD3\x88\xFF\x8F\x02\x3A\x0C\xA0\x08\xE0\xFF\x3B\x0C\x30\x83\x8F\x03\x39\x08\x29\x98\x8F\xEC\x39\xC6\x60\xA3\x6F\xE3\x4F\x26\x6E\xF6\x6D\xF6\x6C\xF6\x6B\xF6\x6A\xF6\x69\xF6\x00\x0B\x68\xF6\x00\x00\x80\x00\x00\x00\x00\x00";
2247
2248 let mut data = Cursor::new(&bytes);
2249 let code = Code::read(&mut data).unwrap();
2250 assert_eq!(bytes.len(), 106);
2251 assert_eq!(code.size, 104);
2252 assert_eq!(code.code.len(), 104);
2253 assert_eq!(code.code, bytes[2..]);
2254
2255 let bytes = b"\x0A\x0A\x1F\x00\x4A\x00\x02\x00\x00\x00\x2E\x34\x00\xFC\xFF\xFF\xFF\x2C\x04\x01\x00\x00\x22\x00\x00\x00\x2C\x04\x01\x00\x00\x60\x00\x00\x00";
2256 let mut data = Cursor::new(&bytes);
2257 let section = Section::read(&mut data).unwrap();
2258 assert_eq!(section.to_string(), "10 : Patch type 10 at offset 1f with ($2-arshift_chk-(($fffffffc&(sectbase(1)+$22))-(sectbase(1)+$60)))");
2259
2260 println!("section: {section}");
2261
2262 let bytes = b"\x4C\x4E\x4B\x02\x2E\x08\x14\x0B\x33\x80\x03\x62\x73\x73\x10\x0C\x33\x0B\x33\x08\x06\x62\x73\x73\x65\x6E\x64\x06\x0C\x33\x0C\x0A\x33\x0C\x33\x00\x00\x00\x00\x03\x65\x6E\x64\x00";
2263 let mut data = Cursor::new(&bytes);
2264 let _ = OBJ::read(&mut data).unwrap();
2265 }
2266}