Compare commits
5 Commits
feature/im
...
feature/im
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
313fb3c577 | ||
|
|
dad59e261d | ||
|
|
93a3c8548e | ||
|
|
0a979dd8e0 | ||
|
|
dd7573a807 |
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@@ -16,7 +16,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"args": [
|
"args": [
|
||||||
"./WADS/DOOM.WAD", "-dev", "-nomonsters", "-skill", "3"
|
"./WADS/DOOM.WAD", "-dev", "-nomonsters", "-skill", "3", "-config", "DEFAULT.CFG"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceFolder}"
|
"cwd": "${workspaceFolder}"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,4 +3,8 @@ name = "RustyDoom"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = []
|
||||||
|
french = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
46
DEFAULT.CFG
Normal file
46
DEFAULT.CFG
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
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
|
||||||
11
README.md
11
README.md
@@ -1,5 +1,12 @@
|
|||||||
# RustyDoom
|
# RustyDoom
|
||||||
|
|
||||||
A rust version of the original Doom.
|
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)
|
||||||
|
|
||||||
This is more of a learning exercise than something good!
|
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 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
|
||||||
|
|||||||
@@ -8,8 +8,13 @@ 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::w_wad::{W_CheckNumForName, W_InitMultipleFiles};
|
||||||
|
use crate::z_zone::Z_Init;
|
||||||
|
|
||||||
use crate::doomdef::{
|
use crate::doomdef::{
|
||||||
VERSION,
|
VERSION,
|
||||||
@@ -399,18 +404,16 @@ 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(DOOMGLOBALS::with_ref(|g| g.wadfiles.clone())); // we are loading so how cares about a borrow
|
||||||
|
|
||||||
@@ -465,14 +468,15 @@ 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();
|
||||||
|
|
||||||
|
|||||||
638
src/d_strings/d_english/mod.rs
Normal file
638
src/d_strings/d_english/mod.rs
Normal file
@@ -0,0 +1,638 @@
|
|||||||
|
/// 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";
|
||||||
3
src/d_strings/french/mod.rs
Normal file
3
src/d_strings/french/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/// French Language string constants
|
||||||
|
///
|
||||||
|
/// NOT IMPLEMENTED "C'est injuste envers les Français !"
|
||||||
20
src/d_strings/mod.rs
Normal file
20
src/d_strings/mod.rs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#[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;
|
||||||
|
|
||||||
@@ -1,8 +1,38 @@
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
/// 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 {
|
||||||
10
src/doomtype/mod.rs
Normal file
10
src/doomtype/mod.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
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;
|
||||||
99
src/hu_stuff/mod.rs
Normal file
99
src/hu_stuff/mod.rs
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
/// 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() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
323
src/m_menu/mod.rs
Normal file
323
src/m_menu/mod.rs
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
// 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() {
|
||||||
|
|
||||||
|
}
|
||||||
367
src/m_misc/mod.rs
Normal file
367
src/m_misc/mod.rs
Normal file
@@ -0,0 +1,367 @@
|
|||||||
|
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) {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +1,15 @@
|
|||||||
mod d_main;
|
mod d_main;
|
||||||
|
mod d_strings;
|
||||||
mod doomdef;
|
mod doomdef;
|
||||||
|
mod doomtype;
|
||||||
|
mod hu_stuff;
|
||||||
mod m_argv;
|
mod m_argv;
|
||||||
|
mod m_menu;
|
||||||
|
mod m_misc;
|
||||||
|
mod renderer;
|
||||||
|
mod v_video;
|
||||||
mod w_wad;
|
mod w_wad;
|
||||||
|
mod z_zone;
|
||||||
mod math;
|
mod math;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,46 +2,63 @@
|
|||||||
|
|
||||||
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)]
|
||||||
pub struct FixedPoint {
|
#[allow(non_camel_case_types)]
|
||||||
|
pub struct fixed_t {
|
||||||
pub value: i32,
|
pub value: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FixedPoint {
|
impl fixed_t {
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
pub const fn new(val: i32) -> Self {
|
||||||
pub fn FixedMul(a: FixedPoint, b: FixedPoint) -> FixedPoint {
|
fixed_t { value: val }
|
||||||
let value = ((a.value as u64) * (b.value as u64) >> FRACBITS) as i32;
|
|
||||||
FixedPoint{value}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn FixedDiv(a: FixedPoint, b: FixedPoint) -> FixedPoint {
|
pub fn FixedMul(a: fixed_t, b: fixed_t) -> fixed_t {
|
||||||
|
let value = ((a.value as u64) * (b.value as u64) >> FRACBITS) as i32;
|
||||||
|
fixed_t{value}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn FixedDiv(a: fixed_t, b: fixed_t) -> fixed_t {
|
||||||
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 {
|
||||||
FixedPoint{value: MININT};
|
fixed_t{value: MININT};
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
FixedPoint{value: MAXINT};
|
fixed_t{value: MAXINT};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FixedPoint::FixedDiv2(a,b)
|
fixed_t::FixedDiv2(a,b)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn FixedDiv2(a: FixedPoint, b: FixedPoint) -> FixedPoint {
|
pub fn FixedDiv2(a: fixed_t, b: fixed_t) -> fixed_t {
|
||||||
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");
|
||||||
}
|
}
|
||||||
FixedPoint { value: c as i32 }
|
fixed_t { 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
// pub mod m_fixed;
|
mod m_fixed;
|
||||||
|
|
||||||
// pub use m_fixed::FixedPoint;
|
pub use m_fixed::fixed_t;
|
||||||
|
pub use m_fixed::FRACUNIT;
|
||||||
|
pub use m_fixed::FRACBITS;
|
||||||
130
src/renderer/mod.rs
Normal file
130
src/renderer/mod.rs
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
60
src/renderer/r_data.rs
Normal file
60
src/renderer/r_data.rs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
#[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
|
||||||
|
}
|
||||||
441
src/renderer/r_defs.rs
Normal file
441
src/renderer/r_defs.rs
Normal file
@@ -0,0 +1,441 @@
|
|||||||
|
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,
|
||||||
|
}
|
||||||
39
src/renderer/r_plane.rs
Normal file
39
src/renderer/r_plane.rs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#[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 {
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
1843
src/tables/mod.rs
Normal file
1843
src/tables/mod.rs
Normal file
File diff suppressed because it is too large
Load Diff
43
src/v_video/mod.rs
Normal file
43
src/v_video/mod.rs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
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) {
|
||||||
|
|
||||||
|
}
|
||||||
165
src/z_zone/mod.rs
Normal file
165
src/z_zone/mod.rs
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
/// 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);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user