From 9dda6bd84fe38cc368e56b1c37544a6081ea1cd0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 22 May 2026 18:55:14 +0000 Subject: [PATCH 1/2] Initial plan From b5e37827cfa93ab22baa1b9fce19ed34dc3c5cc8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 22 May 2026 19:04:37 +0000 Subject: [PATCH 2/2] refactor: replace cstr! macro calls with c string literals Agent-Logs-Url: https://github.com/sunsided/room/sessions/fb9747f6-a968-4601-ad75-8152c8e345a4 Co-authored-by: sunsided <495335+sunsided@users.noreply.github.com> --- room/src/doom/d_iwad.rs | 79 ++++----- room/src/doom/d_mode.rs | 30 ++-- room/src/doom/dstrings.rs | 48 ++---- room/src/doom/f_finale.rs | 145 ++++++++-------- room/src/doom/hu_stuff.rs | 336 ++++++++++++++++++-------------------- room/src/doom/m_argv.rs | 6 +- room/src/doom/p_spec.rs | 62 +++---- room/src/doom/r_draw.rs | 29 ++-- room/src/doom/statdump.rs | 12 +- room/src/doom/w_main.rs | 13 +- 10 files changed, 336 insertions(+), 424 deletions(-) diff --git a/room/src/doom/d_iwad.rs b/room/src/doom/d_iwad.rs index d8c62704..9dcd8ca0 100644 --- a/room/src/doom/d_iwad.rs +++ b/room/src/doom/d_iwad.rs @@ -38,17 +38,6 @@ const DIR_SEPARATOR: c_char = b'/' as c_char; /// C string-joining functions. const DIR_SEPARATOR_S: &[u8] = b"/\0"; -/// Convenience macro that appends a null terminator to a string literal and -/// returns a `*mut c_char` pointer to it. -/// -/// The resulting pointer points into the program's read-only data segment; -/// callers must never write through it. -macro_rules! cstr { - ($s:literal) => { - concat!($s, "\0").as_ptr() as *mut c_char - }; -} - extern "C" { /// C standard `printf`; used to emit diagnostic messages during IWAD /// search. @@ -114,88 +103,88 @@ unsafe impl Sync for iwad_t {} /// shareware releases. Mirrors `iwads[]` in `d_iwad.c`. static IWADS: [iwad_t; 14] = [ iwad_t { - name: cstr!("doom2.wad"), + name: c"doom2.wad".as_ptr().cast_mut(), mission: d_mode::doom2, mode: d_mode::commercial, - description: cstr!("Doom II"), + description: c"Doom II".as_ptr().cast_mut(), }, iwad_t { - name: cstr!("plutonia.wad"), + name: c"plutonia.wad".as_ptr().cast_mut(), mission: d_mode::pack_plut, mode: d_mode::commercial, - description: cstr!("Final Doom: Plutonia Experiment"), + description: c"Final Doom: Plutonia Experiment".as_ptr().cast_mut(), }, iwad_t { - name: cstr!("tnt.wad"), + name: c"tnt.wad".as_ptr().cast_mut(), mission: d_mode::pack_tnt, mode: d_mode::commercial, - description: cstr!("Final Doom: TNT: Evilution"), + description: c"Final Doom: TNT: Evilution".as_ptr().cast_mut(), }, iwad_t { - name: cstr!("doom.wad"), + name: c"doom.wad".as_ptr().cast_mut(), mission: d_mode::doom, mode: d_mode::retail, - description: cstr!("Doom"), + description: c"Doom".as_ptr().cast_mut(), }, iwad_t { - name: cstr!("doom1.wad"), + name: c"doom1.wad".as_ptr().cast_mut(), mission: d_mode::doom, mode: d_mode::shareware, - description: cstr!("Doom Shareware"), + description: c"Doom Shareware".as_ptr().cast_mut(), }, iwad_t { - name: cstr!("chex.wad"), + name: c"chex.wad".as_ptr().cast_mut(), mission: d_mode::pack_chex, mode: d_mode::shareware, - description: cstr!("Chex Quest"), + description: c"Chex Quest".as_ptr().cast_mut(), }, iwad_t { - name: cstr!("hacx.wad"), + name: c"hacx.wad".as_ptr().cast_mut(), mission: d_mode::pack_hacx, mode: d_mode::commercial, - description: cstr!("Hacx"), + description: c"Hacx".as_ptr().cast_mut(), }, iwad_t { - name: cstr!("freedm.wad"), + name: c"freedm.wad".as_ptr().cast_mut(), mission: d_mode::doom2, mode: d_mode::commercial, - description: cstr!("FreeDM"), + description: c"FreeDM".as_ptr().cast_mut(), }, iwad_t { - name: cstr!("freedoom2.wad"), + name: c"freedoom2.wad".as_ptr().cast_mut(), mission: d_mode::doom2, mode: d_mode::commercial, - description: cstr!("Freedoom: Phase 2"), + description: c"Freedoom: Phase 2".as_ptr().cast_mut(), }, iwad_t { - name: cstr!("freedoom1.wad"), + name: c"freedoom1.wad".as_ptr().cast_mut(), mission: d_mode::doom, mode: d_mode::retail, - description: cstr!("Freedoom: Phase 1"), + description: c"Freedoom: Phase 1".as_ptr().cast_mut(), }, iwad_t { - name: cstr!("heretic.wad"), + name: c"heretic.wad".as_ptr().cast_mut(), mission: d_mode::heretic, mode: d_mode::retail, - description: cstr!("Heretic"), + description: c"Heretic".as_ptr().cast_mut(), }, iwad_t { - name: cstr!("heretic1.wad"), + name: c"heretic1.wad".as_ptr().cast_mut(), mission: d_mode::heretic, mode: d_mode::shareware, - description: cstr!("Heretic Shareware"), + description: c"Heretic Shareware".as_ptr().cast_mut(), }, iwad_t { - name: cstr!("hexen.wad"), + name: c"hexen.wad".as_ptr().cast_mut(), mission: d_mode::hexen, mode: d_mode::commercial, - description: cstr!("Hexen"), + description: c"Hexen".as_ptr().cast_mut(), }, iwad_t { - name: cstr!("strife1.wad"), + name: c"strife1.wad".as_ptr().cast_mut(), mission: d_mode::strife, mode: d_mode::commercial, - description: cstr!("Strife"), + description: c"Strife".as_ptr().cast_mut(), }, ]; @@ -281,7 +270,7 @@ unsafe fn CheckDirectoryHasIWAD(dir: *mut c_char, iwadname: *mut c_char) -> *mut return strdup(dir); } - let filename = if strcmp(dir, cstr!(".")) == 0 { + let filename = if strcmp(dir, c".".as_ptr()) == 0 { strdup(iwadname) } else { let strs: [*const c_char; 4] = [ @@ -386,7 +375,7 @@ unsafe fn IdentifyIWADByName(mut name: *mut c_char, mask: c_int) -> c_int { /// `iwad_dirs_built` without synchronisation, and calls `AddIWADDir` which /// imposes the same requirement. unsafe fn BuildIWADDirList() { - AddIWADDir(cstr!(".")); + AddIWADDir(c".".as_ptr().cast_mut()); iwad_dirs_built = true; } @@ -471,7 +460,7 @@ pub unsafe extern "C" fn D_TryFindWADByName(filename: *mut c_char) -> *mut c_cha /// `mission` must be a valid, non-null pointer. #[no_mangle] pub unsafe extern "C" fn D_FindIWAD(mask: c_int, mission: *mut c_int) -> *mut c_char { - let iwadparm = M_CheckParmWithArgs(cstr!("-iwad"), 1); + let iwadparm = M_CheckParmWithArgs(c"-iwad".as_ptr(), 1); if iwadparm != 0 { let iwadfile = *myargv.offset((iwadparm + 1) as isize); @@ -554,7 +543,7 @@ pub unsafe extern "C" fn D_SaveGameIWADName(gamemission: c_int) -> *mut c_char { return IWADS[i].name; } } - cstr!("unknown.wad") + c"unknown.wad".as_ptr().cast_mut() } /// Returns the canonical IWAD filename that best matches `mission` and `mode`. @@ -570,7 +559,7 @@ pub unsafe extern "C" fn D_SuggestIWADName(mission: c_int, mode: c_int) -> *mut return IWADS[i].name; } } - cstr!("unknown.wad") + c"unknown.wad".as_ptr().cast_mut() } /// Returns a human-readable game name for the given `mission` and `mode`. @@ -587,7 +576,7 @@ pub unsafe extern "C" fn D_SuggestGameName(mission: c_int, mode: c_int) -> *mut return IWADS[i].description; } } - cstr!("Unknown game?") + c"Unknown game?".as_ptr().cast_mut() } /// Validates that the loaded IWAD matches the expected `_mission`. diff --git a/room/src/doom/d_mode.rs b/room/src/doom/d_mode.rs index 13fd3448..88938ce1 100644 --- a/room/src/doom/d_mode.rs +++ b/room/src/doom/d_mode.rs @@ -486,16 +486,6 @@ pub extern "C" fn D_IsEpisodeMap(mission: c_int) -> Boolean { } } -/// Convenience macro to produce a `*mut c_char` from a string literal. -/// -/// Appends a NUL terminator and casts the resulting static byte slice to a raw -/// `c_char` pointer. Used only within [`D_GameMissionString`]. -macro_rules! cstr { - ($s:literal) => { - concat!($s, "\0").as_ptr() as *mut c_char - }; -} - /// Return a NUL-terminated C string naming the given mission. /// /// Returns one of `"doom"`, `"doom2"`, `"tnt"`, `"plutonia"`, `"hacx"`, @@ -512,16 +502,16 @@ macro_rules! cstr { #[no_mangle] pub extern "C" fn D_GameMissionString(mission: c_int) -> *mut c_char { match mission { - doom => cstr!("doom"), - doom2 => cstr!("doom2"), - pack_tnt => cstr!("tnt"), - pack_plut => cstr!("plutonia"), - pack_hacx => cstr!("hacx"), - pack_chex => cstr!("chex"), - heretic => cstr!("heretic"), - hexen => cstr!("hexen"), - strife => cstr!("strife"), - _ => cstr!("none"), + doom => c"doom".as_ptr().cast_mut(), + doom2 => c"doom2".as_ptr().cast_mut(), + pack_tnt => c"tnt".as_ptr().cast_mut(), + pack_plut => c"plutonia".as_ptr().cast_mut(), + pack_hacx => c"hacx".as_ptr().cast_mut(), + pack_chex => c"chex".as_ptr().cast_mut(), + heretic => c"heretic".as_ptr().cast_mut(), + hexen => c"hexen".as_ptr().cast_mut(), + strife => c"strife".as_ptr().cast_mut(), + _ => c"none".as_ptr().cast_mut(), } } diff --git a/room/src/doom/dstrings.rs b/room/src/doom/dstrings.rs index 05f8ec28..4ceb516d 100644 --- a/room/src/doom/dstrings.rs +++ b/room/src/doom/dstrings.rs @@ -10,9 +10,8 @@ //! `Sync` by default, even though the pointers here only ever point at //! immutable `'static` data. //! -//! The `cstr!` macro appends `"\0"` at compile time and casts the resulting -//! `&str` to `*const c_char`, producing a valid NUL-terminated C string from -//! a Rust string literal without any heap allocation. +//! C string literals (`c"..."`) provide static NUL-terminated pointers without +//! heap allocation. //! //! The engine selects a message from these tables at random when the player //! attempts to quit, using `gamemission` to pick the correct table @@ -42,17 +41,6 @@ impl Ptr { } } -/// Construct a [`Ptr`] pointing to a NUL-terminated C string from a string literal. -/// -/// The macro concatenates `"\0"` onto the literal at compile time, then casts -/// the `&'static str` data pointer to `*const c_char`. No heap allocation -/// occurs; the string resides in the binary's read-only data segment. -macro_rules! cstr { - ($s:literal) => { - Ptr(concat!($s, "\0").as_ptr() as *const c_char) - }; -} - /// Eight randomised quit messages shown when a Doom 1 player tries to exit. /// /// Corresponds to `char *doom1_endmsg[]` in `dstrings.c`. The game picks @@ -61,14 +49,14 @@ macro_rules! cstr { /// equivalent) to access the table by its original symbol name. #[no_mangle] pub static doom1_endmsg: [Ptr; 8] = [ - cstr!("are you sure you want to\nquit this great game?"), - cstr!("please don't leave, there's more\ndemons to toast!"), - cstr!("let's beat it -- this is turning\ninto a bloodbath!"), - cstr!("i wouldn't leave if i were you.\ndos is much worse."), - cstr!("you're trying to say you like dos\nbetter than me, right?"), - cstr!("don't leave yet -- there's a\ndemon around that corner!"), - cstr!("ya know, next time you come in here\ni'm gonna toast ya."), - cstr!("go ahead and leave. see if i care."), + Ptr(c"are you sure you want to\nquit this great game?".as_ptr()), + Ptr(c"please don't leave, there's more\ndemons to toast!".as_ptr()), + Ptr(c"let's beat it -- this is turning\ninto a bloodbath!".as_ptr()), + Ptr(c"i wouldn't leave if i were you.\ndos is much worse.".as_ptr()), + Ptr(c"you're trying to say you like dos\nbetter than me, right?".as_ptr()), + Ptr(c"don't leave yet -- there's a\ndemon around that corner!".as_ptr()), + Ptr(c"ya know, next time you come in here\ni'm gonna toast ya.".as_ptr()), + Ptr(c"go ahead and leave. see if i care.".as_ptr()), ]; /// Eight randomised quit messages shown when a Doom 2 player tries to exit. @@ -78,14 +66,14 @@ pub static doom1_endmsg: [Ptr; 8] = [ /// `gamemission` is `doom2`, `pack_tnt`, or `pack_plut`. #[no_mangle] pub static doom2_endmsg: [Ptr; 8] = [ - cstr!("are you sure you want to\nquit this great game?"), - cstr!("you want to quit?\nthen, thou hast lost an eighth!"), - cstr!("don't go now, there's a \ndimensional shambler waiting\nat the dos prompt!"), - cstr!("get outta here and go back\nto your boring programs."), - cstr!("if i were your boss, i'd \n deathmatch ya in a minute!"), - cstr!("look, bud. you leave now\nand you forfeit your body count!"), - cstr!("just leave. when you come\nback, i'll be waiting with a bat."), - cstr!("you're lucky i don't smack\nyou for thinking about leaving."), + Ptr(c"are you sure you want to\nquit this great game?".as_ptr()), + Ptr(c"you want to quit?\nthen, thou hast lost an eighth!".as_ptr()), + Ptr(c"don't go now, there's a \ndimensional shambler waiting\nat the dos prompt!".as_ptr()), + Ptr(c"get outta here and go back\nto your boring programs.".as_ptr()), + Ptr(c"if i were your boss, i'd \n deathmatch ya in a minute!".as_ptr()), + Ptr(c"look, bud. you leave now\nand you forfeit your body count!".as_ptr()), + Ptr(c"just leave. when you come\nback, i'll be waiting with a bat.".as_ptr()), + Ptr(c"you're lucky i don't smack\nyou for thinking about leaving.".as_ptr()), ]; #[cfg(test)] diff --git a/room/src/doom/f_finale.rs b/room/src/doom/f_finale.rs index 92647e84..a6a7d53a 100644 --- a/room/src/doom/f_finale.rs +++ b/room/src/doom/f_finale.rs @@ -86,115 +86,108 @@ const MAXPLAYERS: usize = 4; // Finale text strings (from d_englsh.h) // --------------------------------------------------------------------------- -/// Helper that appends a NUL byte and returns a `*mut c_char` to the literal. -macro_rules! cstr { - ($s:literal) => { - concat!($s, "\0").as_ptr() as *mut c_char - }; -} - /// Episode 1 finale text shown after defeating the boss on E1M8. -const E1TEXT: *mut c_char = cstr!("Once you beat the big badasses and\nclean out the moon base you're supposed\nto win, aren't you? Aren't you? Where's\nyour fat reward and ticket home? What\nthe hell is this? It's not supposed to\nend this way!\n\nIt stinks like rotten meat, but looks\nlike the lost Deimos base. Looks like\nyou're stuck on The Shores of Hell.\nThe only way out is through.\n\nTo continue the DOOM experience, play\nThe Shores of Hell and its amazing\nsequel, Inferno!"); +const E1TEXT: *mut c_char = c"Once you beat the big badasses and\nclean out the moon base you're supposed\nto win, aren't you? Aren't you? Where's\nyour fat reward and ticket home? What\nthe hell is this? It's not supposed to\nend this way!\n\nIt stinks like rotten meat, but looks\nlike the lost Deimos base. Looks like\nyou're stuck on The Shores of Hell.\nThe only way out is through.\n\nTo continue the DOOM experience, play\nThe Shores of Hell and its amazing\nsequel, Inferno!".as_ptr().cast_mut(); /// Episode 2 finale text shown after defeating the boss on E2M8. -const E2TEXT: *mut c_char = cstr!("You've done it! The hideous cyber-\ndemon lord that ruled the lost Deimos\nmoon base has been slain and you\ntriumph over the hordes of hell.\nThe mission is not complete, however.\nThe loathsome vomit of hell still\noozes from the nether regions of\nDeimos.\n\nThe demon spawner, the source of the\nhellish invasion, remains active.\nYou must find it and shut it down.\n\nTo continue the DOOM experience,\nplay Inferno!"); +const E2TEXT: *mut c_char = c"You've done it! The hideous cyber-\ndemon lord that ruled the lost Deimos\nmoon base has been slain and you\ntriumph over the hordes of hell.\nThe mission is not complete, however.\nThe loathsome vomit of hell still\noozes from the nether regions of\nDeimos.\n\nThe demon spawner, the source of the\nhellish invasion, remains active.\nYou must find it and shut it down.\n\nTo continue the DOOM experience,\nplay Inferno!".as_ptr().cast_mut(); /// Episode 3 finale text shown after defeating the boss on E3M8. -const E3TEXT: *mut c_char = cstr!("The loathsome spiderdemon that\nmaster-minded the invasion of the moon\nbase and caused so much death has had\nits ass kicked for all time.\n\nA hidden doorway opens and you begin\nthe long trek back to the surface.\nThe sensual scent of flowers tickles\nyour nose and you smile.\n\nBut wait! The gateway is open, and\nthe demons of hell are pouring\nthrough! You wonder how you'll ever\nget home.\n\nA demon consumes your flesh.\n\nThe End.\n\n(Well, not really. To continue the\nDOOM experience, play Thy Flesh\nConsumed!)"); +const E3TEXT: *mut c_char = c"The loathsome spiderdemon that\nmaster-minded the invasion of the moon\nbase and caused so much death has had\nits ass kicked for all time.\n\nA hidden doorway opens and you begin\nthe long trek back to the surface.\nThe sensual scent of flowers tickles\nyour nose and you smile.\n\nBut wait! The gateway is open, and\nthe demons of hell are pouring\nthrough! You wonder how you'll ever\nget home.\n\nA demon consumes your flesh.\n\nThe End.\n\n(Well, not really. To continue the\nDOOM experience, play Thy Flesh\nConsumed!)".as_ptr().cast_mut(); /// Episode 4 finale text shown after defeating the boss on E4M8. -const E4TEXT: *mut c_char = cstr!("The spider mastermind must have sent forth\nits legions of hellspawn before your\nfinal confrontation with that terrible\nbeast from netherworld. But you stepped\nforward and brought forth eternal damnation\nand suffering upon the horde as a true\nhero would in the face of something so\nevil.\n\nBesides, someone was gonna pay for what\nhappened to daisy, your pet rabbit.\n\nBut now, you see spread before you more\npotential pain and gibbitude as a nation\nof demons run amok among our cities.\n\nNext stop, hell on earth!"); +const E4TEXT: *mut c_char = c"The spider mastermind must have sent forth\nits legions of hellspawn before your\nfinal confrontation with that terrible\nbeast from netherworld. But you stepped\nforward and brought forth eternal damnation\nand suffering upon the horde as a true\nhero would in the face of something so\nevil.\n\nBesides, someone was gonna pay for what\nhappened to daisy, your pet rabbit.\n\nBut now, you see spread before you more\npotential pain and gibbitude as a nation\nof demons run amok among our cities.\n\nNext stop, hell on earth!".as_ptr().cast_mut(); /// Doom II level 6 inter-level text (first story block). -const C1TEXT: *mut c_char = cstr!("YOU HAVE ENTERED DEEPLY INTO THE INFESTED\nSTARPORT. BUT SOMETHING IS WRONG. THE\nMONSTERS HAVE BROUGHT THEIR OWN REALITY\nWITH THEM, AND THE STARPORT'S TECHNOLOGY\nIS BEING SUBVERTED BY THEIR PRESENCE.\n\nAHEAD, YOU SEE AN OUTPOST OF HELL, A\nFORTIFIED ZONE. IF YOU CAN GET PAST IT,\nYOU CAN PENETRATE INTO THE HAUNTED HEART\nOF THE STARBASE AND FIND THE CONTROLLING\nSWITCH WHICH HOLDS EARTH'S POPULATION\nHOSTAGE."); +const C1TEXT: *mut c_char = c"YOU HAVE ENTERED DEEPLY INTO THE INFESTED\nSTARPORT. BUT SOMETHING IS WRONG. THE\nMONSTERS HAVE BROUGHT THEIR OWN REALITY\nWITH THEM, AND THE STARPORT'S TECHNOLOGY\nIS BEING SUBVERTED BY THEIR PRESENCE.\n\nAHEAD, YOU SEE AN OUTPOST OF HELL, A\nFORTIFIED ZONE. IF YOU CAN GET PAST IT,\nYOU CAN PENETRATE INTO THE HAUNTED HEART\nOF THE STARBASE AND FIND THE CONTROLLING\nSWITCH WHICH HOLDS EARTH'S POPULATION\nHOSTAGE.".as_ptr().cast_mut(); /// Doom II level 11 inter-level text. -const C2TEXT: *mut c_char = cstr!("YOU HAVE WON! YOUR VICTORY HAS ENABLED\nHUMANKIND TO EVACUATE EARTH AND ESCAPE\nTHE NIGHTMARE. NOW YOU ARE THE ONLY\nHUMAN LEFT ON THE FACE OF THE PLANET.\nCAN YOU FIND YOUR WAY BACK TO HAPPY\nREALITY?\n\nOR ARE YOU DOOMED TO ROAM ETERNAL\nAMONG THE DEMONS?"); +const C2TEXT: *mut c_char = c"YOU HAVE WON! YOUR VICTORY HAS ENABLED\nHUMANKIND TO EVACUATE EARTH AND ESCAPE\nTHE NIGHTMARE. NOW YOU ARE THE ONLY\nHUMAN LEFT ON THE FACE OF THE PLANET.\nCAN YOU FIND YOUR WAY BACK TO HAPPY\nREALITY?\n\nOR ARE YOU DOOMED TO ROAM ETERNAL\nAMONG THE DEMONS?".as_ptr().cast_mut(); /// Doom II level 20 inter-level text. -const C3TEXT: *mut c_char = cstr!("YOU ARE AT THE CORRUPT HEART OF THE CITY,\nSURROUNDED BY THE CORPSES OF YOUR ENEMIES.\nYOU SEE NO WAY TO ESCAPE FROM THIS FUTURE\nHELL, BUT YOU MAY DELAY THE DAMNATION OF\nHUMANITY BY THROWING YOURSELF INTO THE\nPORTAL, AND HEADING OFF THE DEMONIC\nINVASION AT ITS SOURCE."); +const C3TEXT: *mut c_char = c"YOU ARE AT THE CORRUPT HEART OF THE CITY,\nSURROUNDED BY THE CORPSES OF YOUR ENEMIES.\nYOU SEE NO WAY TO ESCAPE FROM THIS FUTURE\nHELL, BUT YOU MAY DELAY THE DAMNATION OF\nHUMANITY BY THROWING YOURSELF INTO THE\nPORTAL, AND HEADING OFF THE DEMONIC\nINVASION AT ITS SOURCE.".as_ptr().cast_mut(); /// Doom II level 30 inter-level text. -const C4TEXT: *mut c_char = cstr!("SENSIBLE, NO?\n\nTHERE WAS NO WAY YOU COULD SURVIVE THIS\nHELL, BUT YOU HAVE SUCCEEDED IN SPOILING\nTHE DEMONS' PLANS. THE HAZARDOUS-WASTE\nFACILITY HAS BEEN DESTROYED AND HELL'S\nPORTAL HAS BEEN SEALED.\n\nYOU ARE THE ONLY SURVIVOR, BUT THE BATTLE\nCONTINUES ELSEWHERE. EARTH REMAINS UNDER\nSIEGE, AND THE HELLSPAWN PROWL THE\nSTREETS IN SEARCH OF MORE PREY.\n\nTHE INVASION IS FAR FROM OVER."); +const C4TEXT: *mut c_char = c"SENSIBLE, NO?\n\nTHERE WAS NO WAY YOU COULD SURVIVE THIS\nHELL, BUT YOU HAVE SUCCEEDED IN SPOILING\nTHE DEMONS' PLANS. THE HAZARDOUS-WASTE\nFACILITY HAS BEEN DESTROYED AND HELL'S\nPORTAL HAS BEEN SEALED.\n\nYOU ARE THE ONLY SURVIVOR, BUT THE BATTLE\nCONTINUES ELSEWHERE. EARTH REMAINS UNDER\nSIEGE, AND THE HELLSPAWN PROWL THE\nSTREETS IN SEARCH OF MORE PREY.\n\nTHE INVASION IS FAR FROM OVER.".as_ptr().cast_mut(); /// Doom II level 15 (secret exit) inter-level text. -const C5TEXT: *mut c_char = cstr!("BUT WAIT! THERE'S MORE!\n\nIT'S BACK TO THE PITS OF HELL FOR YOU,\nTO FACE MORE DEMONS, MORE HELLSPAWN, AND\nMORE HIDEOUS ACTS OF EVIL.\n\nIT'S A DIRTY JOB, BUT SOMEONE'S GOT TO\nDO IT. AND THAT SOMEONE IS YOU."); +const C5TEXT: *mut c_char = c"BUT WAIT! THERE'S MORE!\n\nIT'S BACK TO THE PITS OF HELL FOR YOU,\nTO FACE MORE DEMONS, MORE HELLSPAWN, AND\nMORE HIDEOUS ACTS OF EVIL.\n\nIT'S A DIRTY JOB, BUT SOMEONE'S GOT TO\nDO IT. AND THAT SOMEONE IS YOU.".as_ptr().cast_mut(); /// Doom II level 31 inter-level text. -const C6TEXT: *mut c_char = cstr!("CONGRATULATIONS!\n\nYOU HAVE FOUND THE SECRET LEVEL!\n\nHOPEFULLY YOU FOUND THE PLASMA GUN.\n\nTHE DEMON HORDE IS ABOUT TO GET A WAKE-UP\nCALL."); +const C6TEXT: *mut c_char = c"CONGRATULATIONS!\n\nYOU HAVE FOUND THE SECRET LEVEL!\n\nHOPEFULLY YOU FOUND THE PLASMA GUN.\n\nTHE DEMON HORDE IS ABOUT TO GET A WAKE-UP\nCALL.".as_ptr().cast_mut(); /// TNT: Evilution level 6 inter-level text. -const T1TEXT: *mut c_char = cstr!("You've fought your way out of the infested\nexperimental labs. It seems that UAC has\nonce again gulped it down. Ahead lies\ntheir central complex, now firmly in the\ngrasp of the demon hordes. Perhaps by\nsabotaging their primary teleporter you\ncan halt the invasion."); +const T1TEXT: *mut c_char = c"You've fought your way out of the infested\nexperimental labs. It seems that UAC has\nonce again gulped it down. Ahead lies\ntheir central complex, now firmly in the\ngrasp of the demon hordes. Perhaps by\nsabotaging their primary teleporter you\ncan halt the invasion.".as_ptr().cast_mut(); /// TNT: Evilution level 11 inter-level text. -const T2TEXT: *mut c_char = cstr!("The demon spawner you've found appears to\nhave been activated. The Demons are\npouring through in endless waves. You\nneed to find a way to deactivate it,\nfast!"); +const T2TEXT: *mut c_char = c"The demon spawner you've found appears to\nhave been activated. The Demons are\npouring through in endless waves. You\nneed to find a way to deactivate it,\nfast!".as_ptr().cast_mut(); /// TNT: Evilution level 20 inter-level text. -const T3TEXT: *mut c_char = cstr!("The river of blood spills over into the\nnext area. It seems your arrival hasn't\ngone unnoticed. Ahead lies the most\ninfested region of the complex. You must\nfind a way to stem the tide of demons, or\ndie trying."); +const T3TEXT: *mut c_char = c"The river of blood spills over into the\nnext area. It seems your arrival hasn't\ngone unnoticed. Ahead lies the most\ninfested region of the complex. You must\nfind a way to stem the tide of demons, or\ndie trying.".as_ptr().cast_mut(); /// TNT: Evilution level 30 inter-level text. -const T4TEXT: *mut c_char = cstr!("The stench of rotten flesh and sulfur\nfills the air. You have reached the\nheart of the infested complex. Somewhere\nbeyond the next portal lies the Demon\nSpawner itself. If you can survive long\nenough to find it, you may be able to turn\nthe tide of this war."); +const T4TEXT: *mut c_char = c"The stench of rotten flesh and sulfur\nfills the air. You have reached the\nheart of the infested complex. Somewhere\nbeyond the next portal lies the Demon\nSpawner itself. If you can survive long\nenough to find it, you may be able to turn\nthe tide of this war.".as_ptr().cast_mut(); /// TNT: Evilution level 15 inter-level text. -const T5TEXT: *mut c_char = cstr!("You've done it! The hideous Spiderdemon\nthat masterminded the invasion is dead.\nBut the demon spawner still remains,\nand the forces of hell are still pouring\nthrough. You need to find the primary\nteleporter and destroy it."); +const T5TEXT: *mut c_char = c"You've done it! The hideous Spiderdemon\nthat masterminded the invasion is dead.\nBut the demon spawner still remains,\nand the forces of hell are still pouring\nthrough. You need to find the primary\nteleporter and destroy it.".as_ptr().cast_mut(); /// TNT: Evilution level 31 inter-level text. -const T6TEXT: *mut c_char = cstr!("The primary teleporter is destroyed, but\nthe forces of hell are still pouring in.\nYou need to find the secondary teleporter\nand shut it down. The fate of Earth\ndepends on it."); +const T6TEXT: *mut c_char = c"The primary teleporter is destroyed, but\nthe forces of hell are still pouring in.\nYou need to find the secondary teleporter\nand shut it down. The fate of Earth\ndepends on it.".as_ptr().cast_mut(); /// Plutonia Experiment level 6 inter-level text. -const P1TEXT: *mut c_char = cstr!("You gloat over the steaming carcass of the\nGuardian. With its death, you've wrested\nthe Accelerator from the stinking claws\nof Hell. You relax and glance around\nthe room. Damn! There was supposed to\nbe a bridge around here somewhere! Did\nthe Invaders sense your victory and\nwithdraw the bridge to prevent your\nescape?\n\nYou hear the sound of claws on stone.\nYou frantically grab your pistol and\ndive for the door, but it's too late.\nThe Demons have arrived."); +const P1TEXT: *mut c_char = c"You gloat over the steaming carcass of the\nGuardian. With its death, you've wrested\nthe Accelerator from the stinking claws\nof Hell. You relax and glance around\nthe room. Damn! There was supposed to\nbe a bridge around here somewhere! Did\nthe Invaders sense your victory and\nwithdraw the bridge to prevent your\nescape?\n\nYou hear the sound of claws on stone.\nYou frantically grab your pistol and\ndive for the door, but it's too late.\nThe Demons have arrived.".as_ptr().cast_mut(); /// Plutonia Experiment level 11 inter-level text. -const P2TEXT: *mut c_char = cstr!("You did it! The hideous Spiderdemon\nthat masterminded the invasion is dead.\nBut the demon spawner still remains,\nand the forces of hell are still pouring\nthrough. You need to find the primary\nteleporter and destroy it."); +const P2TEXT: *mut c_char = c"You did it! The hideous Spiderdemon\nthat masterminded the invasion is dead.\nBut the demon spawner still remains,\nand the forces of hell are still pouring\nthrough. You need to find the primary\nteleporter and destroy it.".as_ptr().cast_mut(); /// Plutonia Experiment level 20 inter-level text. -const P3TEXT: *mut c_char = cstr!("The Vile presence fades. You feel a\nsense of relief, but it is short lived.\nYou still must find the demon spawner\nand shut it down. Time is running out."); +const P3TEXT: *mut c_char = c"The Vile presence fades. You feel a\nsense of relief, but it is short lived.\nYou still must find the demon spawner\nand shut it down. Time is running out.".as_ptr().cast_mut(); /// Plutonia Experiment level 30 inter-level text. -const P4TEXT: *mut c_char = cstr!("The demon spawner lies in ruins before\nyou. The forces of hell are in full\nretreat, and the invasion is stopped.\nYou step onto the teleporter, eager to\nreturn home and bask in the glory of\nyour victory."); +const P4TEXT: *mut c_char = c"The demon spawner lies in ruins before\nyou. The forces of hell are in full\nretreat, and the invasion is stopped.\nYou step onto the teleporter, eager to\nreturn home and bask in the glory of\nyour victory.".as_ptr().cast_mut(); /// Plutonia Experiment level 15 inter-level text. -const P5TEXT: *mut c_char = cstr!("You have survived the horrors of the\ninfested complex and emerged victorious.\nThe demon spawner lies in ruins, and the\nforces of hell have been driven back.\nYou step onto the teleporter, ready to\nreturn Earth and face whatever\nchallenges lie ahead."); +const P5TEXT: *mut c_char = c"You have survived the horrors of the\ninfested complex and emerged victorious.\nThe demon spawner lies in ruins, and the\nforces of hell have been driven back.\nYou step onto the teleporter, ready to\nreturn Earth and face whatever\nchallenges lie ahead.".as_ptr().cast_mut(); /// Plutonia Experiment level 31 inter-level text. -const P6TEXT: *mut c_char = cstr!("The primary teleporter is destroyed, but\nthe forces of hell are still pouring in.\nYou need to find the secondary teleporter\nand shut it down. The fate of Earth\ndepends on it."); +const P6TEXT: *mut c_char = c"The primary teleporter is destroyed, but\nthe forces of hell are still pouring in.\nYou need to find the secondary teleporter\nand shut it down. The fate of Earth\ndepends on it.".as_ptr().cast_mut(); // Cast names (from d_englsh.h) /// Cast-roll name for the Zombieman. -const CC_ZOMBIE: *mut c_char = cstr!("ZOMBIEMAN"); +const CC_ZOMBIE: *mut c_char = c"ZOMBIEMAN".as_ptr().cast_mut(); /// Cast-roll name for the Shotgun Guy. -const CC_SHOTGUN: *mut c_char = cstr!("SHOTGUN GUY"); +const CC_SHOTGUN: *mut c_char = c"SHOTGUN GUY".as_ptr().cast_mut(); /// Cast-roll name for the Heavy Weapon Dude (chaingunner). -const CC_HEAVY: *mut c_char = cstr!("HEAVY WEAPON DUDE"); +const CC_HEAVY: *mut c_char = c"HEAVY WEAPON DUDE".as_ptr().cast_mut(); /// Cast-roll name for the Imp. -const CC_IMP: *mut c_char = cstr!("IMP"); +const CC_IMP: *mut c_char = c"IMP".as_ptr().cast_mut(); /// Cast-roll name for the Demon. -const CC_DEMON: *mut c_char = cstr!("DEMON"); +const CC_DEMON: *mut c_char = c"DEMON".as_ptr().cast_mut(); /// Cast-roll name for the Lost Soul. -const CC_LOST: *mut c_char = cstr!("LOST SOUL"); +const CC_LOST: *mut c_char = c"LOST SOUL".as_ptr().cast_mut(); /// Cast-roll name for the Cacodemon. -const CC_CACO: *mut c_char = cstr!("CACODEMON"); +const CC_CACO: *mut c_char = c"CACODEMON".as_ptr().cast_mut(); /// Cast-roll name for the Hell Knight. -const CC_HELL: *mut c_char = cstr!("HELL KNIGHT"); +const CC_HELL: *mut c_char = c"HELL KNIGHT".as_ptr().cast_mut(); /// Cast-roll name for the Baron of Hell. -const CC_BARON: *mut c_char = cstr!("BARON OF HELL"); +const CC_BARON: *mut c_char = c"BARON OF HELL".as_ptr().cast_mut(); /// Cast-roll name for the Arachnotron. -const CC_ARACH: *mut c_char = cstr!("ARACHNOTRON"); +const CC_ARACH: *mut c_char = c"ARACHNOTRON".as_ptr().cast_mut(); /// Cast-roll name for the Pain Elemental. -const CC_PAIN: *mut c_char = cstr!("PAIN ELEMENTAL"); +const CC_PAIN: *mut c_char = c"PAIN ELEMENTAL".as_ptr().cast_mut(); /// Cast-roll name for the Revenant. -const CC_REVEN: *mut c_char = cstr!("REVENANT"); +const CC_REVEN: *mut c_char = c"REVENANT".as_ptr().cast_mut(); /// Cast-roll name for the Mancubus. -const CC_MANCU: *mut c_char = cstr!("MANCUBUS"); +const CC_MANCU: *mut c_char = c"MANCUBUS".as_ptr().cast_mut(); /// Cast-roll name for the Arch-Vile. -const CC_ARCH: *mut c_char = cstr!("ARCH-VILE"); +const CC_ARCH: *mut c_char = c"ARCH-VILE".as_ptr().cast_mut(); /// Cast-roll name for the Spider Mastermind. -const CC_SPIDER: *mut c_char = cstr!("THE SPIDER MASTERMIND"); +const CC_SPIDER: *mut c_char = c"THE SPIDER MASTERMIND".as_ptr().cast_mut(); /// Cast-roll name for the Cyberdemon. -const CC_CYBER: *mut c_char = cstr!("THE CYBERDEMON"); +const CC_CYBER: *mut c_char = c"THE CYBERDEMON".as_ptr().cast_mut(); /// Cast-roll name for the player character. -const CC_HERO: *mut c_char = cstr!("OUR HERO"); +const CC_HERO: *mut c_char = c"OUR HERO".as_ptr().cast_mut(); // --------------------------------------------------------------------------- // Types @@ -349,154 +342,154 @@ const TEXTSCREENS: [TextScreen; 22] = [ mission: d_mode::doom, episode: 1, level: 8, - background: cstr!("FLOOR4_8"), + background: c"FLOOR4_8".as_ptr().cast_mut(), text: E1TEXT, }, TextScreen { mission: d_mode::doom, episode: 2, level: 8, - background: cstr!("SFLR6_1"), + background: c"SFLR6_1".as_ptr().cast_mut(), text: E2TEXT, }, TextScreen { mission: d_mode::doom, episode: 3, level: 8, - background: cstr!("MFLR8_4"), + background: c"MFLR8_4".as_ptr().cast_mut(), text: E3TEXT, }, TextScreen { mission: d_mode::doom, episode: 4, level: 8, - background: cstr!("MFLR8_3"), + background: c"MFLR8_3".as_ptr().cast_mut(), text: E4TEXT, }, TextScreen { mission: d_mode::doom2, episode: 1, level: 6, - background: cstr!("SLIME16"), + background: c"SLIME16".as_ptr().cast_mut(), text: C1TEXT, }, TextScreen { mission: d_mode::doom2, episode: 1, level: 11, - background: cstr!("RROCK14"), + background: c"RROCK14".as_ptr().cast_mut(), text: C2TEXT, }, TextScreen { mission: d_mode::doom2, episode: 1, level: 20, - background: cstr!("RROCK07"), + background: c"RROCK07".as_ptr().cast_mut(), text: C3TEXT, }, TextScreen { mission: d_mode::doom2, episode: 1, level: 30, - background: cstr!("RROCK17"), + background: c"RROCK17".as_ptr().cast_mut(), text: C4TEXT, }, TextScreen { mission: d_mode::doom2, episode: 1, level: 15, - background: cstr!("RROCK13"), + background: c"RROCK13".as_ptr().cast_mut(), text: C5TEXT, }, TextScreen { mission: d_mode::doom2, episode: 1, level: 31, - background: cstr!("RROCK19"), + background: c"RROCK19".as_ptr().cast_mut(), text: C6TEXT, }, TextScreen { mission: d_mode::pack_tnt, episode: 1, level: 6, - background: cstr!("SLIME16"), + background: c"SLIME16".as_ptr().cast_mut(), text: T1TEXT, }, TextScreen { mission: d_mode::pack_tnt, episode: 1, level: 11, - background: cstr!("RROCK14"), + background: c"RROCK14".as_ptr().cast_mut(), text: T2TEXT, }, TextScreen { mission: d_mode::pack_tnt, episode: 1, level: 20, - background: cstr!("RROCK07"), + background: c"RROCK07".as_ptr().cast_mut(), text: T3TEXT, }, TextScreen { mission: d_mode::pack_tnt, episode: 1, level: 30, - background: cstr!("RROCK17"), + background: c"RROCK17".as_ptr().cast_mut(), text: T4TEXT, }, TextScreen { mission: d_mode::pack_tnt, episode: 1, level: 15, - background: cstr!("RROCK13"), + background: c"RROCK13".as_ptr().cast_mut(), text: T5TEXT, }, TextScreen { mission: d_mode::pack_tnt, episode: 1, level: 31, - background: cstr!("RROCK19"), + background: c"RROCK19".as_ptr().cast_mut(), text: T6TEXT, }, TextScreen { mission: d_mode::pack_plut, episode: 1, level: 6, - background: cstr!("SLIME16"), + background: c"SLIME16".as_ptr().cast_mut(), text: P1TEXT, }, TextScreen { mission: d_mode::pack_plut, episode: 1, level: 11, - background: cstr!("RROCK14"), + background: c"RROCK14".as_ptr().cast_mut(), text: P2TEXT, }, TextScreen { mission: d_mode::pack_plut, episode: 1, level: 20, - background: cstr!("RROCK07"), + background: c"RROCK07".as_ptr().cast_mut(), text: P3TEXT, }, TextScreen { mission: d_mode::pack_plut, episode: 1, level: 30, - background: cstr!("RROCK17"), + background: c"RROCK17".as_ptr().cast_mut(), text: P4TEXT, }, TextScreen { mission: d_mode::pack_plut, episode: 1, level: 15, - background: cstr!("RROCK13"), + background: c"RROCK13".as_ptr().cast_mut(), text: P5TEXT, }, TextScreen { mission: d_mode::pack_plut, episode: 1, level: 31, - background: cstr!("RROCK19"), + background: c"RROCK19".as_ptr().cast_mut(), text: P6TEXT, }, ]; @@ -1149,7 +1142,7 @@ pub extern "C" fn F_CastDrawer() { V_DrawPatch( 0, 0, - W_CacheLumpName(DEH_String(cstr!("BOSSBACK")), PU_CACHE) as *mut patch_t, + W_CacheLumpName(DEH_String(c"BOSSBACK".as_ptr().cast_mut()), PU_CACHE) as *mut patch_t, ); F_CastPrint(DEH_String(CASTORDER[castnum as usize].name)); @@ -1210,8 +1203,8 @@ pub extern "C" fn F_DrawPatchCol(x: c_int, patch: *mut patch_t, col: c_int) { #[no_mangle] pub extern "C" fn F_BunnyScroll() { unsafe { - let p1 = W_CacheLumpName(DEH_String(cstr!("PFUB2")), PU_LEVEL) as *mut patch_t; - let p2 = W_CacheLumpName(DEH_String(cstr!("PFUB1")), PU_LEVEL) as *mut patch_t; + let p1 = W_CacheLumpName(DEH_String(c"PFUB2".as_ptr().cast_mut()), PU_LEVEL) as *mut patch_t; + let p2 = W_CacheLumpName(DEH_String(c"PFUB1".as_ptr().cast_mut()), PU_LEVEL) as *mut patch_t; V_MarkRect(0, 0, SCREENWIDTH, SCREENHEIGHT); @@ -1233,7 +1226,7 @@ pub extern "C" fn F_BunnyScroll() { V_DrawPatch( (SCREENWIDTH - 13 * 8) / 2, (SCREENHEIGHT - 8 * 8) / 2, - W_CacheLumpName(DEH_String(cstr!("END0")), PU_CACHE) as *mut patch_t, + W_CacheLumpName(DEH_String(c"END0".as_ptr().cast_mut()), PU_CACHE) as *mut patch_t, ); LAST_STAGE = 0; return; @@ -1282,13 +1275,13 @@ pub extern "C" fn F_ArtScreenDrawer() { let lumpname = match gameepisode { 1 => { if gamemode == d_mode::retail { - cstr!("CREDIT") + c"CREDIT".as_ptr().cast_mut() } else { - cstr!("HELP2") + c"HELP2".as_ptr().cast_mut() } } - 2 => cstr!("VICTORY2"), - 4 => cstr!("ENDPIC"), + 2 => c"VICTORY2".as_ptr().cast_mut(), + 4 => c"ENDPIC".as_ptr().cast_mut(), _ => return, }; diff --git a/room/src/doom/hu_stuff.rs b/room/src/doom/hu_stuff.rs index aae9c1c4..9d034ed4 100644 --- a/room/src/doom/hu_stuff.rs +++ b/room/src/doom/hu_stuff.rs @@ -116,18 +116,6 @@ unsafe fn logical_gamemission() -> c_int { // String literals // --------------------------------------------------------------------------- -/// Create a `*mut c_char` pointer to a NUL-terminated string literal. -/// -/// Appends `"\0"` at compile time and casts the resulting `&[u8]` pointer to -/// `*mut c_char`. The pointed-to data lives in the read-only data segment, so -/// the `mut` qualifier exists only to satisfy C-FFI signatures that declare -/// `char *` without `const`; the data must never actually be mutated. -macro_rules! cstr { - ($s:literal) => { - concat!($s, "\0").as_ptr() as *mut c_char - }; -} - // --------------------------------------------------------------------------- // Exported globals // --------------------------------------------------------------------------- @@ -139,16 +127,16 @@ macro_rules! cstr { /// to the C side so that `m_config.c` can bind user-configurable strings. #[no_mangle] pub static mut chat_macros: [*mut c_char; 10] = [ - cstr!("No"), - cstr!("I'm ready to kick butt!"), - cstr!("I'm OK."), - cstr!("I'm not looking too good!"), - cstr!("Help!"), - cstr!("You suck!"), - cstr!("Next time, scumbag..."), - cstr!("Come here!"), - cstr!("I'll take care of it."), - cstr!("Yes"), + c"No".as_ptr().cast_mut(), + c"I'm ready to kick butt!".as_ptr().cast_mut(), + c"I'm OK.".as_ptr().cast_mut(), + c"I'm not looking too good!".as_ptr().cast_mut(), + c"Help!".as_ptr().cast_mut(), + c"You suck!".as_ptr().cast_mut(), + c"Next time, scumbag...".as_ptr().cast_mut(), + c"Come here!".as_ptr().cast_mut(), + c"I'll take care of it.".as_ptr().cast_mut(), + c"Yes".as_ptr().cast_mut(), ]; /// Display names for each of the four multiplayer player colors. @@ -158,10 +146,10 @@ pub static mut chat_macros: [*mut c_char; 10] = [ /// C side can substitute Dehacked strings (not implemented in this port). #[no_mangle] pub static mut player_names: [*mut c_char; 4] = [ - cstr!("Green: "), - cstr!("Indigo: "), - cstr!("Brown: "), - cstr!("Red: "), + c"Green: ".as_ptr().cast_mut(), + c"Indigo: ".as_ptr().cast_mut(), + c"Brown: ".as_ptr().cast_mut(), + c"Red: ".as_ptr().cast_mut(), ]; /// Most-recently-transmitted chat character from the local player. @@ -204,51 +192,51 @@ pub static mut message_dontfuckwithme: c_int = 0; /// `hu_stuff.c` and is also exported for access from the C side. #[no_mangle] pub static mut mapnames: [*mut c_char; 45] = [ - cstr!("E1M1: Hangar"), - cstr!("E1M2: Nuclear Plant"), - cstr!("E1M3: Toxin Refinery"), - cstr!("E1M4: Command Control"), - cstr!("E1M5: Phobos Lab"), - cstr!("E1M6: Central Processing"), - cstr!("E1M7: Computer Station"), - cstr!("E1M8: Phobos Anomaly"), - cstr!("E1M9: Military Base"), - cstr!("E2M1: Deimos Anomaly"), - cstr!("E2M2: Containment Area"), - cstr!("E2M3: Refinery"), - cstr!("E2M4: Deimos Lab"), - cstr!("E2M5: Command Center"), - cstr!("E2M6: Halls of the Damned"), - cstr!("E2M7: Spawning Vats"), - cstr!("E2M8: Tower of Babel"), - cstr!("E2M9: Fortress of Mystery"), - cstr!("E3M1: Hell Keep"), - cstr!("E3M2: Slough of Despair"), - cstr!("E3M3: Pandemonium"), - cstr!("E3M4: House of Pain"), - cstr!("E3M5: Unholy Cathedral"), - cstr!("E3M6: Mt. Erebus"), - cstr!("E3M7: Limbo"), - cstr!("E3M8: Dis"), - cstr!("E3M9: Warrens"), - cstr!("E4M1: Hell Beneath"), - cstr!("E4M2: Perfect Hatred"), - cstr!("E4M3: Sever The Wicked"), - cstr!("E4M4: Unruly Evil"), - cstr!("E4M5: They Will Repent"), - cstr!("E4M6: Against Thee Wickedly"), - cstr!("E4M7: And Hell Followed"), - cstr!("E4M8: Unto The Cruel"), - cstr!("E4M9: Fear"), - cstr!("NEWLEVEL"), - cstr!("NEWLEVEL"), - cstr!("NEWLEVEL"), - cstr!("NEWLEVEL"), - cstr!("NEWLEVEL"), - cstr!("NEWLEVEL"), - cstr!("NEWLEVEL"), - cstr!("NEWLEVEL"), - cstr!("NEWLEVEL"), + c"E1M1: Hangar".as_ptr().cast_mut(), + c"E1M2: Nuclear Plant".as_ptr().cast_mut(), + c"E1M3: Toxin Refinery".as_ptr().cast_mut(), + c"E1M4: Command Control".as_ptr().cast_mut(), + c"E1M5: Phobos Lab".as_ptr().cast_mut(), + c"E1M6: Central Processing".as_ptr().cast_mut(), + c"E1M7: Computer Station".as_ptr().cast_mut(), + c"E1M8: Phobos Anomaly".as_ptr().cast_mut(), + c"E1M9: Military Base".as_ptr().cast_mut(), + c"E2M1: Deimos Anomaly".as_ptr().cast_mut(), + c"E2M2: Containment Area".as_ptr().cast_mut(), + c"E2M3: Refinery".as_ptr().cast_mut(), + c"E2M4: Deimos Lab".as_ptr().cast_mut(), + c"E2M5: Command Center".as_ptr().cast_mut(), + c"E2M6: Halls of the Damned".as_ptr().cast_mut(), + c"E2M7: Spawning Vats".as_ptr().cast_mut(), + c"E2M8: Tower of Babel".as_ptr().cast_mut(), + c"E2M9: Fortress of Mystery".as_ptr().cast_mut(), + c"E3M1: Hell Keep".as_ptr().cast_mut(), + c"E3M2: Slough of Despair".as_ptr().cast_mut(), + c"E3M3: Pandemonium".as_ptr().cast_mut(), + c"E3M4: House of Pain".as_ptr().cast_mut(), + c"E3M5: Unholy Cathedral".as_ptr().cast_mut(), + c"E3M6: Mt. Erebus".as_ptr().cast_mut(), + c"E3M7: Limbo".as_ptr().cast_mut(), + c"E3M8: Dis".as_ptr().cast_mut(), + c"E3M9: Warrens".as_ptr().cast_mut(), + c"E4M1: Hell Beneath".as_ptr().cast_mut(), + c"E4M2: Perfect Hatred".as_ptr().cast_mut(), + c"E4M3: Sever The Wicked".as_ptr().cast_mut(), + c"E4M4: Unruly Evil".as_ptr().cast_mut(), + c"E4M5: They Will Repent".as_ptr().cast_mut(), + c"E4M6: Against Thee Wickedly".as_ptr().cast_mut(), + c"E4M7: And Hell Followed".as_ptr().cast_mut(), + c"E4M8: Unto The Cruel".as_ptr().cast_mut(), + c"E4M9: Fear".as_ptr().cast_mut(), + c"NEWLEVEL".as_ptr().cast_mut(), + c"NEWLEVEL".as_ptr().cast_mut(), + c"NEWLEVEL".as_ptr().cast_mut(), + c"NEWLEVEL".as_ptr().cast_mut(), + c"NEWLEVEL".as_ptr().cast_mut(), + c"NEWLEVEL".as_ptr().cast_mut(), + c"NEWLEVEL".as_ptr().cast_mut(), + c"NEWLEVEL".as_ptr().cast_mut(), + c"NEWLEVEL".as_ptr().cast_mut(), ]; /// Display names for Doom II, Plutonia, and TNT maps (96 entries total). @@ -260,104 +248,104 @@ pub static mut mapnames: [*mut c_char; 45] = [ #[no_mangle] pub static mut mapnames_commercial: [*mut c_char; 96] = [ // DOOM 2 - cstr!("level 1: entryway"), - cstr!("level 2: underhalls"), - cstr!("level 3: the gantlet"), - cstr!("level 4: the focus"), - cstr!("level 5: the waste tunnels"), - cstr!("level 6: the crusher"), - cstr!("level 7: dead simple"), - cstr!("level 8: tricks and traps"), - cstr!("level 9: the pit"), - cstr!("level 10: refueling base"), - cstr!("level 11: 'o' of destruction!"), - cstr!("level 12: the factory"), - cstr!("level 13: downtown"), - cstr!("level 14: the inmost dens"), - cstr!("level 15: industrial zone"), - cstr!("level 16: suburbs"), - cstr!("level 17: tenements"), - cstr!("level 18: the courtyard"), - cstr!("level 19: the citadel"), - cstr!("level 20: gotcha!"), - cstr!("level 21: nirvana"), - cstr!("level 22: the catacombs"), - cstr!("level 23: barrels o' fun"), - cstr!("level 24: the chasm"), - cstr!("level 25: bloodfalls"), - cstr!("level 26: the abandoned mines"), - cstr!("level 27: monster condo"), - cstr!("level 28: the spirit world"), - cstr!("level 29: the living end"), - cstr!("level 30: icon of sin"), - cstr!("level 31: wolfenstein"), - cstr!("level 32: grosse"), + c"level 1: entryway".as_ptr().cast_mut(), + c"level 2: underhalls".as_ptr().cast_mut(), + c"level 3: the gantlet".as_ptr().cast_mut(), + c"level 4: the focus".as_ptr().cast_mut(), + c"level 5: the waste tunnels".as_ptr().cast_mut(), + c"level 6: the crusher".as_ptr().cast_mut(), + c"level 7: dead simple".as_ptr().cast_mut(), + c"level 8: tricks and traps".as_ptr().cast_mut(), + c"level 9: the pit".as_ptr().cast_mut(), + c"level 10: refueling base".as_ptr().cast_mut(), + c"level 11: 'o' of destruction!".as_ptr().cast_mut(), + c"level 12: the factory".as_ptr().cast_mut(), + c"level 13: downtown".as_ptr().cast_mut(), + c"level 14: the inmost dens".as_ptr().cast_mut(), + c"level 15: industrial zone".as_ptr().cast_mut(), + c"level 16: suburbs".as_ptr().cast_mut(), + c"level 17: tenements".as_ptr().cast_mut(), + c"level 18: the courtyard".as_ptr().cast_mut(), + c"level 19: the citadel".as_ptr().cast_mut(), + c"level 20: gotcha!".as_ptr().cast_mut(), + c"level 21: nirvana".as_ptr().cast_mut(), + c"level 22: the catacombs".as_ptr().cast_mut(), + c"level 23: barrels o' fun".as_ptr().cast_mut(), + c"level 24: the chasm".as_ptr().cast_mut(), + c"level 25: bloodfalls".as_ptr().cast_mut(), + c"level 26: the abandoned mines".as_ptr().cast_mut(), + c"level 27: monster condo".as_ptr().cast_mut(), + c"level 28: the spirit world".as_ptr().cast_mut(), + c"level 29: the living end".as_ptr().cast_mut(), + c"level 30: icon of sin".as_ptr().cast_mut(), + c"level 31: wolfenstein".as_ptr().cast_mut(), + c"level 32: grosse".as_ptr().cast_mut(), // Plutonia - cstr!("level 1: congo"), - cstr!("level 2: well of souls"), - cstr!("level 3: aztec"), - cstr!("level 4: caged"), - cstr!("level 5: ghost town"), - cstr!("level 6: baron's lair"), - cstr!("level 7: caughtyard"), - cstr!("level 8: realm"), - cstr!("level 9: abattoire"), - cstr!("level 10: onslaught"), - cstr!("level 11: hunted"), - cstr!("level 12: speed"), - cstr!("level 13: the crypt"), - cstr!("level 14: genesis"), - cstr!("level 15: the twilight"), - cstr!("level 16: the omen"), - cstr!("level 17: compound"), - cstr!("level 18: neurosphere"), - cstr!("level 19: nme"), - cstr!("level 20: the death domain"), - cstr!("level 21: slayer"), - cstr!("level 22: impossible mission"), - cstr!("level 23: tombstone"), - cstr!("level 24: the final frontier"), - cstr!("level 25: the temple of darkness"), - cstr!("level 26: bunker"), - cstr!("level 27: anti-christ"), - cstr!("level 28: the sewers"), - cstr!("level 29: odyssey of noises"), - cstr!("level 30: the gateway of hell"), - cstr!("level 31: cyberden"), - cstr!("level 32: go 2 it"), + c"level 1: congo".as_ptr().cast_mut(), + c"level 2: well of souls".as_ptr().cast_mut(), + c"level 3: aztec".as_ptr().cast_mut(), + c"level 4: caged".as_ptr().cast_mut(), + c"level 5: ghost town".as_ptr().cast_mut(), + c"level 6: baron's lair".as_ptr().cast_mut(), + c"level 7: caughtyard".as_ptr().cast_mut(), + c"level 8: realm".as_ptr().cast_mut(), + c"level 9: abattoire".as_ptr().cast_mut(), + c"level 10: onslaught".as_ptr().cast_mut(), + c"level 11: hunted".as_ptr().cast_mut(), + c"level 12: speed".as_ptr().cast_mut(), + c"level 13: the crypt".as_ptr().cast_mut(), + c"level 14: genesis".as_ptr().cast_mut(), + c"level 15: the twilight".as_ptr().cast_mut(), + c"level 16: the omen".as_ptr().cast_mut(), + c"level 17: compound".as_ptr().cast_mut(), + c"level 18: neurosphere".as_ptr().cast_mut(), + c"level 19: nme".as_ptr().cast_mut(), + c"level 20: the death domain".as_ptr().cast_mut(), + c"level 21: slayer".as_ptr().cast_mut(), + c"level 22: impossible mission".as_ptr().cast_mut(), + c"level 23: tombstone".as_ptr().cast_mut(), + c"level 24: the final frontier".as_ptr().cast_mut(), + c"level 25: the temple of darkness".as_ptr().cast_mut(), + c"level 26: bunker".as_ptr().cast_mut(), + c"level 27: anti-christ".as_ptr().cast_mut(), + c"level 28: the sewers".as_ptr().cast_mut(), + c"level 29: odyssey of noises".as_ptr().cast_mut(), + c"level 30: the gateway of hell".as_ptr().cast_mut(), + c"level 31: cyberden".as_ptr().cast_mut(), + c"level 32: go 2 it".as_ptr().cast_mut(), // TNT - cstr!("level 1: system control"), - cstr!("level 2: human bbq"), - cstr!("level 3: power control"), - cstr!("level 4: wormhole"), - cstr!("level 5: hanger"), - cstr!("level 6: open season"), - cstr!("level 7: prison"), - cstr!("level 8: metal"), - cstr!("level 9: stronghold"), - cstr!("level 10: redemption"), - cstr!("level 11: storage facility"), - cstr!("level 12: crater"), - cstr!("level 13: nukage processing"), - cstr!("level 14: steel works"), - cstr!("level 15: dead zone"), - cstr!("level 16: deepest reaches"), - cstr!("level 17: processing area"), - cstr!("level 18: mill"), - cstr!("level 19: shipping/respawning"), - cstr!("level 20: central processing"), - cstr!("level 21: administration center"), - cstr!("level 22: habitat"), - cstr!("level 23: lunar mining project"), - cstr!("level 24: quarry"), - cstr!("level 25: baron's den"), - cstr!("level 26: ballistyx"), - cstr!("level 27: mount pain"), - cstr!("level 28: heck"), - cstr!("level 29: river styx"), - cstr!("level 30: last call"), - cstr!("level 31: pharaoh"), - cstr!("level 32: caribbean"), + c"level 1: system control".as_ptr().cast_mut(), + c"level 2: human bbq".as_ptr().cast_mut(), + c"level 3: power control".as_ptr().cast_mut(), + c"level 4: wormhole".as_ptr().cast_mut(), + c"level 5: hanger".as_ptr().cast_mut(), + c"level 6: open season".as_ptr().cast_mut(), + c"level 7: prison".as_ptr().cast_mut(), + c"level 8: metal".as_ptr().cast_mut(), + c"level 9: stronghold".as_ptr().cast_mut(), + c"level 10: redemption".as_ptr().cast_mut(), + c"level 11: storage facility".as_ptr().cast_mut(), + c"level 12: crater".as_ptr().cast_mut(), + c"level 13: nukage processing".as_ptr().cast_mut(), + c"level 14: steel works".as_ptr().cast_mut(), + c"level 15: dead zone".as_ptr().cast_mut(), + c"level 16: deepest reaches".as_ptr().cast_mut(), + c"level 17: processing area".as_ptr().cast_mut(), + c"level 18: mill".as_ptr().cast_mut(), + c"level 19: shipping/respawning".as_ptr().cast_mut(), + c"level 20: central processing".as_ptr().cast_mut(), + c"level 21: administration center".as_ptr().cast_mut(), + c"level 22: habitat".as_ptr().cast_mut(), + c"level 23: lunar mining project".as_ptr().cast_mut(), + c"level 24: quarry".as_ptr().cast_mut(), + c"level 25: baron's den".as_ptr().cast_mut(), + c"level 26: ballistyx".as_ptr().cast_mut(), + c"level 27: mount pain".as_ptr().cast_mut(), + c"level 28: heck".as_ptr().cast_mut(), + c"level 29: river styx".as_ptr().cast_mut(), + c"level 30: last call".as_ptr().cast_mut(), + c"level 31: pharaoh".as_ptr().cast_mut(), + c"level 32: caribbean".as_ptr().cast_mut(), ]; // --------------------------------------------------------------------------- @@ -514,7 +502,7 @@ pub extern "C" fn HU_Start() { d_mode::doom2 => mapnames_commercial[(gamemap - 1) as usize], d_mode::pack_plut => mapnames_commercial[(gamemap - 1 + 32) as usize], d_mode::pack_tnt => mapnames_commercial[(gamemap - 1 + 64) as usize], - _ => cstr!("Unknown level"), + _ => c"Unknown level".as_ptr().cast_mut(), }; if gameversion == d_mode::exe_chex { @@ -674,7 +662,7 @@ pub extern "C" fn HU_Ticker() { pub extern "C" fn HU_queueChatChar(c: c_char) { unsafe { if ((head + 1) & (QUEUESIZE - 1)) == tail { - (*plr).message = cstr!("[Message unsent]"); + (*plr).message = c"[Message unsent]".as_ptr().cast_mut(); } else { chatchars[head] = c; head = (head + 1) & (QUEUESIZE - 1); @@ -765,11 +753,11 @@ pub extern "C" fn HU_Responder(ev: *mut event_t) -> c_int { } else if i == consoleplayer as usize { num_nobrainers += 1; (*plr).message = match num_nobrainers { - 1..=2 => cstr!("You mumble to yourself"), - 3..=5 => cstr!("Who's there?"), - 6..=8 => cstr!("You scare yourself"), - 9..=31 => cstr!("You start to rave"), - _ => cstr!("You've lost it..."), + 1..=2 => c"You mumble to yourself".as_ptr().cast_mut(), + 3..=5 => c"Who's there?".as_ptr().cast_mut(), + 6..=8 => c"You scare yourself".as_ptr().cast_mut(), + 9..=31 => c"You start to rave".as_ptr().cast_mut(), + _ => c"You've lost it...".as_ptr().cast_mut(), }; } } diff --git a/room/src/doom/m_argv.rs b/room/src/doom/m_argv.rs index 3e1dab94..cb886851 100644 --- a/room/src/doom/m_argv.rs +++ b/room/src/doom/m_argv.rs @@ -64,7 +64,7 @@ use crate::doom::m_misc::{M_FileLength, FILE as MiscFILE}; /// Returns the matched argument index (1..argc-num_args) or 0 if not /// present. Comparison is case-insensitive. #[no_mangle] -pub extern "C" fn M_CheckParmWithArgs(check: *mut c_char, num_args: c_int) -> c_int { +pub extern "C" fn M_CheckParmWithArgs(check: *const c_char, num_args: c_int) -> c_int { unsafe { let mut i: c_int = 1; while i < myargc - num_args { @@ -80,14 +80,14 @@ pub extern "C" fn M_CheckParmWithArgs(check: *mut c_char, num_args: c_int) -> c_ /// `boolean M_ParmExists(char *check)` — returns nonzero if `check` is /// present on the command line, 0 otherwise. #[no_mangle] -pub extern "C" fn M_ParmExists(check: *mut c_char) -> c_int { +pub extern "C" fn M_ParmExists(check: *const c_char) -> c_int { (M_CheckParm(check) != 0) as c_int } /// `int M_CheckParm(char *check)` — convenience wrapper for /// `M_CheckParmWithArgs(check, 0)`. #[no_mangle] -pub extern "C" fn M_CheckParm(check: *mut c_char) -> c_int { +pub extern "C" fn M_CheckParm(check: *const c_char) -> c_int { M_CheckParmWithArgs(check, 0) } diff --git a/room/src/doom/p_spec.rs b/room/src/doom/p_spec.rs index 472b6631..843f51f8 100644 --- a/room/src/doom/p_spec.rs +++ b/room/src/doom/p_spec.rs @@ -43,16 +43,6 @@ use crate::doom::s_sound::S_StartSound; use crate::doom::z_zone::PU_LEVSPEC; use crate::i_error; -// --------------------------------------------------------------------------- -// Macros -// --------------------------------------------------------------------------- - -macro_rules! cstr { - ($s:expr) => { - concat!($s, "\0").as_ptr() as *mut c_char - }; -} - // --------------------------------------------------------------------------- // Constants // --------------------------------------------------------------------------- @@ -204,32 +194,32 @@ mod layout_checks { /// /// Each tuple is `(istexture, endname, startname, speed)`. A sentinel entry /// with `istexture == -1` terminates the list. Pointers are created from -/// string literals via the `cstr!` macro and are valid for the program -/// lifetime. Sourced from p_spec.c `animdefs[]`. +/// C string literals and are valid for the program lifetime. Sourced from +/// p_spec.c `animdefs[]`. const ANIMDEFS: &[(c_int, *mut c_char, *mut c_char, c_int)] = &[ - (0, cstr!("NUKAGE3"), cstr!("NUKAGE1"), 8), - (0, cstr!("FWATER4"), cstr!("FWATER1"), 8), - (0, cstr!("SWATER4"), cstr!("SWATER1"), 8), - (0, cstr!("LAVA4"), cstr!("LAVA1"), 8), - (0, cstr!("BLOOD3"), cstr!("BLOOD1"), 8), - (0, cstr!("RROCK08"), cstr!("RROCK05"), 8), - (0, cstr!("SLIME04"), cstr!("SLIME01"), 8), - (0, cstr!("SLIME08"), cstr!("SLIME05"), 8), - (0, cstr!("SLIME12"), cstr!("SLIME09"), 8), - (1, cstr!("BLODGR4"), cstr!("BLODGR1"), 8), - (1, cstr!("SLADRIP3"), cstr!("SLADRIP1"), 8), - (1, cstr!("BLODRIP4"), cstr!("BLODRIP1"), 8), - (1, cstr!("FIREWALL"), cstr!("FIREWALA"), 8), - (1, cstr!("GSTFONT3"), cstr!("GSTFONT1"), 8), - (1, cstr!("FIRELAVA"), cstr!("FIRELAV3"), 8), - (1, cstr!("FIREMAG3"), cstr!("FIREMAG1"), 8), - (1, cstr!("FIREBLU2"), cstr!("FIREBLU1"), 8), - (1, cstr!("ROCKRED3"), cstr!("ROCKRED1"), 8), - (1, cstr!("BFALL4"), cstr!("BFALL1"), 8), - (1, cstr!("SFALL4"), cstr!("SFALL1"), 8), - (1, cstr!("WFALL4"), cstr!("WFALL1"), 8), - (1, cstr!("DBRAIN4"), cstr!("DBRAIN1"), 8), - (-1, cstr!(""), cstr!(""), 0), + (0, c"NUKAGE3".as_ptr().cast_mut(), c"NUKAGE1".as_ptr().cast_mut(), 8), + (0, c"FWATER4".as_ptr().cast_mut(), c"FWATER1".as_ptr().cast_mut(), 8), + (0, c"SWATER4".as_ptr().cast_mut(), c"SWATER1".as_ptr().cast_mut(), 8), + (0, c"LAVA4".as_ptr().cast_mut(), c"LAVA1".as_ptr().cast_mut(), 8), + (0, c"BLOOD3".as_ptr().cast_mut(), c"BLOOD1".as_ptr().cast_mut(), 8), + (0, c"RROCK08".as_ptr().cast_mut(), c"RROCK05".as_ptr().cast_mut(), 8), + (0, c"SLIME04".as_ptr().cast_mut(), c"SLIME01".as_ptr().cast_mut(), 8), + (0, c"SLIME08".as_ptr().cast_mut(), c"SLIME05".as_ptr().cast_mut(), 8), + (0, c"SLIME12".as_ptr().cast_mut(), c"SLIME09".as_ptr().cast_mut(), 8), + (1, c"BLODGR4".as_ptr().cast_mut(), c"BLODGR1".as_ptr().cast_mut(), 8), + (1, c"SLADRIP3".as_ptr().cast_mut(), c"SLADRIP1".as_ptr().cast_mut(), 8), + (1, c"BLODRIP4".as_ptr().cast_mut(), c"BLODRIP1".as_ptr().cast_mut(), 8), + (1, c"FIREWALL".as_ptr().cast_mut(), c"FIREWALA".as_ptr().cast_mut(), 8), + (1, c"GSTFONT3".as_ptr().cast_mut(), c"GSTFONT1".as_ptr().cast_mut(), 8), + (1, c"FIRELAVA".as_ptr().cast_mut(), c"FIRELAV3".as_ptr().cast_mut(), 8), + (1, c"FIREMAG3".as_ptr().cast_mut(), c"FIREMAG1".as_ptr().cast_mut(), 8), + (1, c"FIREBLU2".as_ptr().cast_mut(), c"FIREBLU1".as_ptr().cast_mut(), 8), + (1, c"ROCKRED3".as_ptr().cast_mut(), c"ROCKRED1".as_ptr().cast_mut(), 8), + (1, c"BFALL4".as_ptr().cast_mut(), c"BFALL1".as_ptr().cast_mut(), 8), + (1, c"SFALL4".as_ptr().cast_mut(), c"SFALL1".as_ptr().cast_mut(), 8), + (1, c"WFALL4".as_ptr().cast_mut(), c"WFALL1".as_ptr().cast_mut(), 8), + (1, c"DBRAIN4".as_ptr().cast_mut(), c"DBRAIN1".as_ptr().cast_mut(), 8), + (-1, c"".as_ptr().cast_mut(), c"".as_ptr().cast_mut(), 0), ]; // --------------------------------------------------------------------------- @@ -1244,7 +1234,7 @@ unsafe fn DonutOverrun( tmp_s3_floorheight = 0; tmp_s3_floorpic = 0x16; - let p = M_CheckParmWithArgs(cstr!("-donut"), 2); + let p = M_CheckParmWithArgs(c"-donut".as_ptr(), 2); if p > 0 { M_StrToInt( *myargv.offset((p + 1) as isize), diff --git a/room/src/doom/r_draw.rs b/room/src/doom/r_draw.rs index f741b3bb..db06a423 100644 --- a/room/src/doom/r_draw.rs +++ b/room/src/doom/r_draw.rs @@ -757,15 +757,6 @@ pub extern "C" fn R_InitBuffer(width: c_int, height: c_int) { // DEH_String shim — identity in this build // --------------------------------------------------------------------------- -/// Converts a string literal to a null-terminated `*mut c_char` pointer suitable for C FFI. -/// -/// Appends a NUL byte at compile time and casts the resulting byte slice to a C string pointer. -macro_rules! cstr { - ($s:literal) => { - concat!($s, "\0").as_ptr() as *mut c_char - }; -} - /// Identity shim for the DeHackEd string-replacement function. /// /// In the original C codebase `DEH_String` allows patch files to substitute string constants @@ -815,9 +806,9 @@ pub extern "C" fn R_FillBackScreen() { } let name = if gamemode == commercial { - DEH_String(cstr!("GRNROCK")) + DEH_String(c"GRNROCK".as_ptr()) } else { - DEH_String(cstr!("FLOOR7_2")) + DEH_String(c"FLOOR7_2".as_ptr()) }; let src = W_CacheLumpName(name, 8) as *mut u8; // PU_CACHE = 8 @@ -839,22 +830,22 @@ pub extern "C" fn R_FillBackScreen() { // Draw screen and bezel; this is done to a separate screen buffer. V_UseBuffer(background_buffer); - let mut patch = W_CacheLumpName(DEH_String(cstr!("brdr_t")), 8) as *mut patch_t; + let mut patch = W_CacheLumpName(DEH_String(c"brdr_t".as_ptr()), 8) as *mut patch_t; for x in (0..scaledviewwidth).step_by(8) { V_DrawPatch(viewwindowx + x, viewwindowy - 8, patch); } - patch = W_CacheLumpName(DEH_String(cstr!("brdr_b")), 8) as *mut patch_t; + patch = W_CacheLumpName(DEH_String(c"brdr_b".as_ptr()), 8) as *mut patch_t; for x in (0..scaledviewwidth).step_by(8) { V_DrawPatch(viewwindowx + x, viewwindowy + viewheight, patch); } - patch = W_CacheLumpName(DEH_String(cstr!("brdr_l")), 8) as *mut patch_t; + patch = W_CacheLumpName(DEH_String(c"brdr_l".as_ptr()), 8) as *mut patch_t; for y in (0..viewheight).step_by(8) { V_DrawPatch(viewwindowx - 8, viewwindowy + y, patch); } - patch = W_CacheLumpName(DEH_String(cstr!("brdr_r")), 8) as *mut patch_t; + patch = W_CacheLumpName(DEH_String(c"brdr_r".as_ptr()), 8) as *mut patch_t; for y in (0..viewheight).step_by(8) { V_DrawPatch(viewwindowx + scaledviewwidth, viewwindowy + y, patch); } @@ -863,22 +854,22 @@ pub extern "C" fn R_FillBackScreen() { V_DrawPatch( viewwindowx - 8, viewwindowy - 8, - W_CacheLumpName(DEH_String(cstr!("brdr_tl")), 8) as *mut patch_t, + W_CacheLumpName(DEH_String(c"brdr_tl".as_ptr()), 8) as *mut patch_t, ); V_DrawPatch( viewwindowx + scaledviewwidth, viewwindowy - 8, - W_CacheLumpName(DEH_String(cstr!("brdr_tr")), 8) as *mut patch_t, + W_CacheLumpName(DEH_String(c"brdr_tr".as_ptr()), 8) as *mut patch_t, ); V_DrawPatch( viewwindowx - 8, viewwindowy + viewheight, - W_CacheLumpName(DEH_String(cstr!("brdr_bl")), 8) as *mut patch_t, + W_CacheLumpName(DEH_String(c"brdr_bl".as_ptr()), 8) as *mut patch_t, ); V_DrawPatch( viewwindowx + scaledviewwidth, viewwindowy + viewheight, - W_CacheLumpName(DEH_String(cstr!("brdr_br")), 8) as *mut patch_t, + W_CacheLumpName(DEH_String(c"brdr_br".as_ptr()), 8) as *mut patch_t, ); V_RestoreBuffer(); diff --git a/room/src/doom/statdump.rs b/room/src/doom/statdump.rs index fa34d0c1..af5cd34e 100644 --- a/room/src/doom/statdump.rs +++ b/room/src/doom/statdump.rs @@ -13,7 +13,7 @@ #![allow(non_upper_case_globals, non_snake_case)] -use std::ffi::{c_char, c_int, c_void}; +use std::ffi::{c_int, c_void}; /// Snapshot of intermission-screen state captured at the end of every /// level. Mirrors the C `wbstartstruct_t` layout from `d_player.h`. @@ -90,14 +90,6 @@ static mut num_captured_stats: c_int = 0; use crate::doom::m_argv::M_ParmExists; -/// Construct a `*mut c_char` pointing at a null-terminated string literal, -/// used to pass `-statdump` to `M_ParmExists` without an extra allocation. -macro_rules! cstr { - ($s:literal) => { - concat!($s, "\0").as_ptr() as *mut c_char - }; -} - extern "C" { /// C `memcpy` from libc. Used for the bulk struct copy below; an /// `std::ptr::copy_nonoverlapping` would do equally well but the @@ -119,7 +111,7 @@ extern "C" { #[no_mangle] pub extern "C" fn StatCopy(stats: *mut wbstartstruct_t) { unsafe { - if M_ParmExists(cstr!("-statdump")) != 0 && num_captured_stats < MAX_CAPTURES as c_int { + if M_ParmExists(c"-statdump".as_ptr()) != 0 && num_captured_stats < MAX_CAPTURES as c_int { memcpy( std::ptr::addr_of_mut!(captured_stats[0]).offset(num_captured_stats as isize) as *mut c_void, diff --git a/room/src/doom/w_main.rs b/room/src/doom/w_main.rs index 6b6a4e71..312fa253 100644 --- a/room/src/doom/w_main.rs +++ b/room/src/doom/w_main.rs @@ -20,15 +20,6 @@ use crate::doom::d_iwad::D_TryFindWADByName; use crate::doom::m_argv::{myargc, myargv, M_CheckParmWithArgs}; use crate::doom::w_wad::W_AddFile; -/// Construct a `*mut c_char` pointing at a null-terminated string literal. -/// Used to pass Rust string literals to libc / FFI APIs that expect C -/// strings. -macro_rules! cstr { - ($s:literal) => { - concat!($s, "\0").as_ptr() as *mut c_char - }; -} - /// Parse `-file ...` from the command line and append each WAD to the /// lump directory. /// @@ -49,13 +40,13 @@ pub extern "C" fn W_ParseCommandLine() -> Boolean { let mut modifiedgame: Boolean = Boolean::FALSE; unsafe { - let p = M_CheckParmWithArgs(cstr!("-file"), 1); + let p = M_CheckParmWithArgs(c"-file".as_ptr(), 1); if p != 0 { let mut idx = p + 1; modifiedgame = Boolean::TRUE; while idx < myargc && **myargv.offset(idx as isize) != b'-' as c_char { let filename = D_TryFindWADByName(*myargv.offset(idx as isize)); - printf(cstr!(" adding %s\n"), filename); + printf(c" adding %s\n".as_ptr(), filename); W_AddFile(filename); idx += 1; }