OpenRift Posted May 26, 2021 55 minutes ago, Redneckerz said: PPS: This is also a completely off-beat case ofcourse. 32 MB under DOS is enough to support insane things like BTSX, and i can't think of a Vanilla WAD that pushes more than that. But who knows. Doom64 with 64 MB heap? Doom128? :P Well, it's more meant for those vanilla WADs that do rub the zone memory a certain way, as well as limit-removing WADs that can go way beyond that. I'd imagine 64MB is probably doable without adding bytes, since it's still 2 digits (I could be completely wrong, I'm just speculating here). Honestly I wouldn't know how to do that though, since all the stuff I've done so far is changing values to ones that already exist in other EXE hacks.) I think next I'm going to take a closer look at AV.EXE included with Alien Vendetta, so I can see where they changed the par times. Honestly that would be AWESOME if we could see that put into Dehacked Special Edition some day. 1 Quote Share this post Link to post
Redneckerz Posted May 26, 2021 (edited) 12 minutes ago, OpenRift said: Well, it's more meant for those vanilla WADs that do rub the zone memory a certain way, as well as limit-removing WADs that can go way beyond that. I'd imagine 64MB is probably doable without adding bytes, since it's still 2 digits (I could be completely wrong, I'm just speculating here). Honestly I wouldn't know how to do that though, since all the stuff I've done so far is changing values to ones that already exist in other EXE hacks.) That means there is a challenge there, no? :P Quote I think next I'm going to take a closer look at AV.EXE included with Alien Vendetta, so I can see where they changed the par times. Honestly that would be AWESOME if we could see that put into Dehacked Special Edition some day. I can give some background regarding that because those par time edits were done in a seperate array. The name of the person who actually did this edit escapes me at the moment, though. Cleimos is another one of those odd releases that essentially does what DeHacked does but standalone, called CLEIMSET. Described at the Wiki. There are more obscure examples, like Doom Hockey. This is a very early (1994) example that does the following: Comes with a pre-Dehacked binary patch, PATCH.HKY, which is utitlizing an executable called HACK.EXE. PATCH.HKY is generated by a utility called Hex Hacker 1.01 and which will ''patch''/rename the Doom engine to NORMAL.EXE, utilizing similar methods like DoomHack. It is a pre-DeHacked, pre-DeusF form of patching. The WAD is utilizing a voodoo doll as a puck to implement a new game mode. Ottawa University (Or OTTAWAU) is another such WAD that does a lot of dirty hacking, as is Castle Phobos (generates a unique, Doom 1.666 based executable) Edited May 26, 2021 by Redneckerz 3 Quote Share this post Link to post
OpenRift Posted May 26, 2021 1 minute ago, Redneckerz said: I can give some background regarding that because those par time edits were done in a seperate array. The name of the person who actually did this edit escapes me at the moment, though. I'm dumb, so I don't know what an array is. Would editing this array be as simple as changing byte values or would this mean some more complicated stuff? Also looking at the AV text file, Kim AndrŠ Malde aka Mutator did the par time edits. 0 Quote Share this post Link to post
Redneckerz Posted May 26, 2021 1 minute ago, OpenRift said: I'm dumb, so I don't know what an array is. Would editing this array be as simple as changing byte values or would this mean some more complicated stuff? Array's as i understand them are rather large code table where things can be defined. Given that AV is a rather old release, i reckon that array was defined as such. Since its byte values, i guess it could be changed? Above is just an educated guess though. I can just about read a hex value, nothing more. Your crk's are informative though! 1 minute ago, OpenRift said: Also looking at the AV text file, Kim AndrŠ Malde aka Mutator did the par time edits. There ya go. That's the name that escaped me (I remembered Kim, nothing else haha) 0 Quote Share this post Link to post
OpenRift Posted May 27, 2021 Alright, so I figured out how to edit the par times, it's a lot simpler than I thought. The only caveat being that you can't set the par time above 59:59, as it will just display "SUCKS" where the time's supposed to be, akin to how if the player's time reaches 1 hour, it will says "TIME SUCKS" instead of the actual time. The following hexadecimal offsets are where the par time data starts (starting with E1M1/MAP01). The Ultimate Doom: 0009ADC4 Doom II: 00099C34 Final Doom: 0009AE38 The value at those addresses are 1E by default, which equals 30, as all the first levels in each executable have a par time of 30 seconds. 1 Quote Share this post Link to post
Doomkid Posted June 18, 2021 (edited) Hey guys, I just want to check in that UDOOM32 and FDOOM32 are the final (or at least, final-ish) of these limit-raising hacked EXEs? Do they have full Dehacked support? Just asking this stuff because I'd like to include them in the Big Vanilla Wad Pack. DOOM32.EXE has a big detailed textfile, and DOOMP.exe (which will be replaced) at least has a little txt explaining what the old limits were and what they've been raised to. Could you possibly make TXT files up for the new variants as well? I just don't want them to be uncredited, that's all. Something as simple as a document with the names of every contributor and all the raised limits would be more than sufficient! Edited June 18, 2021 by Doomkid 0 Quote Share this post Link to post
Redneckerz Posted June 18, 2021 2 hours ago, Doomkid said: Hey guys, I just want to check in that UDOOM32 and FDOOM32 are the final (or at least, final-ish) of these limit-raising hacked EXEs? FDoom32 does not raise all limits like DoomP. I believe MAXOPENINGS was not raised? I have the exact details on PC, on mobile now. And UDoom32 has a wiki page. What, you thought otherwise? :P I was wondering when you would ask these things for the BVWP. 2 hours ago, Doomkid said: Do they have full Dehacked support? Just asking this stuff because I'd like to include them in the Big Vanilla Wad Pack. UDoom32 should be the same as DoomP at least. 2 hours ago, Doomkid said: DOOM32.EXE has a big detailed textfile, and DOOMP.exe (which will be replaced) at least has a little txt explaining what the old limits were and what they've been raised to. Doom32 is more complete tho because of the increased lump stack, heapsize and OPL. Still waiting on UDOOMHACK to be finalized by @xttl... :) 2 hours ago, Doomkid said: Could you possibly make TXT files up for the new variants as well? I just don't want them to be uncredited, that's all. Something as simple as a document with the names of every contributor and all the raised limits would be more than sufficient! For UDoom32 see the wiki page. I have not put up FDoom32 yet because its not fully compatible with DoomP. I suppose FDoomSP could be there. Its just Final Doom with increased save game limits. 1 Quote Share this post Link to post
Doomkid Posted June 18, 2021 Thank you! I'll just include a full copy of the information on the Wiki page as the info. 1 Quote Share this post Link to post
Doomkid Posted July 10, 2021 Ok, so this might come off as insanely anal - but the one thing that's missing from Doom32.exe that I really wish it had is the ability to change skies on continuous play. The patched version of the Final Doom EXE (found here - DOOM2EXE_IdAnthologyPatch.zip) does have this feature, and also works perfectly with DeHackEd 3.0a "special edition" by xttl. I tried playing Doom2 (not final Doom) and everything seemed to work perfectly, and even many Doom2 mods with .DEH files worked exactly as they should, despite not being for Final Doom. The only issue I could see with this is very occasional demo de-syncs due to the bouncing lost soul effect (which isn't in the "real" doom2 v1.9) but I seriously doubt serious/competitive Doomers are going to be using this EXE to submit demos to the DSDA anyway.. As much wadding & modding as I've done, I've never actually hacked the EXE in the traditional sense - so I have no idea how to go about this, but I do have a feeling other vanilla enthusiasts might enjoy having that damn "skies never update" bug fixed in a true-vanilla EXE, and if it means bouncing lost souls come with it, then so be it. I just wanted to put this idea here, so maybe OpenRift or someone else inclined towards EXE hacking could see it, or maybe lead me in the right direction..! 1 Quote Share this post Link to post
OpenRift Posted July 10, 2021 11 hours ago, Doomkid said: Ok, so this might come off as insanely anal - but the one thing that's missing from Doom32.exe that I really wish it had is the ability to change skies on continuous play. The patched version of the Final Doom EXE (found here - DOOM2EXE_IdAnthologyPatch.zip) does have this feature, and also works perfectly with DeHackEd 3.0a "special edition" by xttl. I tried playing Doom2 (not final Doom) and everything seemed to work perfectly, and even many Doom2 mods with .DEH files worked exactly as they should, despite not being for Final Doom. The only issue I could see with this is very occasional demo de-syncs due to the bouncing lost soul effect (which isn't in the "real" doom2 v1.9) but I seriously doubt serious/competitive Doomers are going to be using this EXE to submit demos to the DSDA anyway.. As much wadding & modding as I've done, I've never actually hacked the EXE in the traditional sense - so I have no idea how to go about this, but I do have a feeling other vanilla enthusiasts might enjoy having that damn "skies never update" bug fixed in a true-vanilla EXE, and if it means bouncing lost souls come with it, then so be it. I just wanted to put this idea here, so maybe OpenRift or someone else inclined towards EXE hacking could see it, or maybe lead me in the right direction..! Honestly, I got no idea. I could've sworn that AXDOOMER's doom-patcher fixes this issue, but checking the github page, I guess not. Honestly, this would be kind of a cool feature to have baked into a "real" doom2 1.9 EXE. I got no idea how to do that though. What I would want the most is probably a tutti-frutti fix, because that's a really common problem that occurs with limit-removing WADs, since people are most likely doing their testing with Crispy Doom anyway, which fixes that, so mappers would never even know. 1 Quote Share this post Link to post
OpenRift Posted October 21, 2021 So little update since last time I posted here: I figured out how to to get custom par times for vanilla, and made a little guide on how to do that! Also, I've recently been messing around with making custom EXEs for HacX and Rekkr (for v1.16, Sunken Land doesn't work in DOS for some reason, despite working in Chocolate). For HacX, I've added the custom quit messages found in the IWAD's LANGUAGE lump. For whatever reason, it there never was any custom par times (it specified par times in the MAPINFO lump, but they're identical to the vanilla par times), so I just left those alone. For REKKR, I was able to change both quit messages and par times, as well as removing all text string references to Doom via dehacked, similar to how HacX's dehacked patch does it, which makes it feel more like its own thing. In addition to those, I've also made some Hex edited versions of the SERSETUP, IPXSETUP, and SETUP EXEs with proper labelling for the respective games. I'm not sure if I'm ready to upload the REKKR package yet, but I'll probably upload the HacX package soon. 3 Quote Share this post Link to post
Noiser Posted October 21, 2021 (edited) I'm looking forward for these! I've beeing playing some games on DOSBox recently and REKKR with a proper stand-alone presentation will be an awesome addition (The same for HacX). Edited October 21, 2021 by Noiser 1 Quote Share this post Link to post
Redneckerz Posted October 21, 2021 @OpenRiftRELEASE, RELEASE!!! :P 1 Quote Share this post Link to post
OpenRift Posted February 8, 2022 This might have just made EXE hacks extinct: @xttl, I think your job may have just gotten a whole lot easier ;) 1 Quote Share this post Link to post
Gibbon Posted February 10, 2022 On 2/8/2022 at 7:36 PM, OpenRift said: This might have just made EXE hacks extinct: @xttl, I think your job may have just gotten a whole lot easier ;) Already done :P https://github.com/atsb/DOOM128/releases/tag/10020222 5 Quote Share this post Link to post
Edw590 Posted February 17, 2022 (edited) @xttl Hi. I just created an account here to say thank you. For a beginner on reverse engineering like me, seems this thread should probably be archived ahah (I'll do it on my own way at least). So THANK YOU!!! I'm messing with Fallout 1 DOS EXE (which is also a Linear Executable LE EXE) and this was exactly what I needed to know!!! I can now patch functions in run-time because of this idea of giving the function the addresses of the segments!!! I had just found out what relocations were and then I understood the reason why it was working on the PC and not on the tablet (didn't seem to make much logic until I learned this). I was thinking in making some automated tool to add things to the relocation table, but then I found this piece of gold. So, thank you again. On 12/7/2018 at 4:45 PM, xttl said: Well, now I finally looked at the linker output instead and in the end it turned out it isn't difficult at all to make this work at least on the level seen in the previous post. It's really fortunate that Open Watcom can make PE DLLs if you select the win95 or nt target, it's such a nice and easy format to parse compared to OMF32 or LE/LX, and then I just had to figure out ways to work around the fact that I don't have any kind of runtime dynamic rebasing loader yet in the C code. I cannot really replace ingame functions from compiled code yet though, because how would I pass the pointers to the vars/funcs structs to some code that isn't called from the start function without resorting to doing something silly, like storing them to some fixed address in low DOS memory, video memory or elsewhere where I could maybe get away with it, for later access? About this, I just wanted to give you (and/or to anyone else) an idea, which I don't know if you already thought of or not (in case you're still at this though - I read the entire thread, so no idea if you're still on this or not). The idea is very simple actually, and seems to have worked here. As a start I'm doing something which came to my mind (and that I believe you mentioned around the thread, no idea where? Or I'm confusing with something else), which is to write on the code section the 3 addresses: the allocated block address, the code section address, and the data section address. Then, every time before you call the functions in the external file, before calling the function you want, push the ESI and EDI, call the next instruction, you just need to do: call $+5 pop esi mov esi, [esi+offset from the previous instruction to where the Code section address is] mov edi, [esi+IDA offset to where the Data section address is] call [esi+IDA offset to where the allocated block address is] Or if you want to go to somewhere specific, put add edx, [whatever] after the last mov. This way I was able to patch a string address from the allocated block code! First time I patched stuff in run-time ahah. [Btw, I'm thinking in just appending to the end of the EXE, which if I remember correctly, won't do anything bad because the header says the last page ends at a specific place and then everything else is just ignored(?). And this way I don't need to have another file around. I know where the the last page ends, so I can put everything else on the allocated block.] Note: I'm storing the addresses in the code section because I don't know which parts of the data section are not used. And there are about 3k null bytes in the last code section page, so I extended the section and started writing there. I also still need to set the section as writable. I haven't done it and it still works (like it did with you as you wrote somewhere here). Not sure why though (the loaders don't like to read!?), but ok. Thank you again! You just spared me a LOT of work moving the EXE contents down to add bytes to the tables and other awful stuff (and gave me some more ideas to the pack in case I ever need again ahah). Seems "DLL injection" works here xD (kind of). Never messed with that (yet, at least), but I think that's how it works, if I'm not mistaken. EDIT: I think one can even do something like this. Spoiler ... loader: (...) ; Supposing ESI containing the Code section address, EDI the Data section address, and EDX the allocated block address mov [edx], esi ; First store the Code section address for faster access(?) mov [edx+4], edi ; Second store the Data section address (the 2nd to be more called) ; The third 4 bytes will also be needed to store the original ESI each time an external function is called, ; which is the least one to be used - only on the function return, hopefully. (...) ... call codecave1 ... ext_funcs_prep: push eax ; Save the external file parameter call $+5 pop eax lea eax, [eax+fixed offset from the previous instruction to where the allocated block address is] mov [eax+8], esi ; Save the original ESI xchg esi, eax ; Store the block address in ESI (useful to the external functions) pop eax ; Here we have the external file parameter again add eax, [esi+12+eax] jmp eax ; Or in case it's a function parameter, no EAX on the ADD ... codecave1: push eax ; Below, a number to sum to the allocated block address or a function number so a main external function can call ; the correct function (in my opinion, if it can be done which I think it can unless I'm missing something, it's ; more general and easier in case you change the functions on the external file, along with their side) mov eax, 123489h jmp ext_funcs_prep ... This way you just need to CALL codecave or JMP to it (where you choose which function to execute on the external file or do other things, for example), and then only use JMPs here on the code above so when you RETurn from the external file (if it was a CALL), you go directly to where you were when you called codecave. Or you can just JMP to the codecave and keep the stack anyway (and then just use a JMP to where you want, though it must be with an absolute address with the Code section address help). Just don't forget of POPing EAX inside the function you called so the stack (and the register) can get back to normal. No idea if this is still useful for here xD, but in case it is, it's here. EDIT 2: actually one can just store the address of the allocated block address and keep the Code section and Data section addresses in the beginning of the block too. If I'm not missing anything, that would save using either ESI or EDI. Only one would be needed (to store the block address). You'd have more instructions to go on memory get the addresses though, but one more register would be available. I've edited the code to have this idea in mind. When you leave the external file, you need to reset the ESI register through the allocated block. This way the stack remains intact (less bugs and less hating life? xD). EDIT 3: to answer another thing, you can have the loader wherever you want, not just on some specific place. You just need to have it in a fixed place (as it should anyway), and then subtract the IDA address from the address after the call instruction. I'm doing that right now. I call the loader from more or less the beginning of main() with a call, and inside I figure out where I am (same idea as I said above, just applied to the loader). EDIT 5: I think one could even get the patcher to patch itself xD. Would make the code above and the need to call that function every time a hack is needed, not needed at all. When the patcher is first called, it patches itself, so next times when it gets called from the functions, it already has the correct addresses on it. I'll try to go this route (seems simpler). Edited February 18, 2022 by DADi590 3 Quote Share this post Link to post
xttl Posted February 18, 2022 (edited) @DADi590 I don't know if you've already found out about it, but some time ago a proper hacker going by the name kgsws figured out a way to get code exec from a PWAD at map load time in vanilla Doom (with some suitably corrupted map data), and developed a simple "framework" (if you can call it that) for patching the game with compiled C code so that this exploit could be more easily used to do some interesting and even flashy stuff from a PWAD. See this thread Also see this github repo https://github.com/kgsws/doom_ace and especially this branch https://github.com/kgsws/doom_ace/tree/doom2_ace The last linked example patches the game in memory to add (limited) ZDoom DECORATE support to it, but of course you could even replace the whole game in memory if you wanted to, or conversely only do some much smaller changes. Might be worth looking into it, at least if you don't mind using gcc instead of Open Watcom to compile your code and the AT&T syntax for x86 asm GNU tools insist on sticking with. :P It seems you'll also have to write small asm wrappers for all functions from the main game binary your patch code calls, at least if the binary was built using the fast register-based calling convention (up to 4 args passed via regs, it seems gcc simply cannot be easily told to do this) Watcom offers. Does Fallout have some stack pushes before pretty much every function call, or just before printf & friends and some other rare exceptions? Instead of exploiting the game and putting the loader code in the REJECT lump of a map, just permanently patch the provided loader code into the game binary and adapt it slightly where necessary (as in read the code blob from somewhere other than a PWAD lump). I know if I ever return (unlikely any time soon) to tinkering around with this crap I'll just take kgsws' stuff and be done with it. 16 hours ago, DADi590 said: [Btw, I'm thinking in just appending to the end of the EXE, which if I remember correctly, won't do anything bad because the header says the last page ends at a specific place and then everything else is just ignored(?). And this way I don't need to have another file around. I know where the the last page ends, so I can put everything else on the allocated block.] Yes, anything you attach to the end of the EXE file should be completely ignored by the loader in DOS4GW (or workalike) unless you make some corresponding LE header edits. Edited February 18, 2022 by xttl 1 Quote Share this post Link to post
Edw590 Posted February 18, 2022 (edited) Ah then it's no longer needed. No problem, at least shared the idea xD. With a quick overview, the idea of the hack seems to be so that it's not needed to patch the EXE? Or the main idea is another one? If it's to remove patching (and since I cannot use that exploit because it's for Doom(?)), then is there any difference between your original approach and the one you just described? (Because I still have to permanently patch and have wrappers) If it's not really about this, never mind. I'll have to properly read the loader code some time and understand what's happening there decently. Will have a look for sure though! Will save the link along with the patches on my PC. Thank you! AT&T syntax is kind of awful for me, but if it's needed, required and mandatory 😂, what can I do ahahah. Fallout seems to have everything passed on registers, except when there's a string involved (then its address gets pushed into the stack). So might mean hard way ahah. [I don't follow Doom things at all (never even played any Doom ahah), so I didn't know about that or anything else anyway. Some day I'll play a game to see what that's all about, but for now I haven't done it yet.] PS: about what you said of using wrappers to every function call. (Why do you say that btw? Sorry, I didn't get it. If it's just a call, why have a wrapper, and btw doing what inside?) The EDIT 5 of my previous message (about which I've been thinking all day ahahah) seem to have a way of me not having to need any wrapper, or actually even needing to store anything in the code segment at all. The loader calls the BIN file on a place of the main external function. That function reads the block itself and patches all absolute references according to the given code and data section addresses. After that, it actually patches the EXE with the values that were just patched on it --> the patch patches itself before it can patch the EXE ahahah. Not sure if this works, but in my head it seems to. This way I wouldn't need to store the block address (I won't need it anymore), or the code and data section addresses. Only if I want to free() the block in the exit (will have to see how bad it is if I don't free it... On Windows would be fine, on DOS might not be, but still, one just would have to restart the VM after exiting the game and that's it, I guess). EDIT: FYI, I just found out GCC can understand Intel x86 syntax if you give this compiling flag: -masm=intel (https://stackoverflow.com/questions/199966). EDIT 2: IT WORKS!!!!!! The patch is patching itself!!! I've managed to call a function that calls printf() and exit() from inside the external code without giving that function ANYthing at all!!!!! No need for any wrappers it seems!!! Just made my life easier xD aside from having learned a bit more!!! (Unless there are alternatives? So far this is the only way I've seen without needing wrappers for every patch function call. At least without some exploit or something(?)). EDIT 3: also, if what I just thought works, one can have global variables and strings placed in whatever segment!!! No more local variables-only thing nor creating strings on the stack with manual assignment with chars by index (awful ahahah) nor code-segment-only programming or whatever limitations!!!! Just make a normal program with normal flags and all shouod work! Will test this tomorrow... Edited February 19, 2022 by DADi590 0 Quote Share this post Link to post
Edw590 Posted February 20, 2022 (edited) So, in case it's useful to know here, this really seems to be possible! (In case this wasn't already known? At least in this thread I didn't see that, but no idea about other places - I don't follow Doom things, because I never played, at least yet.) Finished testing now. The patch patches itself to have the correct addresses, and then patches the EXE (calls, jumps, other values, anything) and when you call the patch's functions from the EXE, you don't need to pass any parameters! The contents of the BIN file remain in memory so that the EXE can jump or call or read its contents wherever it wants. It can jump or call to the EXE functions, and if inside the BIN file those functions need references to the EXE, they have them all already and there's no need to pass parameters. Just do the patch normally without thinking in passing parameters specifically for segment addresses and other stuff (not even my idea of function parameter to know which one to execute --> the EXE just calls the functions on the BIN file, because the patch patches the EXE's jumps and calls to go to the BIN file functions). One can also have global variables/strings and use the data segment and whatever segment is needed and the code will run just fine. I haven't made any patches to the EXE yet, but I've been testing from the call to the patch from the loader. The test function I'm using is a naked function and I pass no parameters to it at all. I managed to call printf from it to print a string in the EXE's data segment ("FALLOUT %p.%p") with the code and data segment addresses as parameters, print a "Hi!" string in the data segment of the BIN file, print a global int value in the BIN file's data segment (with "%d", also on the BIN file's data segment), then increment it and print it again, and call exit(), and all worked perfectly!!! (Being printf() and exit() functions from inside the EXE.) I can also call the EXE's functions from C. I made C functions with the same signature as the original standard ones with an Assembly implementation and I opened a file, read its contents to a local C variable and closed the file. In this case I can even put the patches to be choosable inside an INI file and let people edit the file easily to choose which patches they want applied! So I think this can be used exactly like DLL injection! You load it, let it be loaded, access stuff from inside its memory space, call its functions with references to the EXE's functions, whatever else you want. Not sure if this has any use here though, but at least for a beginner on these things seems to be wow ahahah. I'll still have to check the loader on the repo though. But I'll leave that to later as I'm having too much fun/excitement finding out these things right now ahah. PS: this doesn't mess on how the BIN file is loaded to memory. It just needs to pass 3 addresses in 3 registers or pass one of them and store the others in the block and the rest it's however the loader is implemented. I haven't touched the loader since I began trying these things. It's still loading as I left it 2 days ago or something. Update: just wanted to add a week later that it's no longer PoC. I'm patching a game function call to an external function. That function uses data and other functions from the game EXE. It also uses 2 external strings. I pass no parameters to it and I use only EDI to calculate all relocations, and I push and pop it every time (or if EDI is already in use, then ESI - 2 registers not much used and that are not used in Watcom's calling convention, and btw, EDI seems to be the less used one of the 2). All works perfectly! More ahead I'll have an external function calling another external function. And that will also work. If it's useful, I'm publising the code here: https://github.com/Edw590/F1DP. Thank you again xttl for all your published knowledge!!! EDIT: I made improvements to the explanation (no idea how many, it was months ago) in the GitHub link I've put above. Edited October 16, 2023 by Edw590 1 Quote Share this post Link to post
_delete my account_ Posted May 25, 2022 (edited) On 5/26/2021 at 10:39 PM, OpenRift said: Final Doom fdoom32.zip The Ultimate Doom udoom32.zip UDOOM32 also comes with all the limit increases seen in Doom-plus. FDOOM32's heapsize increase should be especially helpful on Urania, because I know that one can have zone memory issues if you try to save in certain situations (not like a savegame size limit overflow), akin to some points in Back to Saturn X Episode 2. Hi, I applied a patch for sound pitch on FDoom32 and after that I can't save in the game. It just crashes. In the dosbox, the console displays an error: DYNX86: can’t run code in this page! Patch for sound pitch: 56A88: 58FEFFFF[E9CA000000]128B6B 5DAC8: DE8B[54]240889[CB]833D Edited May 25, 2022 by Angel Of Nemesis 0 Quote Share this post Link to post
OpenRift Posted May 25, 2022 (edited) On 5/25/2022 at 7:17 AM, Angel Of Nemesis said: Hi, I applied a patch for sound pitch on FDoom32 and after that I can't save in the game. It just crashes. In the dosbox, the console displays an error: DYNX86: can’t run code in this page! Patch for sound pitch: 56A88: 58FEFFFF[E9CA000000]128B6B 5DAC8: DE8B[54]240889[CB]833D Can't really help you with that, I don't even know how to re-enable that sort of thing anyway. EDIT: For those who are having savegame issues in DOSBox, set your memsize to 63 in your .conf file, this should allow you to save the game without issue. (so sorry for the year and a half late reply lol) Edited January 10, 2023 by OpenRift 0 Quote Share this post Link to post
Never_Again Posted January 10, 2023 (edited) On 5/26/2021 at 3:39 PM, OpenRift said: [...] Final Doom fdoom32.zip The Ultimate Doom udoom32.zip [...] On 5/25/2022 at 7:17 AM, Angel Of Nemesis said: Hi, I applied a patch for sound pitch on FDoom32 and after that I can't save in the game. It just crashes. In the dosbox, the console displays an error: DYNX86: can’t run code in this page! Patch for sound pitch: 56A88: 58FEFFFF[E9CA000000]128B6B 5DAC8: DE8B[54]240889[CB]833D You were off by four bytes. Here is a table of the two series of bytes to be replaced (+ their offsets) for all versions starting with v1.666: v1.666 D1 510EF v1.666 D2 510DF v1.7/v1.7a 510CF v1.8/v1.9 5628C v1.9u 5648C v1.9f 56A8C 8B 59 1A 8B 71 -> E9 CA 00 00 00 v1.666 D1 5728A v1.666 D2 5727A v1.7/v1.7a 5726A v1.8/v1.9 5D2CA v1.9u 5D4CA v1.9f 5DACA 5C 24 08 89 CA -> 54 24 08 89 CB Some notes: the execs for v1.666 are different for D1 and D2 v1.7 and v1.7a are D2-only v1.8 and v1.9 for D1 and D2 are all the same exec v1.9u is Ultimate Doom the offsets for v1.9f are good for both Final Doom versions as the execs are the same length the v1.4-v1.6 betas don't have those two sequences of bytes, so some more disassembling needs to be done Edited January 10, 2023 by Never_Again added notes 4 Quote Share this post Link to post
Never_Again Posted January 14, 2023 DISABLE Q KEY DURING RECORDING v1.0 : 4DE62 v1.1 : 4F19E v1.9u disassembly v1.2 : 4DCD1 v1.4 : 58186 cseg01:00031910 G_WriteDemoTiccmd proc near v1.5 : 5A546 cseg01:00031910 push ebx v1.6 : 5AF96 cseg01:00031911 push ecx v1.666 : 5D776 D2 cseg01:00031912 push edx v1.666 : 5D86C D1 cseg01:00031913 mov ebx, dword_9B74C v1.7a : 5D776 cseg01:00031919 mov edx, eax v1.8/v1.9 : 638F6 cseg01:0003191B cmp dword_9AE18, 0 v1.9u : 63B36 ———————> cseg01:00031922 jz short loc_31929 v1.9f : 64416 cseg01:00031924 call G_CheckDemoStatus v1.9fa : 64456 74 05 E8 -> EB 05 E8 Based on @axdoomer's collection of hacks doom-patcher and extended to cover all versions. A disassembly extract is included to illustrate what this does. And what it does is replace the jump-if-zero operand with an unconditional jmp thus skipping the G_CheckDemoStatus check. 1 Quote Share this post Link to post
Never_Again Posted January 14, 2023 (edited) REMAP ANY1 KEY TO ANY OTHER v1.9 Spoiler 899DD ESC 1B │ 899F8 ENTER 71 │ 89A14 ALT B8 899DE 1 31 │ 899F9 CTRL 9D │ 89A15 SPACE 20 899DF 2 32 │ 899FA A 61 │ 89A17 F1 BB 899E0 3 33 │ 899FB S 73 │ 89A18 F2 BC 899E1 4 34 │ 899FC D 64 │ 89A19 F3 BD 899E2 5 35 │ 899FD F 66 │ 89A1A F4 BE 899E3 6 36 │ 899FE G 67 │ 89A1B F5 BF 899E4 7 37 │ 899FF H 68 │ 89A1C F6 C0 899E5 8 38 │ 89A00 J 6A │ 89A1D F7 C1 899E6 9 39 │ 89A01 K 6B │ 89A1E F8 C2 899E7 0 30 │ 89A02 L 6C │ 89A1F F9 C3 899E8 - 2D │ 89A03 ; 3B │ 89A20 F10 C4 899E9 = 3D │ 89A04 APOSTROPHE 27 │ 89A23 HOME C7 899EA BACKSPACE 7F │ 89A05 ~ 60 │ 89A25 PGUP C9 899EB TAB 09 │ 89A07 \ 5C │ 89A26 NUMPAD- 2D 899EC Q 71 │ 89A08 Z 7A │ 89A28 NUMPAD5 35 899ED W 77 │ 89A09 X 78 │ 8AC2A NUMPAD+ 2B 899EE E 65 │ 89A0A C 63 │ 8AC2B END CF 899EF R 72 │ 89A0B V 76 │ 89A2D PGDN D1 899F0 T 74 │ 89A0C B 62 │ 89A2E INS D2 899F1 Y 79 │ 89A0D N 6E │ 89A2F DEL D3 899F2 U 75 │ 89A0E M 6D │ 89A33 F11 D7 899F3 I 69 │ 89A0F COMMA 2C │ 89A34 F12 D8 899F4 O 6F │ 89A10 PERIOD 2E │ 899F5 P 70 │ 89A11 / 2F │ 899F6 [ 5B │ 89A12 RSHIFT B6 │ 899F7 ] 5D │ 89A13 NUMPAD* 2A │ v1.9u Spoiler 8ABDD ESC 1B │ 8ABF8 ENTER 0D │ 8AC14 ALT B8 8ABDE 1 31 │ 8ABF9 CTRL 9D │ 8AC15 SPACE 20 8ABDF 2 32 │ 8ABFA A 61 │ 8AC17 F1 BB 8ABE0 3 33 │ 8ABFB S 73 │ 8AC18 F2 BC 8ABE1 4 34 │ 8ABFC D 64 │ 8AC19 F3 BD 8ABE2 5 35 │ 8ABFD F 66 │ 8AC1A F4 BE 8ABE3 6 36 │ 8ABFE G 67 │ 8AC1B F5 BF 8ABE4 7 37 │ 8ABFF H 68 │ 8AC1C F6 C0 8ABE5 8 38 │ 8AC00 J 6A │ 8AC1D F7 C1 8ABE6 9 39 │ 8AC01 K 6B │ 8AC1E F8 C2 8ABE7 0 30 │ 8AC02 L 6C │ 8AC1F F9 C3 8ABE8 - 2D │ 8AC03 ; 3B │ 8AC20 F10 C4 8ABE9 = 3D │ 8AC04 APOSTROPHE 27 │ 8AC23 HOME C7 8ABEA BACKSPACE 7F │ 8AC05 ~ 60 │ 8AC25 PGUP C9 8ABEB TAB 09 │ 8AC07 \ 5C │ 8AC26 NUMPAD- 2D 8ABEC Q 71 │ 8AC08 Z 7A │ 8AC28 NUMPAD5 35 8ABED W 77 │ 8AC09 X 78 │ 8AC2A NUMPAD+ 2B 8ABEE E 65 │ 8AC0A C 63 │ 8AC2B END CF 8ABEF R 72 │ 8AC0B V 76 │ 8AC2D PGDN D1 8ABF0 T 74 │ 8AC0C B 62 │ 8AC2E INS D2 8ABF1 Y 79 │ 8AC0D N 6E │ 8AC2F DEL D3 8ABF2 U 75 │ 8AC0E M 6D │ 8AC33 F11 D7 8ABF3 I 69 │ 8AC0F COMMA 2C │ 8AC34 F12 D8 8ABF4 O 6F │ 8AC10 PERIOD 2E │ 8ABF5 P 70 │ 8AC11 / 2F │ 8ABF6 [ 5B │ 8AC12 RSHIFT B6 │ 8ABF7 ] 5D │ 8AC13 NUMPAD* 2A │ v1.9f Spoiler 8B1DD ESC 1B │ 8B1F8 ENTER 71 │ 8B214 ALT B8 8B1DE 1 31 │ 8B1F9 CTRL 9D │ 8B215 SPACE 20 8B1DF 2 32 │ 8B1FA A 61 │ 8B217 F1 BB 8B1E0 3 33 │ 8B1FB S 73 │ 8B218 F2 BC 8B1E1 4 34 │ 8B1FC D 64 │ 8B219 F3 BD 8B1E2 5 35 │ 8B1FD F 66 │ 8B21A F4 BE 8B1E3 6 36 │ 8B1FE G 67 │ 8B21B F5 BF 8B1E4 7 37 │ 8B1FF H 68 │ 8B21C F6 C0 8B1E5 8 38 │ 8B200 J 6A │ 8B21D F7 C1 8B1E6 9 39 │ 8B201 K 6B │ 8B21E F8 C2 8B1E7 0 30 │ 8B202 L 6C │ 8B21F F9 C3 8B1E8 - 2D │ 8B203 ; 3B │ 8B220 F10 C4 8B1E9 = 3D │ 8B204 APOSTROPHE 27 │ 8B223 HOME C7 8B1EA BACKSPACE 7F │ 8B205 ~ 60 │ 8B225 PGUP C9 8B1EB TAB 09 │ 8B207 \ 5C │ 8B226 NUMPAD- 2D 8B1EC Q 71 │ 8B208 Z 7A │ 8B228 NUMPAD5 35 8B1ED W 77 │ 8B209 X 78 │ 8B22A NUMPAD+ 2B 8B1EE E 65 │ 8B20A C 63 │ 8B22B END CF 8B1EF R 72 │ 8B20B V 76 │ 8B22D PGDN D1 8B1F0 T 74 │ 8B20C B 62 │ 8B22E INS D2 8B1F1 Y 79 │ 8B20D N 6E │ 8B22F DEL D3 8B1F2 U 75 │ 8B20E M 6D │ 8B233 F11 D7 8B1F3 I 69 │ 8B20F COMMA 2C │ 8B234 F12 D8 8B1F4 O 6F │ 8B210 PERIOD 2E │ 8B1F5 P 70 │ 8B211 / 2F │ 8B1F6 [ 5B │ 8B212 RSHIFT B6 │ 8B1F7 ] 5D │ 8B213 NUMPAD* 2A │ Format: offset (in hex) - key - default value (in hex) v1.0 77435 (-125A8) │ v1.6 7FF6D (-9A70) v1.1 74F11 (-14ACC) │ v1.666/v1.7a 8436D (-5670) v1.2 74B21 (-14EBC) │ v1.8/v1.9 899DD v1.4 7CC2D (-CDB0) │ v1.9u 8ABDD v1.5 7F86D (-A170) │ v1.9f 8B1DD And this is the list of offsets to the start of the keymap for all versions, sourced from the scantokey array (i_ibm.c). The negative numbers are the difference between that version and v1.9. So if you want, for example, to find the offset for the tilde (~) key in v1.1 you take tilde's v1.9 offset (from the first table above) and subtract v1.1's number in parenthesis from it: 89A05 - 14ACC == 74F39. That byte's value should be 0x60. Change that to 0x71 to quit recording demos with, or to 0x09 to switch to the automap. And so on. The array is 128 bytes long, with 82 key assignments; the rest is null bytes. Of the assigned keys five resisted all my attempts at remapping them: 89A06 LSHIFT FE 89A24 UPARROW AD 89A27 LEFTARROW AC 89A29 RIGHTARROW AE 89A2C DOWNARROW AF Ditto for the rest of the NUMPAD keys, PRNTSCR and SCROLLOCK. And then there's a peculiar case of the null byte immediately after the F10 key: 89A21 PAUSE/NUMLOCK 00 Changing that byte from 0x00 produces interesting results. For example, set it to 0x71. Now you can quit recording with the PAUSE key, with no pause added to the demo. Or you could use NUMLOCK, except that you'll need to press it twice if the NUMLOCK is ON. Set the byte to 0x09 and now switching to the automap will pause the game until you switch back to the normal view. Accessing the automap with the NUMLOCK key is even more bizarre: the first press makes the game alternate rapidly between the normal view and the automap; the second press settles the view on the automap. Another press and the flutter is back, etc. Worth a look, but probably too quirky for regular use. Multiple keys can be set to the same action. To disable a key set its byte to 0x00. Watch out for unexpected side effects. Like, if you swap the pistol and the BFG keys then entering IDCLEV17 in D2 will take you to MAP12 instead of MAP17. Edited January 14, 2023 by Never_Again 0 Quote Share this post Link to post
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.