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"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[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;
|
||||
|
||||
use doomlevel::DoomLevel;
|
||||
use wadfile::WADFile;
|
||||
|
||||
fn main() {
|
||||
let wad_file = WADFile::from_path("WADs/doom1.wad");
|
||||
static WIDTH: u32 = 320;
|
||||
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!(
|
||||
"WAD Path: {}
|
||||
@@ -32,8 +55,98 @@ Header:
|
||||
);
|
||||
}
|
||||
|
||||
println!("\nFirst 15 Vertex Entries for {}:", level.name);
|
||||
|
||||
for i in 0..15 {
|
||||
println!(
|
||||
"Index of e1m1 is: {}",
|
||||
wad_file.get_index_from_name("e1m1").unwrap()
|
||||
"\t{} - ({}, {})",
|
||||
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::{
|
||||
fs::File,
|
||||
io::{Read, Seek, SeekFrom},
|
||||
path::Path,
|
||||
};
|
||||
|
||||
pub struct WADFile {
|
||||
pub(super) wad_path: String,
|
||||
pub(super) identifier: String,
|
||||
pub(super) num_lumps: u32,
|
||||
pub(super) init_offset: u32,
|
||||
pub(super) lump_directory: Vec<Directory>,
|
||||
pub wad_path: String,
|
||||
pub identifier: String,
|
||||
pub num_lumps: u32,
|
||||
pub init_offset: u32,
|
||||
lump_directory: Vec<Directory>,
|
||||
}
|
||||
|
||||
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 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);
|
||||
|
||||
Self {
|
||||
Ok(Self {
|
||||
wad_path: path.to_string(),
|
||||
identifier: header_data.0,
|
||||
num_lumps: header_data.1,
|
||||
init_offset: header_data.2,
|
||||
lump_directory: lump_dir,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
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_size = [0; 4];
|
||||
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_size).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_pos: u32::from_le_bytes(lump_pos),
|
||||
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) {
|
||||
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();
|
||||
|
||||
let mut wad_type = String::with_capacity(4);
|
||||
|
||||
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_data.read(&mut wad_id).unwrap();
|
||||
wad_data.read(&mut dir_size).unwrap();
|
||||
wad_data.read(&mut dir_offset).unwrap();
|
||||
|
||||
(
|
||||
wad_type,
|
||||
u32::from_le_bytes(lump_bytes),
|
||||
u32::from_le_bytes(offset_bytes),
|
||||
String::from_utf8(wad_id.to_vec()).unwrap(),
|
||||
u32::from_le_bytes(dir_size),
|
||||
u32::from_le_bytes(dir_offset),
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user