1. image: download

    Here’s a fix I wanted to do for a really long time.
In the original renderer, BSP textures can be scaled, and the lighting tool does scale their lightmaps correctly, but the renderer doesn’t scale the dynamic lighting that goes on them. As seen in the top-left screenshot, this bug really screws up the dynamic lighting on the last map of the third episode.
Now it’s fixed. As far as I can remember, this was the last renderer bug affecting the original Quake game (features like skyboxes weren’t used by it, so their remaining bugs doesn’t count here).
Some other minor things were also fixed, and the Dreamcast version still need to be worked on.

    Here’s a fix I wanted to do for a really long time.

    In the original renderer, BSP textures can be scaled, and the lighting tool does scale their lightmaps correctly, but the renderer doesn’t scale the dynamic lighting that goes on them. As seen in the top-left screenshot, this bug really screws up the dynamic lighting on the last map of the third episode.

    Now it’s fixed. As far as I can remember, this was the last renderer bug affecting the original Quake game (features like skyboxes weren’t used by it, so their remaining bugs doesn’t count here).

    Some other minor things were also fixed, and the Dreamcast version still need to be worked on.

     
  2. The Dreamcast version is freezing; it seems to happen as soon as a map finishes loading.

    I’ll diff the current code against the Makaqu 1.5.1 source to see what’s happening, but my time to compile and test the DC version is limited.

     
  3. The skybox loading code is pretty much perfect now. The only thing that could be optimized further is the loading and dithering of 24/32 bit TGA images, because right now the whole image is decompressed into RAM prior to dithering. A more RAM-friendly solution would be to:

    • Decompress the first 2 lines at once,
    • converting the first one to 8-bit and sending it to the final texture in RAM,
    • while dithering the second line,
    • and then discarding the first decompressed line from the RAM,
    • decompressing the third line,
    • converting the second line to 8-bit while dithering the third one,
    • discarding the second decompressed line from RAM,
    • and so on.

    The only catch is that TGA compression allows a pack of compressed pixels to go from one line to the next one. This can be taken care of, but all things considered, optimizing the TGA loader like this isn’t a priority right now.

    One of my current priorities is to fix the skyboxes not occluding anything that’s behind regular sky surfaces. This is a really classic bug that affects most engines, including many hardware-accelerated ones. In the software renderer, there are at least two ways of fixing this.

    One is to draw just the skybox first, filling the whole screen, and then resetting the renderer while disabling only the visual output of the regular skies (but not their clipping), so everything else can be drawn in a second pass. This would work, and is quite easy to implement, but would also result in massive overdraw, slowing down the renderer.

    There’s also another way, which is a lot harder and more complicated to implement, but it should avoid most of the overdraw, if not all. I still don’t know exactly how it will turn out, but it should be far simpler than the full support for BSP translucency implemented in Makaqu 1.5.

    In other news, now the LCD screen in the Dreamcast’s VMU should be updated every time the VMU is plugged in. Previously, the engine’s icon was only being drawn in the LCD screens during startup.

    Implementing a kind of status bar in those LCD screens would be nice, and is something I’d certainly love to do, but there’s a lot of more important work to be taken care of in other parts of the engine first. But it should be done, someday.

     
  4. Fixed the stuck offscreen window bug, and a bunch of bugs in the skybox loader.

    Skybox loading was quite broken in the latest releases, due to me trying to use dynamic allocation size for the textures. Plus, the Dreamcast compiler doesn’t support a #pragma that was used on the TGA loader, so it wouldn’t load TGA textures at all. Now the dynamic allocation works really well, a few possible memory leaks were fixed, the TGA loader was reworked to not require the #pragma, so it should work in the Dreamcast (I just need to test it to be sure), and not only I’ve fixed the loading of run-length compressed TGA images, but I’ve also implemented dithering for them (the same dithering that’s already used for non-compressed TGA images).

    Some other smaller bugs were also fixed in the skybox loading code, and I’m going to examine it a little more to see if there’s anything else to fix or improve.

     
  5. Fixed another bunch of bugs, including a wrong video aspect bug when using the old status bar, which is something I hadn’t noticed before.

    Implemented support for 5 mouse buttons in the Windows version.

    Also, I’ve added a “yes/no” box to the pop-up menu, so now almost everything in the menus can be done without leaving the right hand from the mouse. The only exceptions are deleting savegames and bindings (which can only be done by using the delete and backspace keys), the whole “Video modes” menu (which I’m going to redo entirely, but not in this version), some of the Multiplayer menus, and obvious stuff like input bindings and name/console typing. Everything else can be done with the Esc key and a mouse with a wheel (which is a standard feature nowadays).

    Now the Windows version starts windowed by default again, in 640x400 (so the console background is scaled without stretching, and also to leave some room for the taskbar in computers running the desktop at 640x480) and centered in the desktop area.

    The Windows version still has one annoying bug to fix (if running in windowed mode and the window is dragged partially offscreen, it can’t be brought back), and the Dreamcast version has a few.

     
  6. I’m fixing a number of small bugs and inconsistencies now.

    The last major bug I’ve fixed is that the video mode wasn’t being changed when starting the engine. Also, now any changes to the vid_config_x and vid_config_y cvars will take place immediately.

    The engine is more stable now, but it still isn’t stable enough, so I’m not thinking about implementing any new features yet. The next version should be numbered 1.5.2.

    By not using MGL, stretched video modes are lost. Getting rid of MGL is what increased the stability of the engine, and getting rid of it also fixed the -startwindowed bug, so it was worth it. Maybe I can implement pseudo low resolution support directly in the renderer in the future, but that’s not a priority.

    Also, lit particles won’t overbright anymore. This makes the explosions looks less cool, but also makes the blood looks less cheesy.

     
  7. image: download

    This is another experiment I wanted to do for a long time.In Quake, the warping effect of turbulent surfaces (water, slime, lava, portals, etc.) is actually quite jagged, due to the way it was originally optimized. By removing those optimizations, the turbulent surfaces looks perfectly smooth when really close at high resolutions.
However, as the framerate counter shows, they also become massively slow to render; enough to drop the framerate by 2/3 in this scene, where the water isn’t even filling the whole screen. Some speed could be gained back by optimizing the code in a different way, but it wouldn’t be anywhere near enough. So, for now I’ve left this new code disabled, and can make it optional in the future.

    This is another experiment I wanted to do for a long time.

    In Quake, the warping effect of turbulent surfaces (water, slime, lava, portals, etc.) is actually quite jagged, due to the way it was originally optimized. By removing those optimizations, the turbulent surfaces looks perfectly smooth when really close at high resolutions.

    However, as the framerate counter shows, they also become massively slow to render; enough to drop the framerate by 2/3 in this scene, where the water isn’t even filling the whole screen. Some speed could be gained back by optimizing the code in a different way, but it wouldn’t be anywhere near enough. So, for now I’ve left this new code disabled, and can make it optional in the future.

     
  8. Implemented scaling for the underwater screen warping effect.

    In the previous versions of Makaqu, the screen could be rendered in hi-res when underwater, but the warping effect still wasn’t scaled.

    These four screenshots were taken at the exact same moment in the game; it was just a matter of saving the game state and loading it from the console instead of using the menu, so the game’s time got frozen because the console was active. This allowed me to accurately compare results between the current version of the code and Makaqu 1.5.1.

    The low-res warp looks different across both versions because the engines were running at 320x200. The original warping code always treats the pixels as squares, but in a CRT monitor displaying a 320x200 screen with a 4:3 aspect, the pixels are taller than wide. If you look closely, you can notice that in both low-res screens, the horizontal frequency is the same, and the vertical amplitude is also the same. It’s only the vertical frequency and the horizontal amplitude that differs. At 320x240, the warping looks exactly the same in both versions of the code.

    I’ve optimized the new code as much as I could, but it still ended up a bit slower than the original code. I could make the new algorithm optional, but since the original code is simply wrong, the new code is actually a bugfix. I can, however, reimplement the original code for 320x240 only, and make the engine use it automatically at that resolution.

     
  9. After replacing the video interface of the Windows version with one (posted at the Inside3D forums) that doesn’t use MGL, the -startwindowed bug vanished.

    This new video interface doesn’t detect some low-res modes, but I think this can be fixed. It’s also not setting the video mode correctly during startup if a windowed mode with custom dimensions is the default.

    And finally, I also need to port to it all the changes I had done in the old one.

     
  10. Here it goes. This version basically fixes all known bugs introduced by the previous two releases.

    The Dreamcast port runs out of memory when loading maps from Quake’s official mission packs, but this is due to this version requiring more RAM than all versions up to 1.3.1.

    The Dreamcast port also displayed an error message when trying to save files in the VMU when my official Jump Pack was plugged into the second slot of the controller, but it worked fine when a nameless third party Jump Pack was plugged in there instead. I’m not sure whether this is a software bug or a hardware bug yet.

     
  11. I’ve fixed all compiler warnings that appeared when compiling the Dreamcast version, and a few of those fixes should make the Windows version more stable also.

    Savegames and savestates are working; the only thing that’s not working in the Dreamcast version are configuration file saves. This is definitely a software issue, and I’ll take a closer look later on.

     
  12. The Dreamcast version seems to be working perfectly, but for some reason I’m being unable to save/load anything to/from the VMU. It does count the free space on the VMU correctly, but the saves are not showing up in the list, and it’s freezing when trying to save.

    My Dreamcast hasn’t gotten any maintenance done in the last couple years, so some hardware issues may be at hand. I’ll check the cables, try different controllers/VMUs, and so on.

     
  13. Now I’ve found a definitively good fix for the serverflags issue.

    First, an explanation about the issue:

    Quake has a rune item at the end of each episode. When you get a rune, a corresponding slot in a variable called “serverflags” is filled. This is the variable the game uses to know which runes you already have.

    This variable is saved across stages; every time you go to another stage, you take your runes with you. Inside the engine, the “changelevel” routine ensure that the values of certain variables, including the serverflags, are kept. The engine makes a copy of each of those variables, and these copies are used to restore the values of the original variables when the old stage data has been cleared and the new stage data is being loaded. So, in simple words, these copies contains the status of the player at the very moment of the beginning of the stage.

    And they’re also used to restore the status of the player when, for some reason (e.g. the player’s death), the stage is restarted. This means that the values stored in these copies are always important and should be kept in memory at all times, even after the stage has already changed and the player is already playing.

    This is why, when saving games, Quake saves not only the values stored in the original variables, but also the values stored in their copies. Both values are important.

    However, when coding Quake’s savegame system, Id Software forgot to include the value from the copy of the serverflags variable into the saves. This means that when a savegame is loaded, the game has no way to know what value the serverflags variable should be set to in case the stage is restarted.

    This causes a problem, which can be perceived as this: If you start a new game (so all slots in the copy of the serverflags are set to zero), load a savegame from when you had any runes, and die before completing the stage, when the stage is restarted all of your runes will be lost, because they’ll be set to what’s stored in the copy of the serverflags - which is zero.

    But that’s not the complete picture. When you restart a stage, the runes you currently have actually does not matter; what matters is which runes you had when exiting the previous stage. Here are two examples:

    • Get a rune, but don’t get out of the stage yet. The current value of the serverflags will indicate that you have the rune, but the copy of the serverflags should indicate that you did not have that rune when the stage started. In this case, it’s important that the value of the copy of the serverflags be different from the serverflags itself.
    • Get a rune, and get out of the stage. When the next stage is started, the current value of the serverflags will indicate that you have the rune, and the copy of the serverflags should indicate that you already had that rune when the stage started. In this case, the value of the copy of the serverflags can be equal to the current value of the serverflags - until the very moment when you get another rune, of course.

    So, the only way to fix this problem is to store the value of the copy of the serverflags into the savegames. All other copies of other variables are stored as raw values into the save files, so I did the same to the copy of the serverflags in the previous versions of Makaqu.

    But this was a really, really dumb fix.

    First, since raw values don’t have any indication of what variable they do belong to, by adding another raw value to the saves I changed the format of the saves, making them unreadable by other engines that didn’t implement the same fix.

    Second, I did not change the version number of the save files to reflect that change, so other engines have no way to know that saves from Makaqu are of a different version, and Makaqu had no way to be sure of whether a save had its fix implemented or not. This means that other engines would interpret Makaqu’s saves as corrupted, and Makaqu would interpret other engines’ saves as corrupted.

    Third, it’s not impossible to store the value of the copy of the serverflags into the save files without changing the save file format. I should have investigated this sooner.

    This is what I did now.

    In Quake, it’s possible to store comments into the entities stored into the savefiles; this is a feature intended to be used by map developers, so they can put comments in the table of entities stored into the maps, but this also works for entities from save files.

    So, what I did now is to get the world entity (which is always the first one used by the game, and is also always guaranteed to exist) and add a comment to it into the saves - a comment containing the name of the serverflags, and the value stored into the copy of the serverflags. Any other engine will just discard this comment when loading the saves, but Makaqu will now be able to detect it and load the value from that comment into the copy of the serverflags.

    By fixing the serverflags bug this way, saves created by Makaqu will now be able to be loaded by any other engine, so there’s no need to change the version number of the saves. This won’t fix the bug in other engines, but at least it ensures that the saves are compatible.

    This has already been implemented in Makaqu. I’ve also added some code to properly detect saves from previous versions of Makaqu upon loading them, but from now on all saves created by Makaqu will be compatible with other engines, so you will be able to convert saves from the previous versions of Makaqu by simply loading and saving them again.

    Now I’ll remove the leftovers from the previous fix, build and test the Dreamcast version, and package everything for the 1.5.1 release.

     
  14. The bugs in the demo loop have been taken care of. Now the transition from the Credits screens to the first demo is flawless, including the classic effect of the console background scrolling up.

    I’ve also fixed some other small bits of code here and there. The only thing I want to do now before releasing the next version is to see if I can figure out a way to reimplement the serverflags bugfix in a way that allows vanilla Quake to load the bugfixed save files.

     
  15. I’ve fixed the crashing fullscreen bug in the Windows version.

    What caused it was… the fact I’ve made the engine always start in a windowed mode. And all I had done to achieve that was commenting out a check for the -startwindowed commandline parameter during startup.

    That was weird, because when I removed that check, I essentially made the engine always act as if that parameter had been used… So I went on to check if that bug would come back if I started the engine with the -startwindowed parameter, and it did. And then I tested the -startwindowed parameter again, this time in Makaqu 1.3, and got the same crash when trying to set a fullscreen mode. And again in the version 1.2, in the version 1.1, and in the versions 1.0, 0.2 and 0.1.

    All versions of Makaqu will crash when trying to set a fullscreen video mode if the -startwindowed parameter is used. I’ve still got to test if this also happens in the vanilla WinQuake source. If it doesn’t, I can just diff its source against Makaqu 0.1 to find out what’s happening. If it does… it’s a bug of the original source release, and this makes it significantly harder to fix.

    In the meantime, I’ve made the engine ignore any fullscreen video modes if the -startwindowed parameter is used. Fullscreen video modes will only be available if the engine starts up in fullscreen - and starting up in fullscreen is the default behavior again now.

    In other news, screenshots will use the correct palette now, instead of always using the base palette. This means that the colors in any screenshots taken while underwater, picking up an item, being hit, etc. will be correct.

    Console autocorrection behavior has been reverted back to the original, and I’m fixing a few bugs in the demo loop. This should be good enough for a 1.5.1 release.