Previous parts:
one ,
two ,
three .
Thank you for the game!
In the first part of
Wing Commander, when we got out of the game, we received an exception from our EMM386 memory manager. The screen was cleared and a single line was displayed on it, something like “Error of EMM386 memory manager. Blah blah blah".
We needed to release the game as quickly as possible, so I edited the memory manager’s error in the hex editor to make it look like “Thank you for playing
Wing Commander ”.
')
- Ken Demarest100% pure fruit juices
When I first started working in the gaming industry, most of the time I worked in various small, sparingly funded startups. Here is a horror story from those times when men were men and used DirectX 7. I worked for a company that the publisher forced to use a specific 3D engine. I will not call him, but the publisher claimed that he had bought a bunch of licenses for him in a major licensing deal, so he insisted on using it.
Let's face it - the engine did not work, and most of the time working at the company I was engaged in teaching the 3D engine how to do obvious things correctly, such as implementing a single pass overlay of lightmaps from several textures.
One of the most interesting things that didn't work was the BSP compiler. Level designers created the geometry of the levels with the correct visibility, after which minor changes in the geometry violated the areas of visibility in a completely different part of the map. I still don’t know why this happened, but I suppose that the BSP engine compiler added brushes to the BSP tree in random order and certain combinations ... just broke everything in an arbitrary way.
At that time I did not hear about the randomized algorithm, but nevertheless I invented it - we added a preprocessing stage to the BSP compiler, which mixed the order of the brushes before transferring them to the BSP compiler. If the level geometry broke in the BSP compiler, we simply tried to shuffle the brushes with other random numbers until we found a working combination and stuck to it until the BSP compiler broke again.
The game itself was a disaster - and the engine, and the game fell into the comic Penny Arcade, in which
Fruitf * cker 2000 first appeared. This remains an important part of my career.
- Nicholas ViningFlash forward
I worked on
NBA JAM TE for the Sega Genesis, which used a flash chip to save game data. The game was tested for several months, and everything was ready for release, so the publisher ordered 250,000 copies of the cartridges. But it soon became obvious that no one had dropped flash chips on test cartridges for many months in order to check the correctness of the flash memory initialization procedures. And no one ordered the cartridges for testing.
Only after ordering all the cartridges, we found that the flash initialization code had died, and the cartridges could not save the games correctly! The whole studio went mad, trying to figure out how to release 250 thousand broken cartridges. We tried to implement the recommendations of the manufacturers, adding additional resistors and other hacks, but nothing helped.
When everything seemed lost, someone found out that if you play games in a very strange and well-defined order, then the flash memory seems to start working. Therefore, a leaflet with a description of how to use this feature has been attached to each box with a cartridge.
- Chris KirbySmoke
My favorite "last minute hack" was used in the four-player mode of the game
Nitrobike for PS2. As usual, level designers and artists did their work, not realizing in the least how real it is in the real world, and, as usual, they completely left me to complete the game.
After a lot of disputes and collisions, I made them simplify the level graphics, create visually hidden areas and remove unnecessary dynamic objects. But this could not save one particular level with cinematic themes. The design of the level itself resisted the concealment of excess - it consisted of two huge rooms (according to the plot - recording pavilions), which did not overlap and were connected by two open doors.
One door was in the middle of the wall. There was no way to build overlapping polygons to block one room so that it could not be seen from another, as there were no ways to remove any level graphics without destroying its style. I needed to find a way to substitute one large polygon overlying the middle wall onto the wall. And then it dawned on me - the “wall of smoke” from particles, closing the middle door, will be well combined with the level in film themes and will completely solve my problem.
A wall of smoke can be passed through, but not seen through it, and it will hide the existence of my overlapping polygon! I had the opportunity to take one artist myself to create such an emitter and one level designer in order to position the emitters on both sides of the door.
Finally, in the middle, I inserted one very large overlapping polygon. It looked good and fixed the last problem with speed levels.
- Stephen Boswell II... maybe here?
I have been writing games for more than 20 years, and recently worked as a technical manager at THQ, so I saw enough of all sorts of terrible hacks. But there is one that I still laugh at. It happened with Beam Software in the early 1990s.
In that era, when there were no convenient IDEs and smart compilers, we wrote all the games in assembly language. All .s files contained the corresponding assembly code for individual parts of the game: creature1.s, collision.s, controls.s, and so on. In addition, we used a makefile — the programmer created a new .s file and placed it after everything else in the makefile.
The idea was that you enter make on the command line, and the assembler assembles each file into a new .o file, after which the linker joins them all together to build the finished executable file. We had one programmer, notorious for writing code with bugs, that interfered with some random areas of memory. These were usually buffer overflows.
He spent some time finding these bugs, but if he did not succeed, then he ... changed the order of the files in the makefile so that the files were statically linked into memory in a different order! This meant that the accidentally recorded fragment of memory was now in some other place, but due to sheer luck, for some reason the game stopped falling out. He did this until practically any changes in the makefile began to lead to failures.
At the last moment, when the game had to be released, he solved this problem. He simply continued to create new .s files filled with small pieces of data that he inserted into arbitrary places in the makefile until they somehow ceased to crumble, and then released it! At that time there were at least two games (for the Game Boy) released using such a “technique”.
- Shane StevensSubstandard
We sought to release the game
World Series of Poker 2008 , which was our first project on the PlayStation 3. PS3 supported several different screen resolutions and two aspect ratios. We created a 2D shell for a wide screen, but we didn’t have enough time and resources for a 2D shell with standard resolution. I have carefully studied the requirements of the developer and have not found any reasons why letterboxing would be prohibited.
Therefore, our standard ratio mode was just widescreen mode with black bars above and below the picture. The publisher desperately tried to adjust the requirements that would make us fix it, but then gave up and we released the game as it is. In addition, a few hours after buying my own PS3, playing on a TV with a standard aspect ratio, I went and bought a widescreen TV. I doubt that many have connected this miracle of technology (PS3) to the old tube TVs!
- Stephen Boswell IIStriving for constants
For some reason, we have a huge incompatibility between the existing codebase and the new billions of lines of code written to use old code libraries. The first code was written by people who were close to the idea of ​​"safe" programming, as strict and restrictive as possible to avoid errors. Therefore, they used a C / C ++ language feature called CONST.
CONST means "constant"; it ensures that read-only variables cannot be changed inside functions. The code with and without CONST was incompatible with each other, which is why the compiler cursed. The development team decided to insert a hack into the code and performed a cunning little trick: #define const, so that the constant was ... nothing, an empty space. Therefore, the
const int x;
when preprocessing before compilation, became
int x;
. This is similar to the fact that you bought a car, took off two wheels and use it as a motorcycle.
Personally, I really hate CONST, so I liked this trick. But some thought such an approach was analogous to cutting a safety belt with scissors.
- AnonymousReality bites
We had a bug in the game on the Unreal Engine 3 for PlayStation 3 (this was the first project released on UE3 for PS3): in debug mode, the game inexplicably fell out during printf () when connected to a multiplayer game.
The client in debug mode would display all the hashes of each content pack that ordered it to load the server, and obviously, one of the hashes (in this assembly) contained%. We could not come up with a good solution to the problem, but #ifndef PS3 worked quite fine until the next data assembly, in which the bug disappeared.
About a year later, in the next project, I came across the same bug and took advantage of the exact same fix. The disaster occurred after the release of the game, when we were working on the content patch. Creating a DLC / patch was done in such a way that we could not patch the compiled UnrealScript, but we had a bug in which two remote procedure calls were not marked as reliable; this meant that the packets to call them would be re-transmitted until confirmation was received. Therefore, in conditions of poor connection, the functions of enabling readiness and the state of voice transmission in the lobby were sometimes not called. However, only remote UnrealScript can mark remote procedure calls as reliable, and we could not patch UnrealScript.
Therefore, when loading, we loop around all the loaded UFunction objects (which are representations of the script function in C ++), performed a string comparison of names and assigned the two flags to the two calls. Everything worked great.
- AnonymousYour data is ready
The Xbox Live Arcade games on the first Xbox should have been fully packaged in an .xex file. To accomplish this, we stored all the data in a .zip file, embedded as a data section in the executable file. Gradually, the file grew so much that we could no longer load the data section into memory, allocate enough memory to decompress it, and pull out the necessary file.
To fix the problem, I wrote code that, after loading the game, reads the PE header of the executable file and writes offsets to the data sections. Thanks to this, the file stream that read the executable file could simply move to the offsets of different zip files and output them directly from the executable file without loading data partitions into memory.
- Pat WilsonPinhole camera
I will talk about the old case:
Force 21 was one of the first three-dimensional RTS, which used a floating camera to monitor the current squad. By the end of the project, we had a strange bug in which the camera stopped following the squad - it just stopped while the squad continued to move, and nothing could move it. This happened at random times and we could not reproduce the error.
This continued until one of the testers noticed that this happens more often when an airstrike occurs next to the player’s equipment. Thanks to this information I managed to find the source of the error. Since the camera used speed and acceleration, and could also participate in collisions, I made it inheritable from the PhysicalObject class, which possessed such characteristics. But he had one more characteristic: PhysicalObject could take damage. Air strikes inflicted high damage in a fairly large radius, so they literally "killed" the camera.
I corrected this error by making sure that the cameras did not take damage, but to make sure I increased the values ​​of their armor and energy to huge values. I think we can confidently say that our game was the most powerful camera in the world.
- Jim Van WerthHexapility
I was testing
The New Tetris for N64. We had a failure, which I could reproduce at any time: a dump of registers was displayed on the screen, after which the game hung. To get rid of the hangup, you had to turn off and turn on the power of the N64: even the reset key did not respond.
Version by version, the developer said that the bug was fixed, and version by version I reproduced it. The release deadline was approaching, and in order to release the game, the developer needed to eliminate all crashes that lead to crashes. (Nintendo independently tested even the games of other companies, and Nintendo had to approve it for the release of the game.) But they couldn’t get rid of this bug.
Also in the game there were no secret codes related to the bug that could be entered to unlock various features. Once I joked that a developer should replace the hex dump screen with the words “Congratulations! You have discovered the secret code! Turn the console off and on again, and then enter the username HALUCI. ” And he did. It is because of this that the game was released.
- AnonymousShort stack
In 1982–83 I was one of several interns at IMAGIC, and at that time we all made cartridges for Intellivision. One of the programmers had to go back to school, so they chose me to fix a bug with a hang in his game. This turned out to be a stack overflow in the timer interrupt handler.
Since the only task for the handler was to update the display of the on-screen timer, I added code to test the stack depth at the beginning of the interrupt procedure. If there was a danger of stack overflow, the procedure performed a return without doing anything. Since the handler was called many times a second, the player did not notice anything, and the error was corrected.
- AnonymousBack to basics
My colleague Mike Mick and I ported the game about collecting
Klax tiles from arcade machines to Game Boy Color. It was an interesting, stressful six-week project to transfer one of our favorite games to the system.
We had the C source code (actually
Escape from the Planet of the Robot Monsters , only most of the robot monsters were commented out and replaced with the
Klax code), and we often spoke with the original arcade programmer Dave Eckers, who wrote Weekend prototype on Amiga BASIC and ported it to C in about a day.
We coded the game in Z80 assembly language. There were many interesting things, for example, we copied the code onto a whiteboard and mentally traversed line by line, updating the contents of the memory on another whiteboard, because we did not have a real debugger. These were good times.
The deadlines were already running out, but everything worked fine. I played the arcade version, tested the GBC version and found a strange scoring bug. I don’t remember the problem itself, but there was something like a situation where a large cross broke into several diagonals. Be that as it may, points on the GBC compared to the arcade machine were added incorrectly.
Needless to say, I discovered this at about 11:30 pm (right before the end of the term). We ran the code a million times, compared our assembly code with the C code of the arcade machine, and the bug was impossible. We counted the points correctly, and our code performed exactly the same and in the same order as the C program, which was just a line-by-line transfer of what Dave originally did on Amiga BASIC. (I suspect that Dave was a bit like Mike - he was very good at assembly language and BASIC, but he didn’t like C twenty years ago when
Klax was made.)
Finally, at about five in the morning, after spending all night on it, we came to an idea that could not have earned, but it was worth a try. Mike wrote a scoring system on Quick BASIC, and the points began to be counted exactly the same as on the arcade machine. Then we transferred BASIC line by line to the Z80 assembler.
It worked. God knows why, but the program behaved exactly like an arcade machine (perhaps this is somehow related to the fact that the original was written in BASIC). We sent the Atari assembly, printed out both versions of the code, and went to the cafe. At breakfast, we spent an hour looking at the code and still did not understand why it works differently. Even today we can both swear that the code should have given identical results! But sometimes, when it gets too late, it is time to start doing voodoo programming!
- Chris CharlaGames are not the only area in which hacks can save the day. Here are two non-game examples that are too curious to not include as a bonus.Window washers
Five years ago, I worked as a software developer in the field of video surveillance software development. We wrote very sensitive and complex security software. We had a wonderful, well-working product. The most difficult part of the software was the simultaneous display on the screen of 50 video streams. The software required a huge amount of memory, and it had to function 24/7.
A few weeks before the release, we handed over a beta version to customers. A week later, we noticed a huge memory leak - about 4 KB per minute. I spent a couple of days studying the leak, but it did not give any results, and we didn’t have time to fix it before the release. Memory was an essential part of the software, and a leak of this size would completely kill the application. Conducting testing (in Windows), I had to minimize the software window in order to return to the window with the code, and during this I noticed a serious decrease in the occupied memory.
Then I remembered that when I moved a window to the notification area or to the Start menu, Windows instantly recovers unused / freed memory. This was our chance! I added a timer to the application, which every couple of minutes moved the window to the Start menu panel, and then immediately opened it in full screen. On the screen, it looked like a flicker, but it worked! After that, we were able to release the application, which gave us a little more time to fix the bug (which we discovered a few days later - some window handle did not properly clean the window).
- Johan LauniResults may vary.
In the 1970s, I worked with the team on the banking system. We wrote in the long-forgotten programming language MPL2. In this language, there was a limit of 256 global variables, and since they were all used, in order to add a new function to the system, it was often necessary to look for a variable that can be released or used for two different purposes in different parts of the code.
It was a risky and long process. Inside the program, each function could have 256 of its own variables, limited by the function's scope. Once, when I was at home, an insight descended on me. The next morning, I suggested to the boss to wrap all the code in a function. Then we would have 256 global variables for the program, because the 256 used so far will be safely stored in the “internal” function.
The program itself would simply declare a few more variables, and then call a function containing the entire source program. But now she could “see” not only her own 256 variables, but also the new 256 global variables. My boss was skeptical, but gave me a two-hour compile-time window and was stunned that it worked. We were able to circumvent the problem that the team had been facing for a couple of years.