1 Commits

Author SHA1 Message Date
Jim
8fd20b2760 Added an inital port of d_main.c/d_main.h. Added some other basic files 2026-05-20 19:15:27 +01:00
26 changed files with 40 additions and 4578 deletions

1
.gitignore vendored
View File

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

2
.vscode/launch.json vendored
View File

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

View File

@@ -3,8 +3,4 @@ name = "RustyDoom"
version = "0.1.0" version = "0.1.0"
edition = "2024" edition = "2024"
[features]
default = []
french = []
[dependencies] [dependencies]

View File

@@ -1,46 +0,0 @@
mouse_sensitivity 5
sfx_volume 8
music_volume 8
show_messages 1
key_right 77
key_left 75
key_up 72
key_down 80
key_strafeleft 51
key_straferight 52
key_fire 29
key_use 57
key_strafe 56
key_speed 54
use_mouse 1
mouseb_fire 0
mouseb_strafe 1
mouseb_forward 2
use_joystick 0
joyb_fire 0
joyb_strafe 1
joyb_use 3
joyb_speed 2
screenblocks 9
detaillevel 0
showmessages 1
comport 1
snd_channels 8
snd_musicdevice 4
snd_sfxdevice 3
snd_sbport 544
snd_sbirq 7
snd_sbdma 1
snd_mport -1
usegamma 0
chatmacro0 "no macro"
chatmacro1 "no macro"
chatmacro2 "no macro"
chatmacro3 "no macro"
chatmacro4 "no macro"
chatmacro5 "no macro"
chatmacro6 "no macro"
chatmacro7 "no macro"
chatmacro8 "no macro"
chatmacro9 "no macro"
0

View File

@@ -1,12 +1,5 @@
# RustyDoom # RustyDoom
A Rust version of the original DOOM base on the offically released source code found at [https://github.com/id-software/doom](https://github.com/id-software/doom) A rust version of the original Doom.
This is more of a learning exercise than something good! For example, the original `z_zone.c` and `z_zone.h` will be more "Rust-like" compared to the original version. This is more of a learning exercise than something good!
This repository will only contain the SHAREWARE verison of the original DOOM1, but will be able to run both IWAD and PWADS.
This repository will be done in two parts before a "release"
1. An initial port keeping as close to the original C code as possible, which some minor modifications where it is clear on how to convert the code to Rust
2. Rust-ify any (hopefully all) parts of the code, that is removing `unsafe` and other such things. This will also include breaking down some of the `uber` sized funtions of the original source into more managable bits

Binary file not shown.

View File

@@ -8,13 +8,6 @@ use crate::m_argv;
use crate::m_argv::M_CheckParm; 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::m_menu::M_Init;
use crate::m_misc::M_LoadDefaults;
use crate::renderer::R_Init;
use crate::v_video::V_Init;
use crate::w_wad::{W_CheckNumForName, W_InitMultipleFiles};
use crate::z_zone::Z_Init;
use crate::doomdef::{ use crate::doomdef::{
VERSION, VERSION,
@@ -404,18 +397,20 @@ pub fn D_DoomMain() {
} }
} }
// TODO: Implement subsytem inits
/*
println!("V_Init: allocate screens."); println!("V_Init: allocate screens.");
V_Init(); V_Init();
println!("M_LoadDefaults: Load system defaults."); println!("M_LoadDefaults: Load system defaults.")
M_LoadDefaults(); M_LoadDefaults();
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"); println!("W_Init: Init WADfiles");
W_InitMultipleFiles(DOOMGLOBALS::with_ref(|g| g.wadfiles.clone())); // we are loading so how cares about a borrow W_InitMultipleFiles(wadfiles);
*/
let is_modified = DOOMGLOBALS::with_ref(|g| g.modifiedgame); let is_modified = DOOMGLOBALS::with_ref(|g| g.modifiedgame);
@@ -431,13 +426,12 @@ pub fn D_DoomMain() {
} }
if g_mode == GameMode::Registered { if g_mode == GameMode::Registered {
let missing_registered_lump = iwads_lumps_to_check for lump in iwads_lumps_to_check.iter().take(24) {
.iter() // TODO: Implement check
.any(|lump_name| W_CheckNumForName(lump_name) == -1); // for (i = 0;i < 23; i++)
if missing_registered_lump { // if (W_CheckNumForName(name[i])<0)
// TODO: Implement I_Error // I_Error("\nThis is not the registered version.");
// I_Error("\nThis is not the registered version."); }
}
} }
} }
@@ -468,15 +462,14 @@ pub fn D_DoomMain() {
} }
} }
// TODO: Implement other inits
/*
println!("M_Init: Init miscellaneous info."); println!("M_Init: Init miscellaneous info.");
M_Init(); M_Init();
println!("R_Init: Init DOOM refresh daemon - "); println!("R_Init: Init DOOM refresh daemon - ")
R_Init(); R_Init();
// TODO: Implement other inits
/*
println!("P_Init: Init Playloop state."); println!("P_Init: Init Playloop state.");
P_Init(); P_Init();
@@ -548,7 +541,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,638 +0,0 @@
/// English Language string constants
//
// D_Main
//
pub const D_DEVSTR: &'static str = "Development mode ON.\n";
pub const D_CDROM: &'static str = "CD-ROM Version: default.cfg from c:\\doomdata\n";
//
// M_Menu
//
pub const PRESSKEY: &'static str = "press a key.";
pub const PRESSYN: &'static str = "press y or n.";
pub const QUITMSG: &'static str = "are you sure you want to\nquit this great game?";
pub const LOADNET: &'static str = concat!("you can't do load while in a net game!\n\n", "press a key.");
pub const QLOADNET: &'static str = concat!("you can't quickload during a netgame!\n\n", "press a key.");
pub const QSAVESPOT: &'static str = concat!("you haven't picked a quicksave slot yet!\n\n", "press a key.");
pub const SAVEDEAD: &'static str = concat!("you can't save if you aren't playing!\n\n", "press a key.");
pub const QSPROMPT: &'static str = concat!("quicksave over your game named\n\n'%s'?\n\n", "press y or n.");
pub const QLPROMPT: &'static str = concat!("do you want to quickload the game named\n\n'%s'?\n\n", "press y or n.");
pub const NEWGAME: &'static str = concat!("you can't start a new game\n", "while in a network game.\n\n", "press a key.");
pub const NIGHTMARE: &'static str = concat!("are you sure? this skill level\n","isn't even remotely fair.\n\n", "press y or n.");
pub const SWSTRING: &'static str = concat!("this is the shareware version of doom.\n\n", "you need to order the entire trilogy.\n\n", "press a key.");
pub const MSGOFF: &'static str = "Messages OFF";
pub const MSGON: &'static str = "Messages ON";
pub const NETEND: &'static str = concat!("you can't end a netgame!\n\n", "press a key.");
pub const ENDGAME: &'static str = concat!("are you sure you want to end the game?\n\n", "press y or n.");
pub const DOSY: &'static str = "(press y to quit)";
pub const DETAILHI: &'static str = "High detail";
pub const DETAILLO: &'static str = "Low detail";
pub const GAMMALVL0: &'static str = "Gamma correction OFF";
pub const GAMMALVL1: &'static str = "Gamma correction level 1";
pub const GAMMALVL2: &'static str = "Gamma correction level 2";
pub const GAMMALVL3: &'static str = "Gamma correction level 3";
pub const GAMMALVL4: &'static str = "Gamma correction level 4";
pub const EMPTYSTRING: &'static str = "empty slot";
//
// P_inter.C
//
pub const GOTARMOR: &'static str = "Picked up the armor.";
pub const GOTMEGA: &'static str = "Picked up the MegaArmor!";
pub const GOTHTHBONUS: &'static str = "Picked up a health bonus.";
pub const GOTARMBONUS: &'static str = "Picked up an armor bonus.";
pub const GOTSTIM: &'static str = "Picked up a stimpack.";
pub const GOTMEDINEED: &'static str = "Picked up a medikit that you REALLY need!";
pub const GOTMEDIKIT: &'static str = "Picked up a medikit.";
pub const GOTSUPER: &'static str = "Supercharge!";
pub const GOTBLUECARD: &'static str = "Picked up a blue keycard.";
pub const GOTYELWCARD: &'static str = "Picked up a yellow keycard.";
pub const GOTREDCARD: &'static str = "Picked up a red keycard.";
pub const GOTBLUESKUL: &'static str = "Picked up a blue skull key.";
pub const GOTYELWSKUL: &'static str = "Picked up a yellow skull key.";
pub const GOTREDSKULL: &'static str = "Picked up a red skull key.";
pub const GOTINVUL: &'static str = "Invulnerability!";
pub const GOTBERSERK: &'static str = "Berserk!";
pub const GOTINVIS: &'static str = "Partial Invisibility";
pub const GOTSUIT: &'static str = "Radiation Shielding Suit";
pub const GOTMAP: &'static str = "Computer Area Map";
pub const GOTVISOR: &'static str = "Light Amplification Visor";
pub const GOTMSPHERE: &'static str = "MegaSphere!";
pub const GOTCLIP: &'static str = "Picked up a clip.";
pub const GOTCLIPBOX: &'static str = "Picked up a box of bullets.";
pub const GOTROCKET: &'static str = "Picked up a rocket.";
pub const GOTROCKBOX: &'static str = "Picked up a box of rockets.";
pub const GOTCELL: &'static str = "Picked up an energy cell.";
pub const GOTCELLBOX: &'static str = "Picked up an energy cell pack.";
pub const GOTSHELLS: &'static str = "Picked up 4 shotgun shells.";
pub const GOTSHELLBOX: &'static str = "Picked up a box of shotgun shells.";
pub const GOTBACKPACK: &'static str = "Picked up a backpack full of ammo!";
pub const GOTBFG9000: &'static str = "You got the BFG9000! Oh, yes.";
pub const GOTCHAINGUN: &'static str = "You got the chaingun!";
pub const GOTCHAINSAW: &'static str = "A chainsaw! Find some meat!";
pub const GOTLAUNCHER: &'static str = "You got the rocket launcher!";
pub const GOTPLASMA: &'static str = "You got the plasma gun!";
pub const GOTSHOTGUN: &'static str = "You got the shotgun!";
pub const GOTSHOTGUN2: &'static str = "You got the super shotgun!";
//
// P_Doors.C
//
pub const PD_BLUEO: &'static str = "You need a blue key to activate this object";
pub const PD_REDO: &'static str = "You need a red key to activate this object";
pub const PD_YELLOWO: &'static str = "You need a yellow key to activate this object";
pub const PD_BLUEK: &'static str = "You need a blue key to open this door";
pub const PD_REDK: &'static str = "You need a red key to open this door";
pub const PD_YELLOWK: &'static str = "You need a yellow key to open this door";
//
// G_game.C
//
pub const GGSAVED: &'static str = "game saved.";
//
// HU_stuff.C
//
pub const HUSTR_MSGU: &'static str = "[Message unsent]";
pub const HUSTR_E1M1: &'static str = "E1M1: Hangar";
pub const HUSTR_E1M2: &'static str = "E1M2: Nuclear Plant";
pub const HUSTR_E1M3: &'static str = "E1M3: Toxin Refinery";
pub const HUSTR_E1M4: &'static str = "E1M4: Command Control";
pub const HUSTR_E1M5: &'static str = "E1M5: Phobos Lab";
pub const HUSTR_E1M6: &'static str = "E1M6: Central Processing";
pub const HUSTR_E1M7: &'static str = "E1M7: Computer Station";
pub const HUSTR_E1M8: &'static str = "E1M8: Phobos Anomaly";
pub const HUSTR_E1M9: &'static str = "E1M9: Military Base";
pub const HUSTR_E2M1: &'static str = "E2M1: Deimos Anomaly";
pub const HUSTR_E2M2: &'static str = "E2M2: Containment Area";
pub const HUSTR_E2M3: &'static str = "E2M3: Refinery";
pub const HUSTR_E2M4: &'static str = "E2M4: Deimos Lab";
pub const HUSTR_E2M5: &'static str = "E2M5: Command Center";
pub const HUSTR_E2M6: &'static str = "E2M6: Halls of the Damned";
pub const HUSTR_E2M7: &'static str = "E2M7: Spawning Vats";
pub const HUSTR_E2M8: &'static str = "E2M8: Tower of Babel";
pub const HUSTR_E2M9: &'static str = "E2M9: Fortress of Mystery";
pub const HUSTR_E3M1: &'static str = "E3M1: Hell Keep";
pub const HUSTR_E3M2: &'static str = "E3M2: Slough of Despair";
pub const HUSTR_E3M3: &'static str = "E3M3: Pandemonium";
pub const HUSTR_E3M4: &'static str = "E3M4: House of Pain";
pub const HUSTR_E3M5: &'static str = "E3M5: Unholy Cathedral";
pub const HUSTR_E3M6: &'static str = "E3M6: Mt. Erebus";
pub const HUSTR_E3M7: &'static str = "E3M7: Limbo";
pub const HUSTR_E3M8: &'static str = "E3M8: Dis";
pub const HUSTR_E3M9: &'static str = "E3M9: Warrens";
pub const HUSTR_E4M1: &'static str = "E4M1: Hell Beneath";
pub const HUSTR_E4M2: &'static str = "E4M2: Perfect Hatred";
pub const HUSTR_E4M3: &'static str = "E4M3: Sever The Wicked";
pub const HUSTR_E4M4: &'static str = "E4M4: Unruly Evil";
pub const HUSTR_E4M5: &'static str = "E4M5: They Will Repent";
pub const HUSTR_E4M6: &'static str = "E4M6: Against Thee Wickedly";
pub const HUSTR_E4M7: &'static str = "E4M7: And Hell Followed";
pub const HUSTR_E4M8: &'static str = "E4M8: Unto The Cruel";
pub const HUSTR_E4M9: &'static str = "E4M9: Fear";
pub const HUSTR_1: &'static str = "level 1: entryway";
pub const HUSTR_2: &'static str = "level 2: underhalls";
pub const HUSTR_3: &'static str = "level 3: the gantlet";
pub const HUSTR_4: &'static str = "level 4: the focus";
pub const HUSTR_5: &'static str = "level 5: the waste tunnels";
pub const HUSTR_6: &'static str = "level 6: the crusher";
pub const HUSTR_7: &'static str = "level 7: dead simple";
pub const HUSTR_8: &'static str = "level 8: tricks and traps";
pub const HUSTR_9: &'static str = "level 9: the pit";
pub const HUSTR_10: &'static str = "level 10: refueling base";
pub const HUSTR_11: &'static str = "level 11: 'o' of destruction!";
pub const HUSTR_12: &'static str = "level 12: the factory";
pub const HUSTR_13: &'static str = "level 13: downtown";
pub const HUSTR_14: &'static str = "level 14: the inmost dens";
pub const HUSTR_15: &'static str = "level 15: industrial zone";
pub const HUSTR_16: &'static str = "level 16: suburbs";
pub const HUSTR_17: &'static str = "level 17: tenements";
pub const HUSTR_18: &'static str = "level 18: the courtyard";
pub const HUSTR_19: &'static str = "level 19: the citadel";
pub const HUSTR_20: &'static str = "level 20: gotcha!";
pub const HUSTR_21: &'static str = "level 21: nirvana";
pub const HUSTR_22: &'static str = "level 22: the catacombs";
pub const HUSTR_23: &'static str = "level 23: barrels o' fun";
pub const HUSTR_24: &'static str = "level 24: the chasm";
pub const HUSTR_25: &'static str = "level 25: bloodfalls";
pub const HUSTR_26: &'static str = "level 26: the abandoned mines";
pub const HUSTR_27: &'static str = "level 27: monster condo";
pub const HUSTR_28: &'static str = "level 28: the spirit world";
pub const HUSTR_29: &'static str = "level 29: the living end";
pub const HUSTR_30: &'static str = "level 30: icon of sin";
pub const HUSTR_31: &'static str = "level 31: wolfenstein";
pub const HUSTR_32: &'static str = "level 32: grosse";
pub const PHUSTR_1: &'static str ="level 1: congo";
pub const PHUSTR_2: &'static str ="level 2: well of souls";
pub const PHUSTR_3: &'static str ="level 3: aztec";
pub const PHUSTR_4: &'static str ="level 4: caged";
pub const PHUSTR_5: &'static str ="level 5: ghost town";
pub const PHUSTR_6: &'static str ="level 6: baron's lair";
pub const PHUSTR_7: &'static str ="level 7: caughtyard";
pub const PHUSTR_8: &'static str ="level 8: realm";
pub const PHUSTR_9: &'static str ="level 9: abattoire";
pub const PHUSTR_10: &'static str = "level 10: onslaught";
pub const PHUSTR_11: &'static str = "level 11: hunted";
pub const PHUSTR_12: &'static str = "level 12: speed";
pub const PHUSTR_13: &'static str = "level 13: the crypt";
pub const PHUSTR_14: &'static str = "level 14: genesis";
pub const PHUSTR_15: &'static str = "level 15: the twilight";
pub const PHUSTR_16: &'static str = "level 16: the omen";
pub const PHUSTR_17: &'static str = "level 17: compound";
pub const PHUSTR_18: &'static str = "level 18: neurosphere";
pub const PHUSTR_19: &'static str = "level 19: nme";
pub const PHUSTR_20: &'static str = "level 20: the death domain";
pub const PHUSTR_21: &'static str = "level 21: slayer";
pub const PHUSTR_22: &'static str = "level 22: impossible mission";
pub const PHUSTR_23: &'static str = "level 23: tombstone";
pub const PHUSTR_24: &'static str = "level 24: the final frontier";
pub const PHUSTR_25: &'static str = "level 25: the temple of darkness";
pub const PHUSTR_26: &'static str = "level 26: bunker";
pub const PHUSTR_27: &'static str = "level 27: anti-christ";
pub const PHUSTR_28: &'static str = "level 28: the sewers";
pub const PHUSTR_29: &'static str = "level 29: odyssey of noises";
pub const PHUSTR_30: &'static str = "level 30: the gateway of hell";
pub const PHUSTR_31: &'static str = "level 31: cyberden";
pub const PHUSTR_32: &'static str = "level 32: go 2 it";
pub const THUSTR_1: &'static str = "level 1: system control";
pub const THUSTR_2: &'static str = "level 2: human bbq";
pub const THUSTR_3: &'static str = "level 3: power control";
pub const THUSTR_4: &'static str = "level 4: wormhole";
pub const THUSTR_5: &'static str = "level 5: hanger";
pub const THUSTR_6: &'static str = "level 6: open season";
pub const THUSTR_7: &'static str = "level 7: prison";
pub const THUSTR_8: &'static str = "level 8: metal";
pub const THUSTR_9: &'static str = "level 9: stronghold";
pub const THUSTR_10: &'static str = "level 10: redemption";
pub const THUSTR_11: &'static str = "level 11: storage facility";
pub const THUSTR_12: &'static str = "level 12: crater";
pub const THUSTR_13: &'static str = "level 13: nukage processing";
pub const THUSTR_14: &'static str = "level 14: steel works";
pub const THUSTR_15: &'static str = "level 15: dead zone";
pub const THUSTR_16: &'static str = "level 16: deepest reaches";
pub const THUSTR_17: &'static str = "level 17: processing area";
pub const THUSTR_18: &'static str = "level 18: mill";
pub const THUSTR_19: &'static str = "level 19: shipping/respawning";
pub const THUSTR_20: &'static str = "level 20: central processing";
pub const THUSTR_21: &'static str = "level 21: administration center";
pub const THUSTR_22: &'static str = "level 22: habitat";
pub const THUSTR_23: &'static str = "level 23: lunar mining project";
pub const THUSTR_24: &'static str = "level 24: quarry";
pub const THUSTR_25: &'static str = "level 25: baron's den";
pub const THUSTR_26: &'static str = "level 26: ballistyx";
pub const THUSTR_27: &'static str = "level 27: mount pain";
pub const THUSTR_28: &'static str = "level 28: heck";
pub const THUSTR_29: &'static str = "level 29: river styx";
pub const THUSTR_30: &'static str = "level 30: last call";
pub const THUSTR_31: &'static str ="level 31: pharaoh";
pub const THUSTR_32: &'static str ="level 32: caribbean";
pub const HUSTR_CHATMACRO1: &'static str = "I'm ready to kick butt!";
pub const HUSTR_CHATMACRO2: &'static str = "I'm OK.";
pub const HUSTR_CHATMACRO3: &'static str = "I'm not looking too good!";
pub const HUSTR_CHATMACRO4: &'static str = "Help!";
pub const HUSTR_CHATMACRO5: &'static str = "You suck!";
pub const HUSTR_CHATMACRO6: &'static str = "Next time, scumbag...";
pub const HUSTR_CHATMACRO7: &'static str = "Come here!";
pub const HUSTR_CHATMACRO8: &'static str = "I'll take care of it.";
pub const HUSTR_CHATMACRO9: &'static str = "Yes";
pub const HUSTR_CHATMACRO0: &'static str = "No";
pub const HUSTR_TALKTOSELF1: &'static str = "You mumble to yourself";
pub const HUSTR_TALKTOSELF2: &'static str = "Who's there?";
pub const HUSTR_TALKTOSELF3: &'static str = "You scare yourself";
pub const HUSTR_TALKTOSELF4: &'static str = "You start to rave";
pub const HUSTR_TALKTOSELF5: &'static str = "You've lost it...";
pub const HUSTR_MESSAGESENT: &'static str = "[Message Sent]";
// The following should NOT be changed unless it seems
// just AWFULLY necessary
pub const HUSTR_PLRGREEN: &'static str = "Green: ";
pub const HUSTR_PLRINDIGO: &'static str = "Indigo: ";
pub const HUSTR_PLRBROWN: &'static str = "Brown: ";
pub const HUSTR_PLRRED: &'static str = "Red: ";
pub const HUSTR_KEYGREEN: &'static str = "g";
pub const HUSTR_KEYINDIGO: &'static str = "i";
pub const HUSTR_KEYBROWN: &'static str = "b";
pub const HUSTR_KEYRED: &'static str = "r";
//
// AM_map.C
//
pub const AMSTR_FOLLOWON: &'static str = "Follow Mode ON";
pub const AMSTR_FOLLOWOFF: &'static str = "Follow Mode OFF";
pub const AMSTR_GRIDON: &'static str = "Grid ON";
pub const AMSTR_GRIDOFF: &'static str = "Grid OFF";
pub const AMSTR_MARKEDSPOT: &'static str = "Marked Spot";
pub const AMSTR_MARKSCLEARED: &'static str = "All Marks Cleared";
//
// ST_stuff.C
//
pub const STSTR_MUS: &'static str = "Music Change";
pub const STSTR_NOMUS: &'static str = "IMPOSSIBLE SELECTION";
pub const STSTR_DQDON: &'static str = "Degreelessness Mode On";
pub const STSTR_DQDOFF: &'static str = "Degreelessness Mode Off";
pub const STSTR_KFAADDED: &'static str = "Very Happy Ammo Added";
pub const STSTR_FAADDED: &'static str = "Ammo (no keys) Added";
pub const STSTR_NCON: &'static str = "No Clipping Mode ON";
pub const STSTR_NCOFF: &'static str = "No Clipping Mode OFF";
pub const STSTR_BEHOLD: &'static str = "inVuln, Str, Inviso, Rad, Allmap, or Lite-amp";
pub const STSTR_BEHOLDX: &'static str = "Power-up Toggled";
pub const STSTR_CHOPPERS: &'static str = "... doesn't suck - GM";
pub const STSTR_CLEV: &'static str = "Changing Level...";
//
// F_Finale.C
//
pub const E1TEXT: &'static str = concat!("Once you beat the big badasses and\n",
"clean out the moon base you're supposed\n",
"to win, aren't you? Aren't you? Where's\n",
"your fat reward and ticket home? What\n",
"the hell is this? It's not supposed to\n",
"end this way!\n",
"\n" ,
"It stinks like rotten meat, but looks\n",
"like the lost Deimos base. Looks like\n",
"you're stuck on The Shores of Hell.\n",
"The only way out is through.\n",
"\n",
"To continue the DOOM experience, play\n",
"The Shores of Hell and its amazing\n",
"sequel, Inferno!\n");
pub const E2TEXT: &'static str = concat!("You've done it! The hideous cyber-\n",
"demon lord that ruled the lost Deimos\n",
"moon base has been slain and you\n",
"are triumphant! But ... where are\n",
"you? You clamber to the edge of the\n",
"moon and look down to see the awful\n",
"truth.\n" ,
"\n",
"Deimos floats above Hell itself!\n",
"You've never heard of anyone escaping\n",
"from Hell, but you'll make the bastards\n",
"sorry they ever heard of you! Quickly,\n",
"you rappel down to the surface of\n",
"Hell.\n",
"\n" ,
"Now, it's on to the final chapter of\n",
"DOOM! -- Inferno.");
pub const E3TEXT: &'static str = concat!("The loathsome spiderdemon that\n",
"masterminded the invasion of the moon\n",
"bases and caused so much death has had\n",
"its ass kicked for all time.\n",
"\n",
"A hidden doorway opens and you enter.\n",
"You've proven too tough for Hell to\n",
"contain, and now Hell at last plays\n",
"fair -- for you emerge from the door\n",
"to see the green fields of Earth!\n",
"Home at last.\n" ,
"\n",
"You wonder what's been happening on\n",
"Earth while you were battling evil\n",
"unleashed. It's good that no Hell-\n",
"spawn could have come through that\n",
"door with you ...");
pub const E4TEXT: &'static str = concat!("the spider mastermind must have sent forth\n",
"its legions of hellspawn before your\n",
"final confrontation with that terrible\n",
"beast from hell. but you stepped forward\n",
"and brought forth eternal damnation and\n",
"suffering upon the horde as a true hero\n",
"would in the face of something so evil.\n",
"\n",
"besides, someone was gonna pay for what\n",
"happened to daisy, your pet rabbit.\n",
"\n",
"but now, you see spread before you more\n",
"potential pain and gibbitude as a nation\n",
"of demons run amok among our cities.\n",
"\n",
"next stop, hell on earth!");
// after level 6, put this:
pub const C1TEXT: &'static str = concat!("YOU HAVE ENTERED DEEPLY INTO THE INFESTED\n",
"STARPORT. BUT SOMETHING IS WRONG. THE\n",
"MONSTERS HAVE BROUGHT THEIR OWN REALITY\n",
"WITH THEM, AND THE STARPORT'S TECHNOLOGY\n",
"IS BEING SUBVERTED BY THEIR PRESENCE.\n",
"\n",
"AHEAD, YOU SEE AN OUTPOST OF HELL, A\n",
"FORTIFIED ZONE. IF YOU CAN GET PAST IT,\n",
"YOU CAN PENETRATE INTO THE HAUNTED HEART\n",
"OF THE STARBASE AND FIND THE CONTROLLING\n",
"SWITCH WHICH HOLDS EARTH'S POPULATION\n",
"HOSTAGE.");
// After level 11, put this:
pub const C2TEXT: &'static str = concat!("YOU HAVE WON! YOUR VICTORY HAS ENABLED\n",
"HUMANKIND TO EVACUATE EARTH AND ESCAPE\n",
"THE NIGHTMARE. NOW YOU ARE THE ONLY\n",
"HUMAN LEFT ON THE FACE OF THE PLANET.\n",
"CANNIBAL MUTATIONS, CARNIVOROUS ALIENS,\n",
"AND EVIL SPIRITS ARE YOUR ONLY NEIGHBORS.\n",
"YOU SIT BACK AND WAIT FOR DEATH, CONTENT\n",
"THAT YOU HAVE SAVED YOUR SPECIES.\n",
"\n",
"BUT THEN, EARTH CONTROL BEAMS DOWN A\n",
"MESSAGE FROM SPACE: \"SENSORS HAVE LOCATED\n",
"THE SOURCE OF THE ALIEN INVASION. IF YOU\n",
"GO THERE, YOU MAY BE ABLE TO BLOCK THEIR\n",
"ENTRY. THE ALIEN BASE IS IN THE HEART OF\n",
"YOUR OWN HOME CITY, NOT FAR FROM THE\n",
"STARPORT.\" SLOWLY AND PAINFULLY YOU GET\n",
"UP AND RETURN TO THE FRAY.");
// After level 20, put this:
pub const C3TEXT: &'static str = concat!("YOU ARE AT THE CORRUPT HEART OF THE CITY,\n",
"SURROUNDED BY THE CORPSES OF YOUR ENEMIES.\n",
"YOU SEE NO WAY TO DESTROY THE CREATURES'\n",
"ENTRYWAY ON THIS SIDE, SO YOU CLENCH YOUR\n",
"TEETH AND PLUNGE THROUGH IT.\n",
"\n",
"THERE MUST BE A WAY TO CLOSE IT ON THE\n",
"OTHER SIDE. WHAT DO YOU CARE IF YOU'VE\n",
"GOT TO GO THROUGH HELL TO GET TO IT?");
// After level 29, put this:
pub const C4TEXT: &'static str = concat!("THE HORRENDOUS VISAGE OF THE BIGGEST\n",
"DEMON YOU'VE EVER SEEN CRUMBLES BEFORE\n",
"YOU, AFTER YOU PUMP YOUR ROCKETS INTO\n",
"HIS EXPOSED BRAIN. THE MONSTER SHRIVELS\n",
"UP AND DIES, ITS THRASHING LIMBS\n",
"DEVASTATING UNTOLD MILES OF HELL'S\n",
"SURFACE.\n",
"\n",
"YOU'VE DONE IT. THE INVASION IS OVER.\n",
"EARTH IS SAVED. HELL IS A WRECK. YOU\n",
"WONDER WHERE BAD FOLKS WILL GO WHEN THEY\n",
"DIE, NOW. WIPING THE SWEAT FROM YOUR\n",
"FOREHEAD YOU BEGIN THE LONG TREK BACK\n",
"HOME. REBUILDING EARTH OUGHT TO BE A\n",
"LOT MORE FUN THAN RUINING IT WAS.\n");
// Before level 31, put this:
pub const C5TEXT: &'static str = concat!("CONGRATULATIONS, YOU'VE FOUND THE SECRET\n",
"LEVEL! LOOKS LIKE IT'S BEEN BUILT BY\n",
"HUMANS, RATHER THAN DEMONS. YOU WONDER\n",
"WHO THE INMATES OF THIS CORNER OF HELL\n",
"WILL BE.");
// Before level 32, put this:
pub const C6TEXT: &'static str = concat!("CONGRATULATIONS, YOU'VE FOUND THE\n",
"SUPER SECRET LEVEL! YOU'D BETTER\n",
"BLAZE THROUGH THIS ONE!\n");
// after map 06
pub const P1TEXT: &'static str = concat!("You gloat over the steaming carcass of the\n",
"Guardian. With its death, you've wrested\n",
"the Accelerator from the stinking claws\n",
"of Hell. You relax and glance around the\n",
"room. Damn! There was supposed to be at\n",
"least one working prototype, but you can't\n",
"see it. The demons must have taken it.\n",
"\n",
"You must find the prototype, or all your\n",
"struggles will have been wasted. Keep\n",
"moving, keep fighting, keep killing.\n",
"Oh yes, keep living, too.");
// after map 11
pub const P2TEXT: &'static str = concat!("Even the deadly Arch-Vile labyrinth could\n",
"not stop you, and you've gotten to the\n",
"prototype Accelerator which is soon\n",
"efficiently and permanently deactivated.\n",
"\n",
"You're good at that kind of thing.");
// after map 20
pub const P3TEXT: &'static str = concat!("You've bashed and battered your way into\n",
"the heart of the devil-hive. Time for a\n",
"Search-and-Destroy mission, aimed at the\n",
"Gatekeeper, whose foul offspring is\n",
"cascading to Earth. Yeah, he's bad. But\n",
"you know who's worse!\n",
"\n",
"Grinning evilly, you check your gear, and\n",
"get ready to give the bastard a little Hell\n",
"of your own making!");
// after map 30
pub const P4TEXT: &'static str = concat!("The Gatekeeper's evil face is splattered\n",
"all over the place. As its tattered corpse\n",
"collapses, an inverted Gate forms and\n",
"sucks down the shards of the last\n",
"prototype Accelerator, not to mention the\n",
"few remaining demons. You're done. Hell\n",
"has gone back to pounding bad dead folks \n",
"instead of good live ones. Remember to\n",
"tell your grandkids to put a rocket\n",
"launcher in your coffin. If you go to Hell\n",
"when you die, you'll need it for some\n",
"final cleaning-up ...");
// before map 31
pub const P5TEXT: &'static str = concat!("You've found the second-hardest level we\n",
"got. Hope you have a saved game a level or\n",
"two previous. If not, be prepared to die\n",
"aplenty. For master marines only.");
// before map 32
pub const P6TEXT: &'static str = concat!("Betcha wondered just what WAS the hardest\n",
"level we had ready for ya? Now you know.\n",
"No one gets out alive.");
pub const T1TEXT: &'static str = concat!("You've fought your way out of the infested\n",
"experimental labs. It seems that UAC has\n",
"once again gulped it down. With their\n",
"high turnover, it must be hard for poor\n",
"old UAC to buy corporate health insurance\n",
"nowadays..\n",
"\n",
"Ahead lies the military complex, now\n",
"swarming with diseased horrors hot to get\n",
"their teeth into you. With luck, the\n",
"complex still has some warlike ordnance\n",
"laying around.");
pub const T2TEXT: &'static str = concat!("You hear the grinding of heavy machinery\n",
"ahead. You sure hope they're not stamping\n",
"out new hellspawn, but you're ready to\n",
"ream out a whole herd if you have to.\n",
"They might be planning a blood feast, but\n",
"you feel about as mean as two thousand\n",
"maniacs packed into one mad killer.\n",
"\n",
"You don't plan to go down easy.");
pub const T3TEXT: &'static str = concat!("The vista opening ahead looks real damn\n",
"familiar. Smells familiar, too -- like\n",
"fried excrement. You didn't like this\n",
"place before, and you sure as hell ain't\n",
"planning to like it now. The more you\n",
"brood on it, the madder you get.\n",
"Hefting your gun, an evil grin trickles\n",
"onto your face. Time to take some names.");
pub const T4TEXT: &'static str = concat!("Suddenly, all is silent, from one horizon\n",
"to the other. The agonizing echo of Hell\n",
"fades away, the nightmare sky turns to\n",
"blue, the heaps of monster corpses start \n",
"to evaporate along with the evil stench \n",
"that filled the air. Jeeze, maybe you've\n",
"done it. Have you really won?\n",
"\n",
"Something rumbles in the distance.\n",
"A blue light begins to glow inside the\n",
"ruined skull of the demon-spitter.");
pub const T5TEXT: &'static str = concat!("What now? Looks totally different. Kind\n",
"of like King Tut's condo. Well,\n",
"whatever's here can't be any worse\n",
"than usual. Can it? Or maybe it's best\n",
"to let sleeping gods lie..");
pub const T6TEXT: &'static str = concat!("Time for a vacation. You've burst the\n",
"bowels of hell and by golly you're ready\n",
"for a break. You mutter to yourself,\n",
"Maybe someone else can kick Hell's ass\n",
"next time around. Ahead lies a quiet town,\n",
"with peaceful flowing water, quaint\n",
"buildings, and presumably no Hellspawn.\n",
"\n",
"As you step off the transport, you hear\n",
"the stomp of a cyberdemon's iron shoe.");
//
// Character cast strings F_FINALE.C
//
pub const CC_ZOMBIE: &'static str = "ZOMBIEMAN";
pub const CC_SHOTGUN: &'static str = "SHOTGUN GUY";
pub const CC_HEAVY: &'static str = "HEAVY WEAPON DUDE";
pub const CC_IMP: &'static str = "IMP";
pub const CC_DEMON: &'static str = "DEMON";
pub const CC_LOST: &'static str = "LOST SOUL";
pub const CC_CACO: &'static str = "CACODEMON";
pub const CC_HELL: &'static str = "HELL KNIGHT";
pub const CC_BARON: &'static str = "BARON OF HELL";
pub const CC_ARACH: &'static str = "ARACHNOTRON";
pub const CC_PAIN: &'static str = "PAIN ELEMENTAL";
pub const CC_REVEN: &'static str = "REVENANT";
pub const CC_MANCU: &'static str = "MANCUBUS";
pub const CC_ARCH: &'static str = "ARCH-VILE";
pub const CC_SPIDER: &'static str = "THE SPIDER MASTERMIND";
pub const CC_CYBER: &'static str = "THE CYBERDEMON";
pub const CC_HERO: &'static str = "OUR HERO";

View File

@@ -1,3 +0,0 @@
/// French Language string constants
///
/// NOT IMPLEMENTED "C'est injuste envers les Français !"

View File

@@ -1,20 +0,0 @@
#[cfg(feature = "french")]
mod d_french;
#[cfg(not(feature = "french"))]
mod d_english;
#[cfg(feature = "french")]
pub use d_french::*;
#[cfg(not(feature = "french"))]
pub use d_english::*;
pub const SAVEGAMENAME: &'static str = "doomsav";
pub const DEVMPAS: &'static str = "devmaps";
pub const DEVDATA: &'static str = "devdata";
pub const NUM_QUITMESSAGES: i32 = 22;

View File

@@ -1,38 +1,9 @@
use std::cell::RefCell; use std::cell::RefCell;
use std::sync::{Mutex, MutexGuard, OnceLock};
/// DOOM version
pub const VERSION:i32 = 110; pub const VERSION:i32 = 110;
pub const D_DEVSTR: &str = "Development mode ON.";
/// BASE_WIDTH
/// For resize of screen, at start of game.
/// It will not work dynamically, see visplanes. TODO: Investigate what this means.
pub const BASE_WIDTH: i32 = 320;
/// Screen scale multiplier?
/// Original source comment:
/// It is educational but futile to change this
/// scaling e.g. to 2. Drawing of status bar,
/// menues etc. is tied to the scale implied
/// by the graphics.
pub const SCREEN_MUL: i32 = 1;
/// Inverse of the aspect ratio
pub const INV_ASPECT_RATIO: f32 = 0.625; // 0.75, ideally according to the original source
/// SCREENWIDTH
/// = SCREEN_MUL*BASE_WIDTH //320
pub const SCREENWIDTH: i32 = 320;
/// SCREENHEIGHT
/// (int)(SCREEN_MUL*BASE_WIDTH*INV_ASPECT_RATIO) //200
pub const SCREENHEIGHT:i32 = 200;
/// The maximum number of players, multiplayer/networking.
pub const MAXPLAYERS: i32 = 4;
/// The number of state updates (ticks) to be done per second
pub const TICRATE: i32 = 35;
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum GameMode { pub enum GameMode {

View File

@@ -1,10 +0,0 @@
pub const MAXCHAR: i8 = i8::MAX;
pub const MAXSHORT: i16 = i16::MAX;
pub const MAXINT: i32 = i32::MAX;
pub const MAXLONG: i32 = i32::MAX;
// Minimum values
pub const MINCHAR: i8 = i8::MIN;
pub const MINSHORT: i16 = i16::MIN;
pub const MININT: i32 = i32::MIN;
pub const MINLONG: i32 = i32::MIN;

View File

@@ -1,99 +0,0 @@
/// Heads up display stuff
use std::sync::OnceLock;
use crate::doomdef::TICRATE;
use crate::d_strings;
/// The first font characters
pub const HU_FONTSTART: char = '!';
/// The last font characters
pub const HU_FONTEND: char = '_';
/// Number of glyphs in the font
pub const HU_FONTSIZE: u8 = (HU_FONTEND as u8 - HU_FONTSTART as u8) + 1;
pub const HU_BROADCAST: i32 = 5;
// pub const HU_MSGREFRESH = KEY_ENTER // Comes from doomdef.h TODO: implement more doomdef!
pub const HU_MSGX: i32 = 0;
pub const HU_MSGY: i32 = 0;
/// The width of a message in characters
pub const HU_MSGWIDTH: i32 = 64;
/// The height of a message in lines
pub const HU_MSGHEIGHT: i32 = 1;
/// The time a message should be displayed for before it disapears
pub const HU_MSGTIMEOUT: i32 = 4 * TICRATE;
/// Constant string arrays
static CHAT_MACROS_LOCK: OnceLock<[String; 10]> = OnceLock::new();
pub fn get_chat_macro_ptr(index: usize) -> *mut String {
let array_ref = CHAT_MACROS_LOCK.get_or_init(|| [
d_strings::HUSTR_CHATMACRO0.to_string(),
d_strings::HUSTR_CHATMACRO1.to_string(),
d_strings::HUSTR_CHATMACRO2.to_string(),
d_strings::HUSTR_CHATMACRO3.to_string(),
d_strings::HUSTR_CHATMACRO4.to_string(),
d_strings::HUSTR_CHATMACRO5.to_string(),
d_strings::HUSTR_CHATMACRO6.to_string(),
d_strings::HUSTR_CHATMACRO7.to_string(),
d_strings::HUSTR_CHATMACRO8.to_string(),
d_strings::HUSTR_CHATMACRO9.to_string(),
]);
// Cast the immutable reference from the lock to a raw mutable pointer
unsafe {
let array_ptr = array_ref.as_ptr() as *mut String;
array_ptr.add(index)
}
}
// HUD text stuff
#[allow(non_snake_case)]
pub fn HU_INIT() {
}
#[allow(non_snake_case)]
pub fn HU_Start() {
}
/*
// TODO: Implement d_event.h/c
#[allow(non_snake_case)]
pub fn HU_Responder(event_t* ev) {
}
*/
#[allow(non_snake_case)]
pub fn HU_Ticker() {
}
#[allow(non_snake_case)]
pub fn HU_Ticket() {
}
#[allow(non_snake_case)]
pub fn HU_dequeueChatChar() /*-> char */ {
}
#[allow(non_snake_case)]
pub fn HU_Erase() {
}

View File

@@ -1,323 +0,0 @@
// Menu Widget stuff i.e episode selection etc.
// TODO: Implement d_event.handle
use std::ptr::addr_of_mut;
use crate::doomdef::{DOOMGLOBALS, GameMode};
#[repr(C)]
#[derive(Copy, Clone)]
#[allow(non_snake_case)]
struct menuitem_t {
status: i32,
name: [u8; 10],
routine: Option<fn(choice: i32)>,
// hotkey in menu
alpha_key: u8,
}
#[repr(C)]
#[derive(Copy, Clone)]
#[allow(non_snake_case)]
struct menu_t {
/// Number of items in the menu
numitems: i32,
/// Pointer to the previous menu
prevMenu: *mut menu_t,
/// The menu items
menuItems: *mut menuitem_t,
/// draw routine
routine: Option<fn()>,
/// X of the menu
x: i32,
/// y of the menu
y: i32,
/// The last item the user was on in the menu
lastOn: i32
}
/// TEMP function
#[allow(non_snake_case)]
fn VoidRoutine() {
}
#[allow(non_snake_case)]
fn VoidRoutineWithChoice(choice: i32) {
let _ = choice;
}
// Main Menu
#[allow(non_snake_case)]
mod MainMenu {
use super::*;
/// Enumeration of the main menu options
#[allow(non_camel_case_types)]
pub(super) enum main_e {
newgame = 0,
options,
loadgame,
savegame,
readthis,
quitdoom,
main_end
}
/// Main Menu items
#[allow(non_upper_case_globals)]
pub(super) static mut MainMenu: [menuitem_t; 6] = [
menuitem_t {
status: 1,
name: *b"M_NGAME\0\0\0",
routine: Some(VoidRoutineWithChoice),
alpha_key: b'n'
},
menuitem_t {
status: 1,
name: *b"M_OPTION\0\0",
routine: Some(VoidRoutineWithChoice),
alpha_key: b'o'
},
menuitem_t {
status: 1,
name: *b"M_LOADG\0\0\0",
routine: Some(VoidRoutineWithChoice),
alpha_key: b'l'
},
menuitem_t {
status: 1,
name: *b"M_SAVEG\0\0\0",
routine: Some(VoidRoutineWithChoice),
alpha_key: b's'
},
menuitem_t {
status: 1,
name: *b"M_RDTHIS\0\0",
routine: Some(VoidRoutineWithChoice),
alpha_key: b'r'
},
menuitem_t {
status: 1,
name: *b"M_QUITG\0\0\0",
routine: Some(VoidRoutineWithChoice),
alpha_key: b'q'
}
];
/// Default MainMenu
#[allow(non_upper_case_globals)]
pub(super) static mut MainDef: menu_t = menu_t {
numitems: main_e::main_end as i32,
prevMenu: std::ptr::null_mut(),
menuItems: &raw mut MainMenu as *mut menuitem_t, // Use &raw mut instead of .as_mut_ptr() to avoid illegal static mut references (Feels dirty)
routine: Some(VoidRoutine),
x: 97,
y: 64,
lastOn: 0,
};
}
// New Game menu
#[allow(non_snake_case)]
mod NewGameMenu {
use super::*;
/// Enumeration of the New Game options
#[allow(non_camel_case_types)]
pub(super) enum newgame_e {
killthings,
toorough,
hurtme,
violence,
nightmare,
newg_end
}
/// New Game Menu items
#[allow(non_upper_case_globals)]
pub(super) static mut NewGameMenu: [menuitem_t; 5] = [
menuitem_t {
status: 1,
name: *b"M_JKILL\0\0\0",
routine: Some(VoidRoutineWithChoice),
alpha_key: b'i'
},
menuitem_t {
status: 1,
name: *b"M_ROUGH\0\0\0",
routine: Some(VoidRoutineWithChoice),
alpha_key: b'h'
},
menuitem_t {
status: 1,
name: *b"M_HURT\0\0\0\0",
routine: Some(VoidRoutineWithChoice),
alpha_key: b'h'
},
menuitem_t {
status: 1,
name: *b"M_ULTRA\0\0\0",
routine: Some(VoidRoutineWithChoice),
alpha_key: b'u'
},
menuitem_t {
status: 1,
name: *b"M_NMARE\0\0\0",
routine: Some(VoidRoutineWithChoice),
alpha_key: b'n'
}
];
#[allow(non_upper_case_globals)]
pub(super) static mut NewDef: menu_t = menu_t {
numitems: newgame_e::newg_end as i32,
prevMenu: std::ptr::null_mut(), // TODO: Add EpiDef
menuItems: &raw mut NewGameMenu as *mut menuitem_t, // Use &raw mut instead of .as_mut_ptr() to avoid illegal static mut references (Feels dirty)
routine: Some(VoidRoutine),
x: 48,
y: 63,
lastOn: newgame_e::hurtme as i32,
};
}
// TODO: add OptionsMenu
#[allow(non_snake_case)]
mod ReadThis1 {
use super::*;
/// Enumeration of the main menu options
#[allow(non_camel_case_types)]
pub(super) enum read_e {
rdthisempty1 = 0,
read1_end,
}
/// Read1 Menu items
#[allow(non_upper_case_globals)]
pub(super) static mut ReadMenu1: [menuitem_t; 1] = [
menuitem_t {
status: 1,
name: *b"\0\0\0\0\0\0\0\0\0\0",
routine: Some(VoidRoutineWithChoice),
alpha_key: b'0'
}
];
/// Default MainMenu
#[allow(non_upper_case_globals)]
pub(super) static mut Read1Def: menu_t = menu_t {
numitems: read_e::rdthisempty1 as i32,
prevMenu: addr_of_mut!(MainMenu::MainDef),
menuItems: &raw mut ReadMenu1 as *mut menuitem_t, // Use &raw mut instead of .as_mut_ptr() to avoid illegal static mut references (Feels dirty)
routine: Some(VoidRoutine),
x: 280,
y: 185,
lastOn: 0,
};
}
// TODO: The rest of this hell!
#[allow(non_upper_case_globals)]
static mut currentMenu: *mut menu_t = std::ptr::null_mut();
#[allow(non_upper_case_globals)]
static mut menuactive: bool = false;
#[allow(non_upper_case_globals)]
static mut itemOn: i32 = 0;
#[allow(non_upper_case_globals)]
static mut whichSkull: i32 = 0;
#[allow(non_upper_case_globals)]
static mut skullAnimCounter: i32 = 0;
#[allow(non_upper_case_globals)]
pub(crate) static mut detailLevel: i32 = 0;
#[allow(non_upper_case_globals)]
pub static mut screenSize: i32 = 0;
#[allow(non_upper_case_globals)]
pub(crate) static mut screenBlocks: i32 = 0;
#[allow(non_upper_case_globals)]
static mut messageToPrint: i32 = 0;
#[allow(non_upper_case_globals)]
static mut messageString: *mut u8 = std::ptr::null_mut();
#[allow(non_upper_case_globals)]
static mut messageLastMenuActive: i32 = 0;
#[allow(non_upper_case_globals)]
static mut quickSaveSlot: i32 = -1;
#[allow(non_snake_case)]
pub fn M_Ticket() {
}
#[allow(non_snake_case)]
pub fn M_Drawer() {
}
#[allow(non_snake_case)]
pub fn M_Init() {
unsafe {
currentMenu = addr_of_mut!(MainMenu::MainDef);
menuactive = false;
itemOn = (*currentMenu).lastOn;
whichSkull = 0;
skullAnimCounter = 10;
screenSize = screenBlocks - 3;
messageToPrint = 0;
messageString = std::ptr::null_mut();
messageLastMenuActive = menuactive as i32;
quickSaveSlot = -1;
match DOOMGLOBALS::with_ref(|g| g.gamemode) {
GameMode::Commercial => {
/*
Original source code comment:
// This is used because DOOM 2 had only one HELP
// page. I use CREDIT as second page now, but
// kept this hack for educational purposes.
*/
MainMenu::MainMenu[MainMenu::main_e::readthis as usize] = MainMenu::MainMenu[MainMenu::main_e::quitdoom as usize];
MainMenu::MainDef.numitems -=1;
MainMenu::MainDef.y += 8;
NewGameMenu::NewDef.prevMenu = addr_of_mut!(MainMenu::MainDef);
ReadThis1::Read1Def.routine = Some(VoidRoutine);
ReadThis1::Read1Def.x = 330;
ReadThis1::Read1Def.y = 165;
ReadThis1::ReadMenu1[ReadThis1::read_e::rdthisempty1 as usize].routine = Some(VoidRoutineWithChoice);
},
GameMode::Shareware | GameMode::Registered => {
// TODO EpiDef.numitems--
}
_ => {
// do nothing :)
}
}
}
}
#[allow(non_snake_case)]
pub fn M_StartControlPanel() {
}

View File

@@ -1,367 +0,0 @@
use std::ptr::addr_of_mut;
use crate::d_strings;
use crate::doomtype;
use crate::hu_stuff::get_chat_macro_ptr;
use crate::m_argv::{M_CheckParm, M_GetOptionalArgumentValueByArgument, PARM_NOT_FOUND};
// static mut variable stuff
#[allow(non_upper_case_globals)]
static mut mouseSensitivity: i32 = 0;
#[allow(non_upper_case_globals)]
static mut snd_SfxVolumne: i32 = 0;
#[allow(non_upper_case_globals)]
static mut snd_MusicVolume: i32 = 0;
#[allow(non_upper_case_globals)]
static mut showMessages: i32 = 0;
#[allow(non_upper_case_globals)]
static mut usemouse: i32 = 0;
#[allow(non_upper_case_globals)]
static mut mousebfire: i32 = 0;
#[allow(non_upper_case_globals)]
static mut mousebstrafe: i32 = 0;
#[allow(non_upper_case_globals)]
static mut mousebforward: i32 = 0;
#[allow(non_upper_case_globals)]
static mut usejoystick: i32 = 0;
#[allow(non_upper_case_globals)]
static mut joybfire: i32 = 0;
#[allow(non_upper_case_globals)]
static mut joybstrafe: i32 = 0;
#[allow(non_upper_case_globals)]
static mut joybuse: i32 = 0;
#[allow(non_upper_case_globals)]
static mut joybspeed: i32 = 0;
#[allow(non_upper_case_globals)]
static mut screenblocks: i32 = 0;
#[allow(non_upper_case_globals)]
static mut detailLevel: i32 = 0;
#[allow(non_upper_case_globals)]
static mut numChannels: i32 = 0;
#[allow(non_upper_case_globals)]
static mut usegamma: i32 = 0;
/// Represents a type-safe pointer to either a numeric or string global variable
pub enum DefaultLocation {
/// Pointer to an integer(i32) value
Int(*mut i32),
/// Pointer to a String value
Str(*mut String)
}
/// Represents a type to represent the extacted default fallback value
pub enum ConfigValue {
/// Represents an integer(i32) configuration value
Int(i32),
/// Represents a String configuration value
Str(String)
}
/// Represents the name, location and default value of a configuation variable
#[repr(C)]
pub struct default_t {
/// The key used for the configuration value from the corresponding '.cfg' file
pub name: &'static str,
/// The memory location of the global variable to update
pub location: DefaultLocation,
/// The fallback value if the setting is missing from the file
pub default_value: ConfigValue
}
fn get_defaults() -> Vec<default_t> {
unsafe {
vec![
// mouse_sensitivity
default_t {
name: "mouse_sensitivity",
location: DefaultLocation::Int(addr_of_mut!(mouseSensitivity)),
default_value: ConfigValue::Int(5)
},
// snd_SfxVolumne
default_t {
name: "sfx_volume",
location: DefaultLocation::Int(addr_of_mut!(snd_SfxVolumne)),
default_value: ConfigValue::Int(8)
},
// snd_MusicVolume
default_t {
name: "snd_MusicVolumne",
location: DefaultLocation::Int(addr_of_mut!(snd_MusicVolume)),
default_value: ConfigValue::Int(8)
},
// showMessages
default_t {
name: "show_messages",
location: DefaultLocation::Int(addr_of_mut!(showMessages)),
default_value: ConfigValue::Int(1)
},
// usemouse
default_t {
name: "use_mouse",
location: DefaultLocation::Int(addr_of_mut!(usemouse)),
default_value: ConfigValue::Int(1)
},
// mousebfire
default_t {
name: "mouseb_fire",
location: DefaultLocation::Int(addr_of_mut!(mousebfire)),
default_value: ConfigValue::Int(0)
},
// mousebstrafe
default_t {
name: "mouseb_strafe",
location: DefaultLocation::Int(addr_of_mut!(mousebstrafe)),
default_value: ConfigValue::Int(1)
},
// mousebforward
default_t {
name: "mouseb_forward",
location: DefaultLocation::Int(addr_of_mut!(mousebforward)),
default_value: ConfigValue::Int(2)
},
// usejoystick
default_t {
name: "use_joystick",
location: DefaultLocation::Int(addr_of_mut!(usejoystick)),
default_value: ConfigValue::Int(0)
},
// joybfire
default_t {
name: "joyb_fire",
location: DefaultLocation::Int(addr_of_mut!(joybfire)),
default_value: ConfigValue::Int(0)
},
// joybstrafe
default_t {
name: "joyb_strafe",
location: DefaultLocation::Int(addr_of_mut!(joybstrafe)),
default_value: ConfigValue::Int(1)
},
// joybuse
default_t {
name: "joyb_use",
location: DefaultLocation::Int(addr_of_mut!(joybuse)),
default_value: ConfigValue::Int(3)
},
// joybspeed
default_t {
name: "joyb_speed",
location: DefaultLocation::Int(addr_of_mut!(joybspeed)),
default_value: ConfigValue::Int(2)
},
// screenblocks
default_t {
name: "screenblocks",
location: DefaultLocation::Int(addr_of_mut!(screenblocks)),
default_value: ConfigValue::Int(9)
},
// detailLevel
default_t {
name: "detailLevel",
location: DefaultLocation::Int(addr_of_mut!(detailLevel)),
default_value: ConfigValue::Int(0)
},
// numChannels
default_t {
name: "snd_channels",
location: DefaultLocation::Int(addr_of_mut!(numChannels)),
default_value: ConfigValue::Int(3)
},
// usegamma
default_t {
name: "usegamma",
location: DefaultLocation::Int(addr_of_mut!(usegamma)),
default_value: ConfigValue::Int(0)
},
// chatmacro0
default_t {
name: "chatmacro0",
location: DefaultLocation::Str(get_chat_macro_ptr(0)),
default_value: ConfigValue::Str(d_strings::HUSTR_CHATMACRO0.to_string())
},
// chatmacro1
default_t {
name: "chatmacro1",
location: DefaultLocation::Str(get_chat_macro_ptr(1)),
default_value: ConfigValue::Str(d_strings::HUSTR_CHATMACRO1.to_string())
},
// chatmacro2
default_t {
name: "chatmacro2",
location: DefaultLocation::Str(get_chat_macro_ptr(2)),
default_value: ConfigValue::Str(d_strings::HUSTR_CHATMACRO2.to_string())
},
// chatmacro3
default_t {
name: "chatmacro3",
location: DefaultLocation::Str(get_chat_macro_ptr(3)),
default_value: ConfigValue::Str(d_strings::HUSTR_CHATMACRO3.to_string())
},
// chatmacro4
default_t {
name: "chatmacro4",
location: DefaultLocation::Str(get_chat_macro_ptr(4)),
default_value: ConfigValue::Str(d_strings::HUSTR_CHATMACRO4.to_string())
},
// chatmacro5
default_t {
name: "chatmacro5",
location: DefaultLocation::Str(get_chat_macro_ptr(5)),
default_value: ConfigValue::Str(d_strings::HUSTR_CHATMACRO5.to_string())
},
// chatmacro6
default_t {
name: "chatmacro6",
location: DefaultLocation::Str(get_chat_macro_ptr(6)),
default_value: ConfigValue::Str(d_strings::HUSTR_CHATMACRO6.to_string())
},
// chatmacro7
default_t {
name: "chatmacro7",
location: DefaultLocation::Str(get_chat_macro_ptr(7)),
default_value: ConfigValue::Str(d_strings::HUSTR_CHATMACRO7.to_string())
},
// chatmacro8
default_t {
name: "chatmacro8",
location: DefaultLocation::Str(get_chat_macro_ptr(8)),
default_value: ConfigValue::Str(d_strings::HUSTR_CHATMACRO8.to_string())
},
// chatmacro9
default_t {
name: "chatmacro9",
location: DefaultLocation::Str(get_chat_macro_ptr(9)),
default_value: ConfigValue::Str(d_strings::HUSTR_CHATMACRO9.to_string())
}
]
}
}
#[allow(non_snake_case)]
pub fn M_WriteFile(name: &str, source: std::fs::File, length: i64) {
}
#[allow(non_snake_case)]
pub fn M_ReadFile(name: &str, buffer: Vec<u8>) {
}
#[allow(non_snake_case)]
pub fn M_ScreenShot() {
}
#[allow(non_snake_case)]
pub fn M_LoadDefaults() {
// Set to defaults
let mut defaults = get_defaults();
for item in &defaults {
unsafe {
match &item.location {
DefaultLocation::Int(ptr) => {
if let ConfigValue::Int(val) = item.default_value {
**ptr = val;
}
}
DefaultLocation::Str(ptr) => {
if let ConfigValue::Str(val) = &item.default_value {
**ptr = val.clone();
}
}
}
}
} // end iter
// load custom cfg?
let mut cfg_location = "DEFAULT.CFG";
let p = M_CheckParm("-config");
if p != PARM_NOT_FOUND {
cfg_location = M_GetOptionalArgumentValueByArgument("-config").unwrap();
}
// read contents
if let Ok(cfg_content) = std::fs::read_to_string(cfg_location) {
for line in cfg_content.lines() {
let cfg_line = line.trim();
if cfg_line.is_empty() {
continue;
}
// split the non-empty cfg line into two
if let Some((parsed_cfg_key, parsed_cfg_value)) = cfg_line.split_once(char::is_whitespace) {
let key = parsed_cfg_key.trim();
let value = parsed_cfg_value.trim();
if let Some(cfg_item) = defaults.iter_mut().find(|d| d.name == key) {
unsafe {
match &cfg_item.location {
DefaultLocation::Int(ptr) => {
if value.starts_with("0x") {
if let Ok(num) = i32::from_str_radix(value, 16) {
**ptr = num;
}
else {
println!("Unable to parse value '{}' as an integer for configuation setting '{}'", value, key);
println!("Using defaults");
}
}
else if let Ok(num) = i32::from_str_radix(value, 10) {
**ptr = num;
}
else {
println!("Unable to parse value '{}' as an integer for configuation setting '{}'", value, key);
println!("Using defaults");
}
}
DefaultLocation::Str(ptr) => {
let cleaned_str = value.trim_matches('"').to_string();
**ptr = cleaned_str;
}
}
}
}
}
}
} else {
println!("Unable to read configuation file '{}'", &cfg_location);
println!("Using defaults");
}
}
#[allow(non_snake_case)]
pub fn M_SaveDefaults() {
}
#[allow(non_snake_case)]
pub fn M_DrawText(x: i32, y: i32, direct: bool, text: &str) {
}

View File

@@ -1,15 +1,6 @@
mod d_main; mod d_main;
mod d_strings;
mod doomdef;
mod doomtype;
mod hu_stuff;
mod m_argv; mod m_argv;
mod m_menu; mod doomdef;
mod m_misc;
mod renderer;
mod v_video;
mod w_wad;
mod z_zone;
mod math; mod math;

View File

@@ -2,63 +2,46 @@
This provides fixed-point arithmetic as 32-bit 16.16 This provides fixed-point arithmetic as 32-bit 16.16
*/ */
use std::ops::ShrAssign;
use crate::doomtype::{
MININT,
MAXINT
};
pub const FRACBITS: i32 = 16; pub const FRACBITS: i32 = 16;
pub const FRACUNIT: i32 = 1 << FRACBITS; pub const FRACUNIT: i32 = 1 << FRACBITS;
pub const MININT: i32 = 0x80000000;
pub const MAXINT: i32 = 0x7fffffff;
/// Struct representing a fixed point 32-bit value /// Struct representing a fixed point 32-bit value
#[derive(Copy, Clone, PartialEq, Debug)] #[derive(Copy, Clone, PartialEq, Debug)]
#[allow(non_camel_case_types)] pub struct FixedPoint {
pub struct fixed_t {
pub value: i32, pub value: i32,
} }
impl fixed_t { impl FixedPoint {
pub const fn new(val: i32) -> Self {
fixed_t { value: val }
}
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn FixedMul(a: fixed_t, b: fixed_t) -> fixed_t { pub fn FixedMul(a: FixedPoint, b: FixedPoint) -> FixedPoint {
let value = ((a.value as u64) * (b.value as u64) >> FRACBITS) as i32; let value = ((a.value as u64) * (b.value as u64) >> FRACBITS) as i32;
fixed_t{value} FixedPoint{value}
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn FixedDiv(a: fixed_t, b: fixed_t) -> fixed_t { pub fn FixedDiv(a: FixedPoint, b: FixedPoint) -> FixedPoint {
if (i32::abs(a.value) >> 14) >= i32::abs(b.value) { if (i32::abs(a.value) >> 14) >= i32::abs(b.value) {
if a.value^b.value == 0 { if a.value^b.value == 0 {
fixed_t{value: MININT}; FixedPoint{value: MININT};
} }
else { else {
fixed_t{value: MAXINT}; FixedPoint{value: MAXINT};
} }
} }
fixed_t::FixedDiv2(a,b) FixedPoint::FixedDiv2(a,b)
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn FixedDiv2(a: fixed_t, b: fixed_t) -> fixed_t { pub fn FixedDiv2(a: FixedPoint, b: FixedPoint) -> FixedPoint {
let c: f64 = ((a.value as f64) / (b.value as f64)) * FRACUNIT as f64; let c: f64 = ((a.value as f64) / (b.value as f64)) * FRACUNIT as f64;
if c >= 2147483648.0 || c < -2147483648.0 { if c >= 2147483648.0 || c < -2147483648.0 {
panic!("FixedDiv: divide by zero"); panic!("FixedDiv: divide by zero");
} }
fixed_t { value: c as i32 } FixedPoint { value: c as i32 }
} }
} }
impl ShrAssign<i32> for fixed_t {
fn shr_assign(&mut self, rhs: i32) {
// Shift the underlying wrapped i32 value directly
self.value >>= rhs;
}
}

View File

@@ -1,5 +1,3 @@
mod m_fixed; // pub mod m_fixed;
pub use m_fixed::fixed_t; // pub use m_fixed::FixedPoint;
pub use m_fixed::FRACUNIT;
pub use m_fixed::FRACBITS;

View File

@@ -1,130 +0,0 @@
// Main entry to Render stuff
// i.e r_main c/h
mod r_data;
mod r_defs;
mod r_plane;
use crate::doomdef::SCREENWIDTH;
use crate::math::{fixed_t, FRACUNIT};
use crate::m_menu::{detailLevel, screenBlocks};
use r_data::R_InitData;
use r_defs::lighttable_t;
use r_plane::R_InitPlanes;
// Light constants
// Orignal source comment: Now why not 32 levels here?
pub const LIGHTLEVELS: i32 = 16;
pub const MAXLIGHTSCALE: i32 = 48;
pub const LIGHTSCALESHIFT: i32 = 12;
pub const MAXLIGHTZ: i32 = 128;
pub const LIGHTZSHIFT: i32 = 20;
#[allow(non_upper_case_globals)]
pub static mut scalelight: [[*mut lighttable_t; MAXLIGHTSCALE as usize]; LIGHTLEVELS as usize] =
[[std::ptr::null_mut(); MAXLIGHTSCALE as usize]; LIGHTLEVELS as usize];
#[allow(non_upper_case_globals)]
pub static mut scalelightfixed: [*mut lighttable_t; MAXLIGHTSCALE as usize] =
[std::ptr::null_mut(); MAXLIGHTSCALE as usize];
#[allow(non_upper_case_globals)]
pub static mut zlight: [[*mut lighttable_t; MAXLIGHTZ as usize]; LIGHTLEVELS as usize] =
[[std::ptr::null_mut(); MAXLIGHTZ as usize]; LIGHTLEVELS as usize];
/// R_InitLightTables
/// Only inits the zlight table,
/// because the scalelight table changes with view size.
pub const DISTMAP:i32 = 2;
/// Number of diminishing brightness levels.
/// There a 0-31, i.e. 32 LUT in the COLORMAP lump.
pub const NUMCOLORMAPS: i32 = 32;
#[allow(non_upper_case_globals)]
static mut viewcos: fixed_t = fixed_t{value: 0};
#[allow(non_upper_case_globals)]
static mut viewsin: fixed_t = fixed_t{value: 0};
#[allow(non_upper_case_globals)]
static mut setsizeneeded: bool = false;
#[allow(non_upper_case_globals)]
static mut setblocks: i32 = 0;
#[allow(non_upper_case_globals)]
static mut setdetail: i32 = 0;
#[allow(non_snake_case)]
fn R_InitPointToAngle() {
// this is unused in the original source
// we get this data from tables
}
#[allow(non_snake_case)]
fn R_InitTables() {
// this is unused in the original source
// we get this data from tables
}
#[allow(non_snake_case)]
fn R_InitLightTables() {
let mut startmap: i32;
let mut scale: fixed_t;
let mut level: i32;
for i in 0..(LIGHTLEVELS as usize) {
startmap = ((LIGHTLEVELS - 1 - (i as i32)) * 2) * NUMCOLORMAPS/LIGHTLEVELS;
for j in 0..(MAXLIGHTZ as usize) {
scale = fixed_t::FixedDiv(fixed_t{value: (SCREENWIDTH/2*FRACUNIT)}, fixed_t{value: ((j as i32) + 1) << LIGHTZSHIFT});
scale >>= LIGHTSCALESHIFT;
level = startmap - scale.value/DISTMAP;
level = level.clamp(0, NUMCOLORMAPS - 1);
// zlight[i][j] = colormaps + level * 256; //TODO: Implement zlight
}
}
}
/* // TODO: Implement player_t
pub fn R_RenderPlayerView(player: *const player_t) {
}
*/
#[allow(non_snake_case)]
pub fn R_Init() {
R_InitData();
println!("R_InitData");
R_InitPointToAngle();
println!("R_InitPointToAngle");
R_InitTables();
// viewwidth / viewheight / detailLevel are set by the defaults
println!("R_InitTables");
unsafe {R_SetViewSize(screenBlocks, detailLevel);}
R_InitPlanes();
println!("R_InitPlanes");
R_InitLightTables();
println!("R_InitLightTables");
//R_InitSkyMap();
println!("R_InitSkyMap");
//R_InitTranslationTables();
println!("R_InitTranslationTables")
// framecount = 0;
}
#[allow(non_snake_case)]
pub fn R_SetViewSize(blocks: i32, detail: i32) {
unsafe {
setsizeneeded = true;
setblocks = blocks;
setdetail = detail;
}
}

View File

@@ -1,60 +0,0 @@
#[allow(non_snake_case)]
fn R_InitTextures() {
}
#[allow(non_snake_case)]
fn R_InitFlats() {
}
#[allow(non_snake_case)]
fn R_InitSpriteLumps() {
}
#[allow(non_snake_case)]
fn R_InitColormaps() {
}
#[allow(non_snake_case)]
pub fn R_GetColumn (tex: i32, col: i32) {
}
/// R_InitData
/// Locates all the lumps that will be used by all views
/// This must be called after `W_Init`
#[allow(non_snake_case)]
pub fn R_InitData() {
R_InitTextures();
println!("InitTextures");
R_InitFlats();
println!("InitFlats");
R_InitSpriteLumps();
println!("InitSprites");
R_InitColormaps();
println!("InitColormaps");
}
#[allow(non_snake_case)]
pub fn R_PrecacheLevel() {
}
#[allow(non_snake_case)]
pub fn R_FlatNumForName(name: &str) -> i32 {
1
}
#[allow(non_snake_case)]
pub fn R_TextureNumForName(name: &str) -> i32 {
1
}
#[allow(non_snake_case)]
pub fn R_CheckTextureNumForName(name: &str) -> i32 {
1
}

View File

@@ -1,441 +0,0 @@
use crate::doomdef::SCREENWIDTH;
use crate::m_fixed::{fixed_t};
use crate::tables::angle_t;
// TODO: Implement d_think.h and p_mobj.h
/// Original Source comment:
/// Silhouette, needed for clipping Segs (mainly)
/// and sprites representing things.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(i32)]
pub enum Silhouette {
None = 0,
Bottom = 1,
Top = 2,
Both = 3,
}
pub const MAXDRAWSEGS: i32 = 256;
/// Original source comment
/// This could be wider for >8 bit display.
/// Indeed, true color support is posibble
/// precalculating 24bpp lightmap/colormap LUT.
/// from darkening PLAYPAL to all black.
/// Could even us emore than 32 levels.
type lighttable_t = u8;
/// Original Source comment:
/// Your plain vanilla vertex.
/// Note: transformed values not buffered locally,
/// like some DOOM-alikes ("wt", "WebView") did.
#[derive(Copy, Clone)]
pub struct vertex_t {
x: fixed_t,
y: fixed_t
}
/// Original Source comment:
/// Each sector has a degenmobj_t in its center
/// for sound origin purposes.
/// I suppose this does not handle sound from
/// moving objects (doppler), because
/// position is prolly just buffered, not
/// updated.
pub struct degenmobj_t {
//TODO: implement d_think.h
// thinker: thinker_t,
x: fixed_t,
y: fixed_t,
z: fixed_t
}
/// Sectors represent a distinct, closed polygon area on the map with uniform
/// floor heights, ceiling heights, lighting levels, and floor/ceiling textures.
/// They also serve as containers for gameplay entities (`mobj_t`).
/// Original Source comment:
/// The SECTORS record, at runtime.
/// Stores things/mobjs.
pub struct sector_t {
/// Height of the floor
pub(crate) floorheight: fixed_t,
/// Height of the ceiling
pub(crate) ceilingheight: fixed_t,
/// Texture index applied to the floor surface
pub(crate) floorpic: i16,
/// Texture index applied to the ceiling surface
pub(crate) ceilingpic: i16,
/// The current brightness level for the sector
pub(crate) lightlevel: i16,
/// Sector type/behaviour flags (e.g sewage / lava damaging floors)
pub(crate) special: i16,
/// Unique ID tag used by linedef triggers to identify and manipluate this sector
pub(crate) tag: i16,
/// Sound propagation state variable used during sound traversal calculations.
/// Values: 0 = untraversed, 1 or 2 = sound lines - 1.
pub(crate) soundtraversed: i32,
//TODO: mobj_t implementation (p_mobj.h)
/// Pointer to the map object (`mobj_t`) that generated a sound in this sector, or null.
pub(crate) soundtarget: *mut mobj_t,
/// A bounding box `[ymin, ymax, xmin, xmax]` mapping blocks for height changes and collisions.
pub(crate) blockbox: [i32; 4],
/// simplified, stationary map object representing the central origin point for sound playback.
pub(crate) soundorg: degenmobj_t,
/// A frame check counter variable used to avoid re-processing this sector multiple times per tick.
pub(crate) validcount: i32,
/// A dynamic collection of all map objects currently inside this sector.
/// TODO: Change back to *mut mobj_t linked list later
pub(crate) thinglist: Vec<mobj_t>,
/// A generic raw pointer to an active thinker struct (e.g., `plat_t`, `ceiling_t`) for handling moving parts
pub(crate) specialdata: *mut (),
/// The total number of linedefs that form the boundaries of this sector.
pub(crate) linecount: i32,
/// A raw pointer to an array of pointers pointing to the `line_s` (linedef) structs that border this sector.
pub(crate) lines: *mut *mut line_s,
}
/// Linedefs are made up of either one or two sidedefs (front and back).
/// A sidedef contains texture alignment offsets, texture indices, and
/// points directly to the sector it faces.
pub struct sidedef_t {
/// Horizontal alignment offset added to the calculated texture column.
pub(crate) textureoffset: fixed_t,
/// Vertical alignment offset added to the calculated texture top.
pub(crate) rowoffset: fixed_t,
// texture indices
/// The index of the upper wall texture (above the ceiling gap).
pub(crate) toptexture: i16,
/// The index of the lower wall texture (below the floor gap).
pub(crate) bottomtexture: i16,
/// The index of the middle wall texture (used on single-sided walls or windows).
pub(crate) midtexture: i16,
/// A raw pointer to the sector this specific side faces.
pub(crate) sector: *mut sector_t,
}
/// The line slope classification type.
///
/// Used by the collision and rendering engines to optimize intersection
/// checks and line-of-sight tracking based on the orientation of a wall line.
#[derive(Copy, Clone)]
enum slopetype_t {
/// A perfectly horizontal line (dy == 0).
ST_HORIZONTAL,
/// A perfectly vertical line (dx == 0).
ST_VERTICAL,
/// A line with a positive slope rising from bottom-left to top-right (dx and dy have the same sign).
ST_POSITIVE,
/// A line with a negative slope falling from top-left to bottom-right (dx and dy have opposite signs).
ST_NEGATIVE
}
/// Linedefs form the walls and structural geometry of a map. They contain
/// pointers to their start/end vertices, front/back siding data, physical
/// triggers (`special`), and precalculated bounding extents to assist the physics engine.
pub struct linedef_t {
/// Raw pointer to the starting vertex (v1) of the wall.
pub(crate) v1: *mut vertex_t,
/// Raw pointer to the ending vertex (v2) of the wall.
pub(crate) v2: *mut vertex_t,
/// Precalculated horizontal delta value (v2.x - v1.x) for quick side-of-line checking.
pub(crate) dx: fixed_t,
/// Precalculated vertical delta value (v2.y - v1.y) for quick side-of-line checking.
pub(crate) dy: fixed_t,
/// Configuration flags handling behavior (e.g., solid wall, blocks monsters, secret map wall).
pub(crate) flags: i16,
/// The linedef activation type/trigger function index (e.g., doors, teleporters, lifts).
pub(crate) special: i16,
/// A unique ID tag matching sector targets to process execution triggers.
pub(crate) tag: i16,
/// Sidedef lookups. `sidenum[0]` is the front side; `sidenum[1]` is the back side (or -1 if single-sided).
pub(crate) sidenum: [i16; 2],
/// Bounding box layout `[ymin, ymax, xmin, xmax]` representing the full grid extent of the line.
pub(crate) bbox: [fixed_t; 4],
/// Slope classification used to optimize physics intersection and visibility clipping loops.
pub(crate) slopetype: slopetype_t,
/// Raw pointer to the sector directly in front of this linedef's first side.
pub(crate) frontsector: *mut sector_t,
/// Raw pointer to the sector behind this linedef's second side, or null if single-sided.
pub(crate) backsector: *mut sector_t,
/// A frame counter lookup variable used to avoid parsing or processing this line multiple times per tick.
pub(crate) validcount: i32,
/// A generic raw pointer to a running thinker action layout (e.g., standard scrolling wall textures).
pub(crate) specialdata: *mut (),
}
/// Subsectors are the structural leaves at the bottom of the BSP tree.
/// They represent smaller, guaranteed-convex sub-polygons carved out of a
/// larger sector, defined by a sequential slice of rendering lines (`seg_t`).
pub struct subsectordef_t {
/// A raw pointer to the parent sector that this subsector belongs to.
pub(crate) sector: *mut sector_t,
/// The total number of consecutive line segments (`seg_t`) that form this subsector.
pub(crate) numlines: i16,
/// The starting array index inside the global `segs` array for this subsector's lines.
pub(crate) firstline: i16,
}
/// Segs are clipped slices of linedefs generated by the node builder.
/// The rendering engine processes them in strict front-to-back order
/// using the BSP tree to draw wall surfaces without sorting artifacts.
pub struct segdef_t {
/// Raw pointer to the starting vertex (v1) of this specific segment.
pub(crate) v1: *mut vertex_t,
/// Raw pointer to the ending vertex (v2) of this specific segment.
pub(crate) v2: *mut vertex_t,
/// The distance offset along the original linedef where this segment begins.
pub(crate) offset: fixed_t,
/// The absolute binary angle of the segment (represented as a 32-bit unsigned integer).
pub(crate) angle: angle_t,
/// Raw pointer to the sidedef structure containing the texture data for this segment.
pub(crate) sidedef: *mut sidedef_t,
/// Raw pointer to the parent linedef structure this segment was split out from.
pub(crate) linedef: *mut linedef_t,
/// Raw pointer to the sector directly in front of this segment.
pub(crate) frontsector: *mut sector_t,
/// Raw pointer to the sector behind this segment, or null if it belongs to a solid one-sided wall.
pub(crate) backsector: *mut sector_t,
}
/// Nodes form the internal branching skeleton of the map's 3D visibility tree.
/// Each node acts as a cutting plane line segment that splits a sub-region into
pub struct node_t {
/// Starting X coordinate of the division splitter line.
pub(crate) x: fixed_t,
/// Starting Y coordinate of the division splitter line.
pub(crate) y: fixed_t,
/// Horizontal delta length of the division splitter vector.
pub(crate) dx: fixed_t,
/// Vertical delta length of the division splitter vector.
pub(crate) dy: fixed_t,
/// Precalculated bounding boxes [ymin, ymax, xmin, xmax] for the right [0] and left [1] child spaces.
pub(crate) bbox: [[FixedT; 4]; 2],
/// References to left [0] and right [1] children. If highest bit (0x8000) is set, it targets a subsector_t index.
pub(crate) children: [u16; 2],
}
/// A runtime record of a drawn wall segment.
/// Stores clipping and scaling metadata to correctly occlude and scale sprites behind it.
pub struct drawseg_t {
/// Pointer to the line segment being rendered (usually seg_t).
pub(crate) curline: *mut sector_t,
/// Starting horizontal screen column (left boundary).
pub(crate) x1: i32,
/// Ending horizontal screen column (right boundary).
pub(crate) x2: i32,
/// Initial texture scale at the starting column (x1).
pub(crate) scale1: fixed_t,
/// Final texture scale at the ending column (x2).
pub(crate) scale2: fixed_t,
/// Amount to change the texture scale per horizontal pixel step.
pub(crate) scalestep: fixed_t,
/// Silhouette type flags handling sprite occlusion (e.g., SIL_BOTTOM, SIL_TOP).
pub(crate) silhouette: i32,
/// Maximum floor height boundary for bottom silhouette clipping.
pub(crate) bsilheight: fixed_t,
/// Minimum ceiling height boundary for top silhouette clipping.
pub(crate) tsilheight: fixed_t,
/// Pointer to the screen column array managing top clipping bounds for sprites.
pub(crate) sprtopclip: *mut u16,
/// Pointer to the screen column array managing bottom clipping bounds for sprites.
pub(crate) sprbottomclip: *mut u16,
/// Pointer to the column offset array used for rendering masked textures.
pub(crate) maskedtexturecol: *mut u16,
}
/// A hardware-agnostic 2D picture or graphic asset.
/// Uses a column-oriented format to optimize rapid vertical stretching and scaling.
pub struct patch_t {
/// Total width of the graphic patch in pixels.
pub(crate) width: u16,
/// Total height of the graphic patch in pixels.
pub(crate) height: u16,
/// Horizontal offset relative to the origin (used to center weapon and sprite frames).
pub(crate) leftoffset: u16,
/// Vertical offset relative to the origin (used to center weapon and sprite frames).
pub(crate) topoffset: u16,
/// Array of byte offsets from the start of the patch to the start of each vertical pixel column.
/// only [width] used
// the [0] is &columnofs[width]
pub(crate) columnofs: [i32; 8],
}
/// A visible sprite entry prepared for rendering.
/// Tracks screen bounds, scaling, and clipping parameters for a partly visible map object.
pub struct vissprite_t {
/// Pointer to the previous sprite in the doubly linked list.
pub(crate) prev: *mut vissprite_t,
/// Pointer to the next sprite in the doubly linked list.
pub(crate) next: *mut vissprite_t,
/// Starting horizontal screen column (left boundary).
pub(crate) x1: i32,
/// Ending horizontal screen column (right boundary).
pub(crate) x2: i32,
/// Global X coordinate used for line-side visibility checks.
pub(crate) gx: fixed_t,
/// Global Y coordinate used for line-side visibility checks.
pub(crate) gy: fixed_t,
/// Global bottom Z coordinate used for silhouette clipping calculations.
pub(crate) gz: fixed_t,
/// Global top Z coordinate used for silhouette clipping calculations.
pub(crate) gzt: fixed_t,
/// Horizontal texture offset fraction at screen column x1.
pub(crate) startfrac: fixed_t,
/// Scale factor of the sprite relative to its distance from the camera.
pub(crate) scale: fixed_t,
/// Horizontal step scale factor (inverted and negative if the sprite is flipped).
pub(crate) xiscale: fixed_t,
/// Vertical texture alignment midpoint coordinate.
pub(crate) texturemid: fixed_t,
/// The index of the graphic patch asset being rendered.
pub(crate) patch: i32,
/// Pointer to the color lookup array handling lighting, shadows, and full-brightness frames.
pub(crate) colormap: *mut lighttable_t,
/// Cached copy of the parent map object's physics and state flags.
pub(crate) mobjflags: i32,
}
/// Animation frame data for a sprite object.
/// Tracks raw graphic lump IDs and horizontal flip bits for all 8 view rotations.
#[derive(Copy, Clone)]
pub struct spriteframe_t {
/// True if the sprite has directional rotation variants; false if it looks identical from all sides.
pub(crate) rotate: bool,
/// WAD graphic lump indices representing the image assets for view angles 0 to 7.
pub(crate) lump: [i16; 8],
/// Bitmask flags (1 = mirror image horizontally) applied to view angles 0 to 7 to save space.
pub(crate) flip: [u8; 8],
}
/// A top-level sprite asset container managing a series of sequential animation frames.
pub struct spritedef_t {
/// Total number of animation frames allocated for this sprite sequence.
pub(crate) numframes: i32,
/// Raw pointer to the array of frame records tracking rotation and asset data.
pub(crate) spriteframes: *mut spriteframe_t,
}
/// A floor or ceiling polygon segment prepared for flat horizontal texture mapping.
/// Merges drawing spans to prevent visible gaps or layout cracking during screen refresh.
pub struct visplane_t {
/// Absolute height level of the floor or ceiling plane in fixed-point space.
pub(crate) height: fixed_t,
/// WAD graphic texture flat index applied to the surface.
pub(crate) picnum: i32,
/// Calculated light/brightness visibility level of the flat polygon plane.
pub(crate) lightlevel: i32,
/// The leftmost horizontal screen column index bound for drawing.
pub(crate) minx: i32,
/// The rightmost horizontal screen column index bound for drawing.
pub(crate) maxx: i32,
/// Memory padding byte mimicking historical x-1 lookups.
pub(crate) pad1: u8,
/// Dynamic horizontal boundary array tracing top rendering margins across columns.
pub(crate) top: [u8; SCREENWIDTH],
/// Memory padding byte mimicking historical array bounds checks.
pub(crate) pad2: u8,
/// Memory padding byte mimicking historical array bounds checks.
pub(crate) pad3: u8,
/// Dynamic horizontal boundary array tracing bottom rendering margins across columns.
pub(crate) bottom: [u8; SCREENWIDTH],
/// Memory padding byte mimicking historical x+1 lookups.
pub(crate) pad4: u8,
}

View File

@@ -1,39 +0,0 @@
#[allow(non_snake_case)]
pub fn R_InitPlanes() {
// Original source comment
// doh!
// wtf?
}
#[allow(non_snake_case)]
pub fn R_ClearPlanes() {
}
#[allow(non_snake_case)]
pub fn R_MapPlane (y: i32, x1: i32, x2: i32) {
}
#[allow(non_snake_case)]
pub fn R_MakeSpans(x: i32, t1: i32, b1: i32, t2: i32, b2: i32) {
}
#[allow(non_snake_case)]
pub fn R_DrawPlanes() {
}
/* TODO: Implement visplane_t
#[allow(non_snake_case)]
pub fn R_FindPlane(height: fixed_t, picnum: i32, lightlevel: i32) -> *const visplane_t {
}
#[allow(non_snake_case)]
pub fn R_CheckPlane(pl: *const visplane_t, start: i32, stop: i32) -> *const visplane_t {
}
*/

File diff suppressed because it is too large Load Diff

View File

@@ -1,43 +0,0 @@
use crate::doomdef::{SCREENHEIGHT, SCREENWIDTH};
use crate::doomtype;
pub const CENTERY: i32 = SCREENHEIGHT / 2;
// static var stuff
#[allow(non_upper_case_globals)]
static mut screens: [[u8; (SCREENWIDTH*SCREENHEIGHT) as usize]; 5] = [[0u8; (SCREENWIDTH*SCREENHEIGHT) as usize]; 5];
#[allow(non_snake_case)]
pub fn V_Init() {
// Do nothing :)
// the memory is already allocated
}
#[allow(non_snake_case)]
pub fn V_CopyRect(srcx: i32, srcy: i32, srcscrn: i32, width: i32, height: i32, destx: i32, desty: i32, destscrn: i32) {
}
/*
TODO: Implement "r_data"
#[allow(non_snake_case)]
pub fn V_DrawPatch(x: i32, y: i32, scrn: i32, patch: Vec<patch_t>) {
}
#[allow(non_snake_case)]
pub fn V_DrawPatchDirect(x: i32, y: i32, scrn: i32, patch: Vec<patch_t>) {
}
*/
#[allow(non_snake_case)]
pub fn V_GetBlock(x: i32, y: i32, scrn: i32, width: i32, height: i32, dest: Vec<u8>) {
}
#[allow(non_snake_case)]
pub fn V_MarkRect(x: i32, y: i32, width: i32, height: i32) {
}

View File

@@ -1,235 +0,0 @@
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() {
}

View File

@@ -1,165 +0,0 @@
/// Memory allocator stuff
/// Compared to the original source, this will be some what "lean n' mean"
use std::cell::RefCell;
use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
/// The PurgeTags (PUs)
/// Tags < 100 are not overwritten untill freed
pub enum PurgeTag {
/// Static the entire execution time
Static = 1,
/// Static while playing
Sound = 2,
/// static while playing
Music = 3,
/// Original source comment: anything else dave wants static
Dave = 4,
/// static until level exit
Level = 50,
/// static for special thinkers in a level
LevSpec = 51,
// Tags >= 100 are "purgable" whenever needed
PurgeLevel = 100,
Cache = 101,
}
/// Provides metadata on
struct AllocMeta {
/// The size of the allocation
size: usize,
/// The PU tag associated with the allocation
tag: i32,
/// A pointer to the caller's tracking pointer, cleared automatically upon freeing
user: *mut *mut u8,
}
thread_local! {
// We promise not to be naughty and access this from another thread :)
/// Mapping from pointers (as usize) to the correspond AllocationMeta
static REGISTRY: RefCell<HashMap<usize, AllocMeta>> = RefCell::new(HashMap::new());
}
// Helper method that we can use to access the registry
fn with_registry<F, R>(f: F) -> R
where
F: FnOnce(&mut HashMap<usize, AllocMeta>) -> R
{
REGISTRY.with(|registry| f(&mut *registry.borrow_mut()))
}
#[allow(non_snake_case)]
/// Initalized the Zone memory allocator sub-system
pub fn Z_Init() {
// do nothing, we get lazy init of the registry.
}
#[allow(non_snake_case)]
/// Allocate a contiguous chunk of zeroed memory from the zone allocator
/// # Safety
/// This function returns a raw pointer that bypasses Rust's automatic memory
/// tracking. The returned memory must be manually reclaimed using `Z_Free`.
pub unsafe fn Z_Malloc(size: usize, tag: i32, user: *mut *mut u8) -> *mut u8 {
let mut buffer = vec![0u8; size];
let ptr = buffer.as_mut_ptr();
// ensures Rust does not drop the buffer at the end of this block
std::mem::forget(buffer);
// Update the engine's tracking pointer if one was provided
if !user.is_null() {
unsafe {
*user = ptr;
}
}
// Save allocation details using the pointer address as the key
with_registry(|map| {
map.insert(ptr as usize, AllocMeta { size, tag, user });
});
ptr
}
#[allow(non_snake_case)]
/// Reclaims and frees a allocation from Z_Malloc
/// # Safety
/// The provided pointer must point to a valid allocation tracked by the registry.
/// Passing an invalid or already freed pointer can result in undefined behavior
pub unsafe fn Z_Free(ptr: *mut u8) {
if ptr.is_null() {
return;
}
let removed = with_registry(|map| map.remove(&(ptr as usize)));
if let Some(meta) = removed {
// Clear the caller's tracking pointer to prevent use-after-free
if !meta.user.is_null() {
unsafe {
*meta.user = std::ptr::null_mut();
}
}
// re-build the vector so Rust can drop it
unsafe {
let _dropped_vec = Vec::from_raw_parts(ptr, meta.size, meta.size);
}
}
}
#[allow(non_snake_case)]
/// Frees all memory allocations between the specific lifetime PU tags.
/// # Safety
/// All pointers tracked within this tag boundary are invalidated and deallocate
pub unsafe fn Z_FreeTags(low_tag: i32, high_tag: i32) {
// get all of the allocations to free
let tags_to_free: Vec<usize> = with_registry(|map| {
map.iter()
.filter(|(_, meta)| meta.tag >= low_tag && meta.tag <= high_tag)
.map(|(ptr_addr,_)| *ptr_addr)
.collect()
});
// remove each pointer returned from the map and drop the memory
for ptr_addr in tags_to_free {
let removed_ptr = with_registry(|map| map.remove(&ptr_addr));
if let Some(meta) = removed_ptr {
let p = ptr_addr as *mut u8;
unsafe {
// clear caller tracking pointer to preven use after free
if !meta.user.is_null() {
*meta.user = std::ptr::null_mut();
}
let _dropped_vec = Vec::from_raw_parts(p, meta.size, meta.size);
}
}
}
}
// Internal ChangeTag function
#[allow(non_snake_case)]
fn Z_ChangeTagInternal(ptr: *mut u8, tag: i32) {
if ptr.is_null() {
return;
}
with_registry(|map| {
if let Some(meta) = map.get_mut(&(ptr as usize)) {
meta.tag = tag;
}
})
}
/// Modifies the lifetime tag of an active allocation.
///
/// # Safety
/// The provided pointer must point to a valid allocation tracked by the registry
#[allow(non_snake_case)]
pub unsafe fn Z_ChangeTag(ptr: *mut u8, tag: i32) {
// removes the original helper macro from the original C, we don't need withcraft here
Z_ChangeTagInternal(ptr, tag);
}