From 120ee6741bbcb128e9d36b46925f673c1d655768 Mon Sep 17 00:00:00 2001 From: Jared Roberts Date: Thu, 10 Mar 2016 13:11:18 -0800 Subject: [PATCH] load CON files --- src/arena.rs | 47 +++++++++++++++++++++++++++ src/main.rs | 25 +++++++++------ src/tile.rs | 67 +++++++++++++++++++++++++++++++++++++++ src/town.rs | 41 ++++++++++++++++++++++++ src/world.rs | 89 ++++++++++------------------------------------------ 5 files changed, 187 insertions(+), 82 deletions(-) create mode 100644 src/arena.rs create mode 100644 src/tile.rs create mode 100644 src/town.rs diff --git a/src/arena.rs b/src/arena.rs new file mode 100644 index 0000000..a17bbf4 --- /dev/null +++ b/src/arena.rs @@ -0,0 +1,47 @@ +use world; +use tile::Tile; + +#[derive(Clone, Copy)] +// offset len notes +// 0x0 16 start_x for monsters 0-15 +// 0x10 16 start_y for monsters 0-15 +// 0x20 8 start_x for party members 0-7 +// 0x28 8 start_y for party members 0-7 +// 0x30 16 ??? +// 0x40 121 11x11 map matrix +// 0xB9 7 ??? +pub struct Arena { + monster_x: [u8; 16], + monster_y: [u8; 16], + party_x: [u8; 8], + party_y: [u8; 8], + _unknown1: [u8; 16], + map: Field, + _unknown2: [u8; 7], +} + +#[derive(Clone, Copy)] +pub struct Shrine { + map: Field, + _unknown1: [[u8; 8]; 8], // Arbitrary grouping for Clone impl + _unknown2: [u8; 7], +} + +type Field = [[Tile; 11]; 11]; +impl world::Map for Field { + fn rows<'a>(&'a self) -> world::BoxedMapIterator { + Box::new(self.iter().map(|row| Box::new(row.into_iter()) as world::RowIterator<'a>)) + } +} + +impl world::HasMap for Arena { + fn map(&self) -> &world::Map { + &self.map + } +} + +impl world::HasMap for Shrine { + fn map(&self) -> &world::Map { + &self.map + } +} diff --git a/src/main.rs b/src/main.rs index ddd0953..a5ea8c2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,39 +7,44 @@ use std::env; use itertools::Itertools; use memmap::{Mmap, Protection}; -mod world; +mod arena; +mod tile; +mod town; mod transpose; +mod world; -use world::Map; - -fn mmap_to_rows<'a, M: world::Map>(mmap: &memmap::Mmap) -> &'a world::Map +fn mmap_to_rows<'a, M: world::HasMap>(mmap: &memmap::Mmap) -> &'a world::HasMap where M: Copy + 'a { - assert!(std::mem::size_of::() <= mmap.len()); + assert_eq!(std::mem::size_of::(), mmap.len()); unsafe { transmute::<*const u8, &M>(mmap.ptr()) } } fn main() { let args: Vec = env::args().collect(); let filename; - let conv; if args.len() > 1 { filename = &args[1] as &str; - conv = mmap_to_rows::; } else { filename = "data/WORLD.MAP"; - conv = mmap_to_rows::; } + let conv = match filename { + s if s.ends_with("SHRINE.CON") => mmap_to_rows::, + s if s.ends_with(".CON") => mmap_to_rows::, + s if s.ends_with(".ULT") => mmap_to_rows::, + s if s.ends_with("WORLD.MAP") => mmap_to_rows::, + _ => panic!("unrecognized map file"), + }; let file_mmap = Mmap::open_path(filename, Protection::Read).unwrap(); let world = conv(&file_mmap); - print_rows(world.rows()); + print_rows(world.map().rows()); } fn print_rows<'a, T: ?Sized, U: ?Sized>(rows: Box) where T: Iterator> + 'a, - U: Iterator + 'a + U: Iterator + 'a { for row in rows { let s1: String = row.into_iter().map(|tile| tile.as_char()).collect(); diff --git a/src/tile.rs b/src/tile.rs new file mode 100644 index 0000000..f7f655c --- /dev/null +++ b/src/tile.rs @@ -0,0 +1,67 @@ +#[derive(Clone, Copy)] +pub struct Tile { + val: u8, +} + +impl Tile { + pub fn as_char(&self) -> char { + match self.val { + 0 => '~', // deep water '๐ŸŒŠ' + 1 => 'โ‰ˆ', // medium water + 2 => 'โ‰‹', // shallow water + 3 => ',', // swamp + 4 => 'โขŠ', // plain 'โ–‘' + 5 => '๐ŸŒฟ', // scrub 'แƒฌ' + 6 => '๐ŸŒณ', // forest + 7 => 'โŒ“', // hill 'โˆฉ' + 8 => 'โจ‡', // mountain 'โ–ณ' + 9 => 'โ˜—', // dungeon + 10 => 'โŸ', // city + 11 | 13...15 => 'โ›ซ', // castle + 12 => 'โ–', // village + 22 => 'โŽ”', // tile floor + 23 => 'โŸ—', // bridge + 24 => 'โงฌ', // balloon + 25 => 'โ‰ƒ', // bridge top + 26 => 'โ‰‚', // bridge bottom + 27 => 'โ', // ladder up + 28 => 'โ—', // ladder down + 29 => 'v', // ruin + 30 => 'โ—Œ', // shrine + 31 => '๐Ÿ˜‡', // avatar + 48 => 'โ—ฏ', // column + 49 => 'โ—ฃ', // SW + 50 => 'โ—ข', // SE + 51 => 'โ—ค', // NW + 52 => 'โ—ฅ', // NE + 53 => 'โ—‰', // Mast + 54 => 'โŽˆ', // ship's wheel + 55 => 'แƒค', // rocks 'โ' + 56 => '/', // Lyin down + 57 => 'โฌ›', // stone wall + 58 => 'โงฏ', // '๐Ÿ”’', // locked door + 59 => 'โงฎ', // '๐Ÿ”“', // unlocked door + 60 => '๐Ÿ’ฐ', // chest + 61 => 'โ˜ฅ', // ankh + 62 => 'โจณ', // brick floor 'โŒ—' + 63 => 'โ–ค', // wood planks 'โงป' + 68 => '๐ŸŒซ', // poison field + 69 => 'โšก', // energy field + 70 => '๐Ÿ”ฅ', // fire field + 71 => '๐Ÿ’ค', // sleep field + 72 => 'โ–ฃ', // solid barrier + 73 => 'โ–’', // hidden passage + 75 => '๐Ÿ–', // spit (rotisserie) '๐Ÿณ' + 76 => 'โŒ˜', // lava + 96...121 => ::std::char::from_u32((self.val - 31) as u32).unwrap(), + 122 => '=', // space + 123 => 'โА', // right '' + 124 => 'โŠ', // left 'โŠจ' + 125 => 'โ–ข', // window + 126 => 'โœจ', // space + 127 => 'โ–“', // brick wall + 189 => 'โš”', // phantom 2 + _ => panic!("{0}", self.val) + } + } +} diff --git a/src/town.rs b/src/town.rs new file mode 100644 index 0000000..b42b104 --- /dev/null +++ b/src/town.rs @@ -0,0 +1,41 @@ +use world::Chunk; +use world::HasMap; +use world::Map; +use tile::Tile; + +#[allow(dead_code)] +#[derive(Clone, Copy, Debug)] +enum Behavior { + FIXED = 0x00, + WANDER = 0x01, + FOLLOW = 0x80, + ATTACK = 0xFF, +} + +#[derive(Clone, Copy)] +pub struct Town { + map: Chunk, + npc_tile1: [Tile; 32], + npc_x1: [u8; 32], + npc_y1: [u8; 32], + npc_tile2: [Tile; 32], + npc_x2: [u8; 32], + npc_y2: [u8; 32], + npc_behavior: [Behavior; 32], + npc_talk_idx: [u8; 32], +} + +impl HasMap for Town { + fn map(&self) -> &Map { + &self.map + } +} + +// 0x400 32 tile for NPCs 0-31 +// 0x420 32 start_x for NPCs 0-31 +// 0x440 32 start_y for NPCs 0-31 +// 0x460 32 repitition of 0x400-0x41F +// 0x480 32 repitition of 0x420-0x43F +// 0x4A0 32 repitition of 0x440-0x45F +// 0x4C0 32 movement_behavior for NPCs 0-31 (0x0-fixed, 0x1-wander, 0x80-follow, 0xFF-attack) +// 0x4E0 32 conversion index (tlk file) for NPCs 0-31 diff --git a/src/world.rs b/src/world.rs index 29f77f4..a1a9324 100644 --- a/src/world.rs +++ b/src/world.rs @@ -3,85 +3,24 @@ extern crate itertools; use self::itertools::Itertools; +use tile::Tile; use transpose::TransposableIterator; -#[derive(Clone, Copy)] -pub struct Tile { - val: u8, -} - -impl Tile { - pub fn as_char(&self) -> char { - match self.val { - 0 => '~', // deep water '๐ŸŒŠ' - 1 => 'โ‰ˆ', // medium water - 2 => 'โ‰‹', // shallow water - 3 => ',', // swamp - 4 => 'โขŠ', // plain 'โ–‘' - 5 => '๐ŸŒฟ', // scrub 'แƒฌ' - 6 => '๐ŸŒณ', // forest - 7 => 'โŒ“', // hill 'โˆฉ' - 8 => 'โจ‡', // mountain 'โ–ณ' - 9 => 'โ˜—', // dungeon - 10 => 'โŸ', // city - 11 | 13...15 => 'โ›ซ', // castle - 12 => 'โ–', // village - 22 => 'โŽ”', // tile floor - 23 => 'โŸ—', // bridge - 24 => 'โงฌ', // balloon - 25 => 'โ‰ƒ', // bridge top - 26 => 'โ‰‚', // bridge bottom - 27 => 'โ', // ladder up - 28 => 'โ—', // ladder down - 29 => 'v', // ruin - 30 => 'โ—Œ', // shrine - 48 => 'โ—ฏ', // column - 49 => 'โ—ฃ', // SW - 50 => 'โ—ข', // SE - 51 => 'โ—ค', // NW - 52 => 'โ—ฅ', // NE - 54 => 'โŽˆ', // ship's wheel - 55 => 'แƒค', // rocks 'โ' - 56 => '/', // Lyin down - 57 => 'โฌ›', // stone wall - 58 => 'โงฏ', // '๐Ÿ”’', // locked door - 59 => 'โงฎ', // '๐Ÿ”“', // unlocked door - 60 => '๐Ÿ’ฐ', // chest - 61 => 'โ˜ฅ', // ankh - 62 => 'โจณ', // brick floor 'โŒ—' - 63 => 'โ–ค', // wood planks 'โงป' - 68 => '๐ŸŒซ', // poison field - 69 => 'โšก', // energy field - 70 => '๐Ÿ”ฅ', // fire field - 71 => '๐Ÿ’ค', // sleep field - 72 => 'โ–ฃ', // solid barrier - 73 => 'โ–’', // hidden passage - 75 => '๐Ÿ–', // spit (rotisserie) '๐Ÿณ' - 76 => 'โŒ˜', // lava - 96...121 => ::std::char::from_u32((self.val - 31) as u32).unwrap(), - 122 => '=', // space - 123 => 'โА', // right '' - 124 => 'โŠ', // left 'โŠจ' - 125 => 'โ–ข', // window - 126 => 'โœจ', // space - 127 => 'โ–“', // brick wall - 189 => 'โš”', // phantom 2 - _ => '?', // panic!("{0}", self.val) - } - } -} +pub type RowIterator<'a> = Box + 'a>; +pub type BoxedMapIterator<'a> = Box> + 'a>; +pub type ExactBoxedMapIterator<'a> = Box> + 'a>; pub trait Map { fn rows<'a>(&'a self) -> BoxedMapIterator; } -pub type BoxedMapIterator<'a> = Box> + 'a>; -pub type ExactBoxedMapIterator<'a> = Box> + 'a>; +pub trait HasMap { + fn map(&self) -> ⤅ +} const CHUNKDIM: usize = 32; pub type ChunkRow = [Tile; CHUNKDIM]; pub type ChunkRect = [ChunkRow; CHUNKDIM]; -pub type ChunkRowIterator<'a> = Box + 'a>; #[derive(Clone, Copy)] pub struct Chunk { pub rect: ChunkRect, @@ -91,7 +30,7 @@ impl Chunk { fn rows_exact<'a>(&'a self) -> ExactBoxedMapIterator { Box::new(self.rect .iter() - .map(|row| Box::new(row.into_iter()) as ChunkRowIterator<'a>)) + .map(|row| Box::new(row.into_iter()) as RowIterator<'a>)) } } @@ -99,12 +38,12 @@ impl Map for Chunk { fn rows<'a>(&'a self) -> BoxedMapIterator { Box::new(self.rect .iter() - .map(|row| Box::new(row.into_iter()) as ChunkRowIterator<'a>)) + .map(|row| Box::new(row.into_iter()) as RowIterator<'a>)) } } impl<'a> IntoIterator for &'a Chunk { - type Item=ChunkRowIterator<'a>; + type Item=RowIterator<'a>; type IntoIter=ExactBoxedMapIterator<'a>; fn into_iter(self) -> Self::IntoIter { self.rows_exact() @@ -123,6 +62,12 @@ impl Map for World { fn rows<'a>(&'a self) -> BoxedMapIterator { let flipped = self.rect.iter().map(|cr| cr.into_iter().transpose()); Box::new(flipped.flatten() - .map(|r| Box::new(r.flatten()) as ChunkRowIterator<'a>)) + .map(|r| Box::new(r.flatten()) as RowIterator<'a>)) + } +} + +impl HasMap for World { + fn map(&self) -> &Map { + self } }