Compare commits
10 Commits
0b0889faee
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14fd8919b0 | ||
|
|
4440e56f85 | ||
|
|
ac3bdaca33 | ||
|
|
12c6d7122c | ||
|
|
6939ac9c8d | ||
|
|
166b047a70 | ||
|
|
510409c730 | ||
|
|
cd5f05daf5 | ||
|
|
4a7a5c0f93 | ||
|
|
430889ff09 |
@@ -3,6 +3,5 @@ name = "doom-oxidized"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
sdl2 = "0.35.2"
|
||||||
|
|||||||
112
src/doomlevel.rs
Normal file
112
src/doomlevel.rs
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
mod linedef;
|
||||||
|
mod vertex;
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
fs::File,
|
||||||
|
io::{Read, Seek, SeekFrom},
|
||||||
|
};
|
||||||
|
|
||||||
|
use self::linedef::Linedef;
|
||||||
|
|
||||||
|
use super::wadfile::WADFile;
|
||||||
|
use vertex::Vertex;
|
||||||
|
|
||||||
|
enum Lumps {
|
||||||
|
THINGS = 1,
|
||||||
|
LINEDEFS,
|
||||||
|
SIDEDEFS,
|
||||||
|
VERTEXES,
|
||||||
|
SEGS,
|
||||||
|
SSECTORS,
|
||||||
|
NODES,
|
||||||
|
SECTORS,
|
||||||
|
REJECT,
|
||||||
|
BLOCKMAP,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DoomLevel {
|
||||||
|
pub name: String,
|
||||||
|
pub vertexes: Vec<Vertex>,
|
||||||
|
pub linedefs: Vec<Linedef>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DoomLevel {
|
||||||
|
pub fn load_level(wad_file: &WADFile, lvl_index: u32) -> Self {
|
||||||
|
Self {
|
||||||
|
name: wad_file.get_lump_name(lvl_index),
|
||||||
|
vertexes: load_vertexes(
|
||||||
|
wad_file,
|
||||||
|
wad_file.get_lump_offset(lvl_index + Lumps::VERTEXES as u32),
|
||||||
|
wad_file.get_lump_size(lvl_index + Lumps::VERTEXES as u32),
|
||||||
|
),
|
||||||
|
linedefs: load_linedefs(
|
||||||
|
wad_file,
|
||||||
|
wad_file.get_lump_offset(lvl_index + Lumps::LINEDEFS as u32),
|
||||||
|
wad_file.get_lump_size(lvl_index + Lumps::LINEDEFS as u32),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_vertexes(wad_file: &WADFile, offset: u32, size: u32) -> Vec<Vertex> {
|
||||||
|
let num_vertex: u32 = size / 4u32;
|
||||||
|
|
||||||
|
let mut vertex_list: Vec<Vertex> = Vec::with_capacity(num_vertex as usize);
|
||||||
|
|
||||||
|
let mut vertex_data = File::open(&wad_file.wad_path).unwrap();
|
||||||
|
vertex_data.seek(SeekFrom::Start(offset as u64)).unwrap();
|
||||||
|
|
||||||
|
for _ in 0..num_vertex {
|
||||||
|
let mut x = [0; 2];
|
||||||
|
let mut y = [0; 2];
|
||||||
|
|
||||||
|
vertex_data.read(&mut x).unwrap();
|
||||||
|
vertex_data.read(&mut y).unwrap();
|
||||||
|
|
||||||
|
vertex_list.push(Vertex {
|
||||||
|
x: i16::from_le_bytes(x),
|
||||||
|
y: i16::from_le_bytes(y),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
vertex_list
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_linedefs(wad_file: &WADFile, offset: u32, size: u32) -> Vec<Linedef> {
|
||||||
|
let num_linedef: u32 = size / 14u32;
|
||||||
|
|
||||||
|
let mut linedef_list: Vec<Linedef> = Vec::with_capacity(num_linedef as usize);
|
||||||
|
|
||||||
|
let mut linedef_data = File::open(&wad_file.wad_path).unwrap();
|
||||||
|
linedef_data.seek(SeekFrom::Start(offset as u64)).unwrap();
|
||||||
|
|
||||||
|
for _ in 0..num_linedef {
|
||||||
|
let mut start_vertex = [0; 2];
|
||||||
|
let mut end_vertex = [0; 2];
|
||||||
|
let mut flags = [0; 2];
|
||||||
|
let mut special_type = [0; 2];
|
||||||
|
let mut sector_tag = [0; 2];
|
||||||
|
let mut front_sidedef = [0; 2];
|
||||||
|
let mut back_sidedef = [0; 2];
|
||||||
|
|
||||||
|
linedef_data.read(&mut start_vertex).unwrap();
|
||||||
|
linedef_data.read(&mut end_vertex).unwrap();
|
||||||
|
linedef_data.read(&mut flags).unwrap();
|
||||||
|
linedef_data.read(&mut special_type).unwrap();
|
||||||
|
linedef_data.read(&mut sector_tag).unwrap();
|
||||||
|
linedef_data.read(&mut front_sidedef).unwrap();
|
||||||
|
linedef_data.read(&mut back_sidedef).unwrap();
|
||||||
|
|
||||||
|
linedef_list.push(Linedef {
|
||||||
|
start_vertex: i16::from_le_bytes(start_vertex),
|
||||||
|
end_vertex: i16::from_le_bytes(end_vertex),
|
||||||
|
flags: i16::from_le_bytes(flags),
|
||||||
|
special_type: i16::from_le_bytes(special_type),
|
||||||
|
sector_tag: i16::from_le_bytes(sector_tag),
|
||||||
|
front_sidedef: i16::from_le_bytes(front_sidedef),
|
||||||
|
back_sidedef: i16::from_le_bytes(back_sidedef),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
linedef_list
|
||||||
|
}
|
||||||
47
src/doomlevel/linedef.rs
Normal file
47
src/doomlevel/linedef.rs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
pub struct Linedef {
|
||||||
|
pub start_vertex: i16,
|
||||||
|
pub end_vertex: i16,
|
||||||
|
pub flags: i16,
|
||||||
|
pub special_type: i16,
|
||||||
|
pub sector_tag: i16,
|
||||||
|
pub front_sidedef: i16,
|
||||||
|
pub back_sidedef: i16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Linedef {
|
||||||
|
pub fn blocks_players(&self) -> bool {
|
||||||
|
self.flags & (1 << 0) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn blocks_monsters(&self) -> bool {
|
||||||
|
self.flags & (1 << 1) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_two_sided(&self) -> bool {
|
||||||
|
self.flags & (1 << 2) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_upper_unpegged(&self) -> bool {
|
||||||
|
self.flags & (1 << 3) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_lower_unpegged(&self) -> bool {
|
||||||
|
self.flags & (1 << 4) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_secret(&self) -> bool {
|
||||||
|
self.flags & (1 << 5) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn blocks_sound(&self) -> bool {
|
||||||
|
self.flags & (1 << 6) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn never_automap(&self) -> bool {
|
||||||
|
self.flags & (1 << 7) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn always_automap(&self) -> bool {
|
||||||
|
self.flags & (1 << 8) != 0
|
||||||
|
}
|
||||||
|
}
|
||||||
4
src/doomlevel/vertex.rs
Normal file
4
src/doomlevel/vertex.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
pub struct Vertex {
|
||||||
|
pub x: i16,
|
||||||
|
pub y: i16,
|
||||||
|
}
|
||||||
121
src/main.rs
121
src/main.rs
@@ -1,9 +1,32 @@
|
|||||||
|
extern crate sdl2;
|
||||||
|
|
||||||
|
use sdl2::event::Event;
|
||||||
|
use sdl2::keyboard::Keycode;
|
||||||
|
use sdl2::pixels::Color;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
mod doomlevel;
|
||||||
mod wadfile;
|
mod wadfile;
|
||||||
|
|
||||||
|
use doomlevel::DoomLevel;
|
||||||
use wadfile::WADFile;
|
use wadfile::WADFile;
|
||||||
|
|
||||||
fn main() {
|
static WIDTH: u32 = 320;
|
||||||
let wad_file = WADFile::from_path("WADs/doom1.wad");
|
static HEIGHT: u32 = 200;
|
||||||
|
static SCALING: u32 = 4;
|
||||||
|
|
||||||
|
fn find_sdl_gl_driver() -> Option<u32> {
|
||||||
|
for (index, item) in sdl2::render::drivers().enumerate() {
|
||||||
|
if item.name == "opengl" {
|
||||||
|
return Some(index as u32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<(), &'static str> {
|
||||||
|
let wad_file = WADFile::from_path("WADs/doom1.wad")?;
|
||||||
|
let level = DoomLevel::load_level(&wad_file, wad_file.get_index_from_name("e1m1").unwrap());
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"WAD Path: {}
|
"WAD Path: {}
|
||||||
@@ -32,8 +55,98 @@ Header:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println!("\nFirst 15 Vertex Entries for {}:", level.name);
|
||||||
|
|
||||||
|
for i in 0..15 {
|
||||||
println!(
|
println!(
|
||||||
"Index of e1m1 is: {}",
|
"\t{} - ({}, {})",
|
||||||
wad_file.get_index_from_name("e1m1").unwrap()
|
i, level.vertexes[i].x, level.vertexes[i].y
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let test_linedef = 247;
|
||||||
|
|
||||||
|
println!("\nLinedef Entry {} for {}:", test_linedef, level.name);
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Start Vertex: {}
|
||||||
|
End Vertex: {}
|
||||||
|
Flags: {}
|
||||||
|
Special Type: {}
|
||||||
|
Sector Tag: {}
|
||||||
|
Front Sidedef: {}
|
||||||
|
Back Sidedef: {}
|
||||||
|
|
||||||
|
Flags:
|
||||||
|
\tBlocks Players: {}
|
||||||
|
\tBlocks Monsters: {}
|
||||||
|
\tTwo Sided: {}
|
||||||
|
\tUpper Texture Unpegged: {}
|
||||||
|
\tLower Texture Unpegged: {}
|
||||||
|
\tSecret: {}
|
||||||
|
\tBlocks Sound: {}
|
||||||
|
\tNever Shows on Automap: {}
|
||||||
|
\tAlways Shows on Automap: {}",
|
||||||
|
level.linedefs[test_linedef].start_vertex,
|
||||||
|
level.linedefs[test_linedef].end_vertex,
|
||||||
|
level.linedefs[test_linedef].flags,
|
||||||
|
level.linedefs[test_linedef].special_type,
|
||||||
|
level.linedefs[test_linedef].sector_tag,
|
||||||
|
level.linedefs[test_linedef].front_sidedef,
|
||||||
|
level.linedefs[test_linedef].back_sidedef,
|
||||||
|
level.linedefs[test_linedef].blocks_players(),
|
||||||
|
level.linedefs[test_linedef].blocks_monsters(),
|
||||||
|
level.linedefs[test_linedef].is_two_sided(),
|
||||||
|
level.linedefs[test_linedef].is_upper_unpegged(),
|
||||||
|
level.linedefs[test_linedef].is_lower_unpegged(),
|
||||||
|
level.linedefs[test_linedef].is_secret(),
|
||||||
|
level.linedefs[test_linedef].blocks_sound(),
|
||||||
|
level.linedefs[test_linedef].never_automap(),
|
||||||
|
level.linedefs[test_linedef].always_automap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let sdl_context = sdl2::init().unwrap();
|
||||||
|
let video_subsystem = sdl_context.video().unwrap();
|
||||||
|
|
||||||
|
let window = video_subsystem
|
||||||
|
.window("Doom - Oxidized", WIDTH * SCALING, HEIGHT * SCALING)
|
||||||
|
.position_centered()
|
||||||
|
.opengl()
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut canvas = window
|
||||||
|
.into_canvas()
|
||||||
|
.index(find_sdl_gl_driver().unwrap())
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
canvas.set_draw_color(Color::RGB(0, 255, 255));
|
||||||
|
canvas.clear();
|
||||||
|
canvas.present();
|
||||||
|
|
||||||
|
let mut event_pump = sdl_context.event_pump().unwrap();
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
'running: loop {
|
||||||
|
i = (i + 1) % 255;
|
||||||
|
canvas.set_draw_color(Color::RGB(i, 64, 255 - i));
|
||||||
|
canvas.clear();
|
||||||
|
|
||||||
|
for event in event_pump.poll_iter() {
|
||||||
|
match event {
|
||||||
|
Event::Quit { .. }
|
||||||
|
| Event::KeyDown {
|
||||||
|
keycode: Some(Keycode::Escape),
|
||||||
|
..
|
||||||
|
} => break 'running,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.present();
|
||||||
|
::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 30));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,31 +4,38 @@ use directory::Directory;
|
|||||||
use std::{
|
use std::{
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{Read, Seek, SeekFrom},
|
io::{Read, Seek, SeekFrom},
|
||||||
|
path::Path,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct WADFile {
|
pub struct WADFile {
|
||||||
pub(super) wad_path: String,
|
pub wad_path: String,
|
||||||
pub(super) identifier: String,
|
pub identifier: String,
|
||||||
pub(super) num_lumps: u32,
|
pub num_lumps: u32,
|
||||||
pub(super) init_offset: u32,
|
pub init_offset: u32,
|
||||||
pub(super) lump_directory: Vec<Directory>,
|
lump_directory: Vec<Directory>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WADFile {
|
impl WADFile {
|
||||||
pub fn from_path(path: &str) -> Self {
|
pub fn from_path(path: &str) -> Result<Self, &str> {
|
||||||
|
let wad_file = Path::new(path);
|
||||||
|
|
||||||
|
if !(wad_file.exists()) {
|
||||||
|
return Err("Could not open file!");
|
||||||
|
}
|
||||||
|
|
||||||
let header_data = get_header_data(path);
|
let header_data = get_header_data(path);
|
||||||
|
|
||||||
let mut lump_dir: Vec<Directory> = Vec::with_capacity(header_data.1 as usize);
|
let mut lump_dir: Vec<Directory> = Vec::with_capacity(header_data.1 as usize);
|
||||||
|
|
||||||
get_lump_dir(path, &header_data.2, &header_data.1, &mut lump_dir);
|
get_lump_dir(path, &header_data.2, &header_data.1, &mut lump_dir);
|
||||||
|
|
||||||
Self {
|
Ok(Self {
|
||||||
wad_path: path.to_string(),
|
wad_path: path.to_string(),
|
||||||
identifier: header_data.0,
|
identifier: header_data.0,
|
||||||
num_lumps: header_data.1,
|
num_lumps: header_data.1,
|
||||||
init_offset: header_data.2,
|
init_offset: header_data.2,
|
||||||
lump_directory: lump_dir,
|
lump_directory: lump_dir,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_lump_name(&self, index: u32) -> String {
|
pub fn get_lump_name(&self, index: u32) -> String {
|
||||||
@@ -74,20 +81,15 @@ fn get_lump_dir(path: &str, dir_offset: &u32, num_lumps: &u32, lump_buffer: &mut
|
|||||||
let mut lump_pos = [0; 4];
|
let mut lump_pos = [0; 4];
|
||||||
let mut lump_size = [0; 4];
|
let mut lump_size = [0; 4];
|
||||||
let mut lump_name = [0; 8];
|
let mut lump_name = [0; 8];
|
||||||
let mut name = String::with_capacity(8);
|
|
||||||
|
|
||||||
wad_data.read(&mut lump_pos).unwrap();
|
wad_data.read(&mut lump_pos).unwrap();
|
||||||
wad_data.read(&mut lump_size).unwrap();
|
wad_data.read(&mut lump_size).unwrap();
|
||||||
wad_data.read(&mut lump_name).unwrap();
|
wad_data.read(&mut lump_name).unwrap();
|
||||||
|
|
||||||
for letter in 0..lump_name.len() {
|
|
||||||
name.push(lump_name[letter] as char);
|
|
||||||
}
|
|
||||||
|
|
||||||
lump_buffer.push(Directory {
|
lump_buffer.push(Directory {
|
||||||
lump_pos: u32::from_le_bytes(lump_pos),
|
lump_pos: u32::from_le_bytes(lump_pos),
|
||||||
lump_size: u32::from_le_bytes(lump_size),
|
lump_size: u32::from_le_bytes(lump_size),
|
||||||
lump_name: name,
|
lump_name: String::from_utf8(lump_name.to_vec()).unwrap(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,23 +97,17 @@ fn get_lump_dir(path: &str, dir_offset: &u32, num_lumps: &u32, lump_buffer: &mut
|
|||||||
fn get_header_data(path: &str) -> (String, u32, u32) {
|
fn get_header_data(path: &str) -> (String, u32, u32) {
|
||||||
let mut wad_data = File::open(&path).unwrap();
|
let mut wad_data = File::open(&path).unwrap();
|
||||||
|
|
||||||
let mut header = [0; 12];
|
let mut wad_id = [0; 4];
|
||||||
|
let mut dir_size = [0; 4];
|
||||||
|
let mut dir_offset = [0; 4];
|
||||||
|
|
||||||
wad_data.read(&mut header).unwrap();
|
wad_data.read(&mut wad_id).unwrap();
|
||||||
|
wad_data.read(&mut dir_size).unwrap();
|
||||||
let mut wad_type = String::with_capacity(4);
|
wad_data.read(&mut dir_offset).unwrap();
|
||||||
|
|
||||||
wad_type.push(header[0] as char);
|
|
||||||
wad_type.push(header[1] as char);
|
|
||||||
wad_type.push(header[2] as char);
|
|
||||||
wad_type.push(header[3] as char);
|
|
||||||
|
|
||||||
let lump_bytes: [u8; 4] = [header[4], header[5], header[6], header[7]];
|
|
||||||
let offset_bytes: [u8; 4] = [header[8], header[9], header[10], header[11]];
|
|
||||||
|
|
||||||
(
|
(
|
||||||
wad_type,
|
String::from_utf8(wad_id.to_vec()).unwrap(),
|
||||||
u32::from_le_bytes(lump_bytes),
|
u32::from_le_bytes(dir_size),
|
||||||
u32::from_le_bytes(offset_bytes),
|
u32::from_le_bytes(dir_offset),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user