RD-2: Implemented W_Init. This adds W_InitMultipleFiles and W_CheckNumForName

This commit was merged in pull request #2.
This commit is contained in:
Jim
2026-05-22 21:24:32 +01:00
parent f0b04bbcc2
commit fd9bbaee2d
7 changed files with 253 additions and 14 deletions

1
.gitignore vendored
View File

@@ -19,3 +19,4 @@
/target /target
/WADS/* /WADS/*
!/WADS/DOOM1.wad

2
.vscode/launch.json vendored
View File

@@ -16,7 +16,7 @@
} }
}, },
"args": [ "args": [
"./WADS/DOOM.WAD", "-dev", "@configs.txt", "-nomonsters", "-file", "test.WAD", "test2.WAD", "-skill", "3" "./WADS/DOOM.WAD", "-dev", "-nomonsters", "-skill", "3"
], ],
"cwd": "${workspaceFolder}" "cwd": "${workspaceFolder}"
}, },

BIN
WADS/doom1.wad Normal file

Binary file not shown.

View File

@@ -9,6 +9,8 @@ use crate::m_argv::M_CheckParm;
use crate::m_argv::M_GetOptionalArgumentValueByArgument; use crate::m_argv::M_GetOptionalArgumentValueByArgument;
use crate::m_argv::PARM_NOT_FOUND; use crate::m_argv::PARM_NOT_FOUND;
use crate::w_wad::{W_CheckNumForName, W_InitMultipleFiles};
use crate::doomdef::{ use crate::doomdef::{
VERSION, VERSION,
// D_DEVSTR, // D_DEVSTR,
@@ -407,10 +409,10 @@ pub fn D_DoomMain() {
println!("Z_init: Init zone memory allocation daemon."); println!("Z_init: Init zone memory allocation daemon.");
Z_Init(); Z_Init();
println!("W_Init: Init WADfiles");
W_InitMultipleFiles(wadfiles);
*/ */
println!("W_Init: Init WADfiles");
W_InitMultipleFiles(DOOMGLOBALS::with_ref(|g| g.wadfiles.clone())); // we are loading so how cares about a borrow
let is_modified = DOOMGLOBALS::with_ref(|g| g.modifiedgame); let is_modified = DOOMGLOBALS::with_ref(|g| g.modifiedgame);
@@ -426,12 +428,13 @@ pub fn D_DoomMain() {
} }
if g_mode == GameMode::Registered { if g_mode == GameMode::Registered {
for lump in iwads_lumps_to_check.iter().take(24) { let missing_registered_lump = iwads_lumps_to_check
// TODO: Implement check .iter()
// for (i = 0;i < 23; i++) .any(|lump_name| W_CheckNumForName(lump_name) == -1);
// if (W_CheckNumForName(name[i])<0) if missing_registered_lump {
// I_Error("\nThis is not the registered version."); // TODO: Implement I_Error
} // I_Error("\nThis is not the registered version.");
}
} }
} }
@@ -541,7 +544,7 @@ pub fn D_DoomMain() {
} }
let g_action = DOOMGLOBALS::with_ref(|g| g.gameaction); // let g_action = DOOMGLOBALS::with_ref(|g| g.gameaction);
// TODO: Impement Game actions // TODO: Impement Game actions
// if g_action != ga_loadgame { // if g_action != ga_loadgame {

View File

@@ -1,10 +1,9 @@
use std::cell::RefCell; use std::cell::RefCell;
use std::sync::{Mutex, MutexGuard, OnceLock};
pub const VERSION:i32 = 110; pub const VERSION:i32 = 110;
pub const D_DEVSTR: &str = "Development mode ON."; pub const D_DEVSTR: &str = "Development mode ON.";
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum GameMode { pub enum GameMode {
Shareware, Shareware,

View File

@@ -1,6 +1,7 @@
mod d_main; mod d_main;
mod m_argv;
mod doomdef; mod doomdef;
mod m_argv;
mod w_wad;
mod math; mod math;

235
src/w_wad/mod.rs Normal file
View File

@@ -0,0 +1,235 @@
use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
use std::mem::size_of;
use std::os::windows::io::AsRawHandle;
use std::path::Path;
#[allow(non_upper_case_globals)]
static mut numlumps: i32 = 0;
#[allow(non_upper_case_globals)]
static mut lumpinfo: Vec<lumpinfo_t> = Vec::new();
#[allow(non_upper_case_globals)]
static mut reloadlump: i32 = 0;
#[allow(non_upper_case_globals)]
static mut reloadname: String = String::new();
/// Struct of the header of a WAD file
/// All integers are 4 bytes long in x86-style little-endian order. Their values can never exceed 231-1
#[repr(C)]
pub struct wadinfo_t {
/// ASCII identifer, either IWAD or PWAD
pub identification: [u8; 4],
/// The number of lumps in the WAD
pub numlumps: i32,
/// Pointer to the location of the directory
pub infotableofs: i32,
}
/// Struct of fileumps of a WAD file
#[repr(C)]
#[derive(Clone)]
pub struct filelump_t {
/// Pointer to the start of the lumps data in the WAD file
pub filepos: i32,
/// The size of the lump in bytes
pub size: i32,
/// ASCII string identifying the lumps name
/// must be null terminated if less than 8 characters long
/// For safety, padd till end with null chars
pub name: [u8; 8],
}
/// TODO: RD-2: fill in if it is even needed for this port??
#[repr(C)]
#[derive(Clone)]
pub struct lumpinfo_t {
pub name: [u8; 8],
pub handle: isize,
pub position: i32,
pub size: i32
}
#[allow(non_snake_case)]
fn W_AddFile(file: &str) {
// Get reference to static vvariables to be used locally
let (lumpinfo_ref, reloadname_ref) = unsafe {
(
&mut *std::ptr::addr_of_mut!(lumpinfo),
&mut *std::ptr::addr_of_mut!(reloadname)
)
};
if file.as_bytes()[0] == '~' as u8 {
unsafe {
reloadname = file.chars().skip(1).collect();
reloadlump = numlumps;
}
}
let mut fileinfo: Vec<filelump_t> = Vec::new();
let mut handle: File = match std::fs::File::open(&file) {
Ok(file) => file,
Err(_) => {
println!(" couldn't open {}", file);
return;
}
};
println!("adding {}",file);
if !file.to_ascii_lowercase().ends_with(".wad") {
// process single lump
let file_meta = handle.metadata().unwrap();
// Single lump file
let mut singleinfo = filelump_t {
filepos: 0,
size: file_meta.len() as i32,
name: [0; 8]
};
let name = Path::new(file)
.file_name()
.and_then(|os_str| os_str.to_str()).unwrap();
for (i, byte) in name.as_bytes().iter().take(8).enumerate() {
singleinfo.name[i] = *byte;
}
fileinfo.push(singleinfo);
unsafe {numlumps += 1};
} else {
// WAD file
let mut header: wadinfo_t = wadinfo_t {
identification: [0; 4],
numlumps: 0,
infotableofs: 0
};
handle.read_exact(&mut header.identification).unwrap();
let mut int_buf:[u8; 4] = [0u8; 4];
handle.read_exact(&mut int_buf).unwrap();
header.numlumps = i32::from_le_bytes(int_buf);
handle.read_exact(&mut int_buf).unwrap();
header.infotableofs = i32::from_le_bytes(int_buf);
if !header.identification.eq_ignore_ascii_case(b"IWAD") {
if !header.identification.eq_ignore_ascii_case(b"PWAD") {
// TODO: Implement I_Error
// I_Error ("Wad file %s doesn't have IWAD or PWAD id\n", file);
}
}
let _ = handle.seek(SeekFrom::Start(header.infotableofs as u64));
fileinfo.resize(header.numlumps as usize, filelump_t {
filepos: 0,
size: 0,
name: [0; 8],
});
let dirinfo_bytes = header.numlumps as usize * size_of::<filelump_t>();
unsafe {
let fileinfo_slice = std::slice::from_raw_parts_mut(
fileinfo.as_mut_ptr() as *mut u8,
dirinfo_bytes,
);
handle.read_exact(fileinfo_slice).unwrap();
}
// enusre LE-ness of the ints
for fl in &mut fileinfo {
fl.filepos = i32::from_le(fl.filepos);
fl.size = i32::from_le(fl.size);
}
unsafe{numlumps += header.numlumps}
};
let is_reloaded = !reloadname_ref.is_empty();
let storehandle: isize = if is_reloaded {
-1 // Original C code closes the file immediately if it's a reloaded file
} else {
// get raw Windows HANDLE as an integer pointer
let raw_handle = handle.as_raw_handle() as isize;
// Tells rust to "trust us" and keeps the handle open after this function scope
std::mem::forget(handle);
raw_handle
};
lumpinfo_ref.reserve(fileinfo.len());
for info in fileinfo {
lumpinfo_ref.push( lumpinfo_t {
handle: storehandle,
position: info.filepos,
size: info.size,
name: info.name
})
}
}
#[allow(non_snake_case)]
pub fn W_InitMultipleFiles(filenames: Vec<String>) {
for file in filenames {
W_AddFile(&file);
}
if unsafe{numlumps == 0} {
// TODO: Implement I_Error
// I_Error("W_InitFiles: no files found")
}
// set up lump cache
}
#[allow(non_snake_case)]
pub fn W_Reload() {
}
#[allow(non_snake_case)]
pub fn W_CheckNumForName(name: &str) -> i32 {
let lumpinfo_ref = unsafe { &*std::ptr::addr_of!(lumpinfo) };
let mut search_name = [0u8; 8];
for (i, byte) in name.as_bytes().iter().take(8).enumerate() {
search_name[i] = byte.to_ascii_uppercase();
}
// 2. Scan backwards so PWAD patches take precedence over IWAD assets
lumpinfo_ref
.iter()
.enumerate()
.rev() // Iterates backward from the end
.find(|(_, lump)| lump.name == search_name)
.map(|(index, _)| index as i32) // If found, return the index
.unwrap_or(-1) // "TFB. Not found." -> return -1
}
#[allow(non_snake_case)]
pub fn W_LumpLength() {
}
#[allow(non_snake_case)]
pub fn W_ReadLump() {
}
#[allow(non_snake_case)]
pub fn W_CacheLumpNum() {
}
#[allow(non_snake_case)]
pub fn W_CacheLumpName() {
}