3 Bugs Fixed
in 3 Bytes
Fixing the Blue Maze
Bug, the Marquee Bug,
and
another obscure bug in Ms.
Pac-Man
by Don Hodges
started 11/03/2008
Updated 8/14/2015 Recently I received a request from a visitor
to this web site to look into the so-called "blue maze bug" that affects Ms. Pac-Man.
It is well known that if a credit is inserted at the very beginning of
the attract mode, before the red ghost appears under the marquee, the first maze of the game will
be colored blue instead of the normal maze color.
In order to understand this bug, we need to dig around in the code for this game
and look at some of the underlying issues. It turns out that Pac-Man and
Ms. Pac-Man have two task lists that are used in the game. One of the task
lists is used to insert events that will happen at a future time in the game.
For example, when a fruit is eaten, a timed
task, set to run 2 seconds in the future, is immediately inserted which will erase the score that appeared on the playfield.
The other type of task list is used to set up tasks that need to occur more or
less right away. When the attract mode begins in Ms. Pac Man, a
timed task is inserted which will increase a memory location [#4E02] that is used to
control the flow of the attract mode.
058A F7 RST #30 ; Insert timed task to increase the attract mode counter in #4E02
058B 4A 02 00 ; Timer = #4A, task = 2, parameter = 0
Timed tasks have three parameters. The first byte is a code for the amount of time the game
will wait before running the task. The second byte is the code for the
task, and the third byte is an optional parameter that can be assigned to have the
task do different things. For example, a task might be set to display text
on the screen, and the optional parameter could control which words appear.
Lets look at this task and its three values. First, the timer is set to
#4A. This is a code for the event to occur 1 second after the task has
been inserted. The task code is set to 2, which means after the 1 second
has elapsed, the game will run the subroutine which increases the memory
location [#4E02] that controls the attract mode. The third code is set to zero; in this case the
optional parameter is not used. Under normal circumstances, this when this
task is encountered, the game waits 1 second before the red ghost appears during the
attract mode. Also, under normal circumstances, when a
credit is inserted, the memory location [#4E02] that controls the attract mode
is reset to zero:
; as soon as a credit is detected the following code is run
0407 AF XOR A ; A := #00
...
040B 32024E LD (#4E02),A ; Clear attract mode counter to zero
However, if a credit is inserted during the brief time frame between when the
timed task is inserted and when it is actually run one second later, the memory #4E02 is
immediately cleared to zero, but the timed task eventually catches up and increases
this memory to a value of 1. This causes a chain reaction later in the
code when the subroutine which colors the maze is run:
; The select maze color
9583 3A 02 4E LD A,(#4E02) ; Load A attract mode counter
9586 A7 AND A ; == #00 ?
9587 28 07 JR Z,#9590 ; Yes, select the color to use based on the board number
9589 FE 10 CP #10 ; Else, is this == #10 ? Is the game in the demo maze ?
958b 3E 01 LD A,#01 ; Load A with 1 = blue color
958d C2 E1 24 JP NZ,#24E1 ; If value in #4E02 is not #10, then return to program
9590 ...
When a game begins, this routine which colors the maze is expecting
the value in #4E02 to be 0, not 1. Therefore, when this bug is
encountered, the program ends up setting the color of the maze to be #01, which
is normally used to color the screen during the attract mode. When this is
encountered on game start, it causes the maze to be colored blue, resulting in the blue maze
bug. The fix
This bug can easily be remedied by changing the timer for the
task from 1 second to 1/10 of a second. This can be done by changing one
byte of code: Original code:
058A F7 RST #30 ; Insert timed task to increase the value in #4E02
058B 4A 02 00 ; Timer = #4A (1 second), task = 2, parameter = 0
Fixed code:
058A F7 RST #30 ; insert timed task to increase the value in #4E02
058B 41 02 00 ; Timer = #41 (1/10 second), task = 2, parameter = 0
It should be noted that this fix still leaves the possibility that the bug can
encountered, if the player is fast enough to get a credit inserted in the 1/10
of a second between the appearance of the marquee and the red ghost.
However, during testing, I have been unable to achieve the feat with this fixed
code in place. [I guess my reflexes aren't as fast as they used to be.] Also,
this fix somewhat changes the behavior of the attract screen, causing the red
ghost to appear more quickly than he did before. For this reason, there is
also another fix that I have created which fully fixes the bug, with no chance
of it occurring, and also leaves the attract mode intact. This second fix is
much more complicated and involves creating a 'hook' in the code to a new
subroutine which clears out the proper memory location when a game is started.
Original code:
0677 EF RST #28 ; Insert task to color the maze
0678 01 01
Fixed code:
0677 C3 41 98 JP #9841 ; Jump to hook to clear #4E02
...
9841 AF XOR A ; A := #00
9842 32 02 4E LD (#4E02),A ; Clear #4E02 to fix possible blue maze bug
9845 EF RST #28 ; Insert task to color the maze
9846 01 01
9848 C3 7A 06 JP #067A ; Return to program
Ms. Pac Man's Marquee Bug and Fix
It is also previously known that there is a minor bug in the
game code which causes the marquee to not light up correctly all the way around
the marquee. In particular, the left side of the marquee does not light up
with white dot on every other animation frame.
The cause of this bug is an incorrect character code in the subroutine which
controls the marquee. Original code:
3F7C 36 83 LD (HL),#83 ; Color the spot white (?) [Bug. Spot stays red]
This
is easily fixed by changing the offending byte to #85, which is what is should
have been all along. Fixed code:
3F7C 36 85 LD (HL),#85 ; Color the spot white [fixed]
Another obscure bug
While I was digging through the code, I came across another bug
which I doubt anyone has ever known about before. It is a very minor bug
and does not affect game play and is very difficult to spot in the wild, which helps explain why it has
probably not been discussed
before. The origin of this bug, which affects Pac-Man and Ms.
Pac-Man, is in the original Pac-Man code. There is a subroutine which
controls the flashing energizers in the attract mode of Pac-Man. Normally,
this subroutine is only supposed to run during the introduction screen where the
ghosts are introduced by name.
On some occasions, perhaps a one in twenty chance or less, when the player dies,
this subroutine get called, which flashes the 2 screen location where these
energizers are located. When it is called in Pac-Man, it causes the
disappearance of the dot that is 2 to the left of the starting point of Pac-Man
in the maze. The other screen location that is affected is already blank,
so the changed color has no visible effect there.
In Ms. Pac-Man, it causes 2 screen locations to
change color, which affects the different mazes in slightly different ways.
For the first maze, this same dot to the left of where Ms.
Pac-Man begins changes color to pink. Like in Pac-Man, the other screen location
that is affected is already blank, so the changed color has no visible effect
there.
For the second maze, two locations are affected:
For the third maze, only one location is visibly affected:
For the fourth maze, two locations are affected:
In any case, this bug is very difficult to spot because usually the anomalies
are covered up by a screen refresh almost immediately after they are created.
The exception to this rule is during the demo mode of Ms. Pac-Man. If you
watch the demo long enough, eventually you will notice that the dot in question
is colored pink on rare occasions after Ms. Pac-Man has died during the demo,
and it stays pink on screen long enough to be easily observed.
The Fix
Since the subroutine to flash the power pellets in the attract mode is not used
in Ms. Pac-Man, a bug fix is fairly straightforward, done by changing a single
byte of code:
Original code:
0C17 3A 04 4E LD A,(#4E04) ; Load A with game state indicator
0C1A FE 03 CP #03 ; Is a game being played ?
0C1C 20 15 JR NZ,#0C33 ; No, flash the 2 pellets for attract screen
0C1E ...
Fixed code:
0C17 3A 04 4E LD A,(#4E04) ; Load A with game state indicator
0C1A FE 03 CP #03 ; Is a game being played ?
0C1C 20 00 JR NZ,#0C1E ; No, do nothing
0C1E ...
A fix for Pac-Man would be more complicated and probably require
creating a hook for a new subroutine. This is left as an exercise for the
reader. I look forward to your submissions for this. |