Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
1 contributor

Users who have contributed to this file

13660 lines (11181 sloc) 551 KB
;; Ms. Pac-Man documented disassembly
;;
;; The copyright holders for the core program
;; included within this file are:
;; (c) 1980 NAMCO
;; (c) 1980 Bally/Midway
;; (c) 1981 General Computer Corporation (GCC)
;;
;; Research and compilation of the documentation by
;; Scott Lawrence
;; pacman@umlautllama.com @yorgle
;;
;; Documentation and Hack Contributors:
;; Don Hodges http://www.donhodges.com
;; David Caldwell http://www.porkrind.org
;; Frederic Vecoven http://www.vecoven.com (Music, Sound)
;; Fred K "Juice"
;; Marcel "The Sil" Silvius http://home.kabelfoon.nl/~msilvius/
;; Mark Spaeth http://rgvac.978.org/asm
;; Dave Widel http://www.widel.com/
;; M.A.B. from Vigasoco
;;
;; DISCLAIMER:
;; This project is a learning experience. The goal is to try
;; to figure out how the original programmers and subsequent
;; GCC programmers wrote Pac-Man, Crazy Otto, and Ms. Pac-Man.
;; This disassembly and comments are not sanctioned in any
;; way by any of the copyright holders of these programs.
;;
;; Over time, this document may transform from a documented disassembly
;; of the bootleg ms-pacman roms into a re-assemblable source file.
;;
;; This is also made to determine which spaces in the roms are available
;; for patches and extra functionality for your own hacks.
;;
;; NOTE: This disassembly is based on the base "bootleg"
;; version of Ms. Pac-Man. ("boot1" through "boot6")
;; rom images used:
;; 0x0000 - 0x0fff boot1
;; 0x1000 - 0x1fff boot2
;; 0x2000 - 0x2fff boot3
;; 0x3000 - 0x3fff boot4
;; 0x8000 - 0x8fff boot5
;; 0x9000 - 0x9fff boot6
;;
;; More information about the actual Ms. Pac-Man aux board is below.
;;
;;
;; IF YOU ARE AWARE OF ANY BITS OF CODE THAT ARE NOT DOCUMENTED
;; HERE, OR KNOW OF MORE RAM ADDRESSES OR SUCH, PLEASE EMAIL
;; ME SO THAT I MAY INTEGRATE YOUR INFORMATION INTO HERE.
;;
;; THANKS!
;; 2014-01-18
;; tried to document HACK2 (standard speedup hack) but it makes no sense
;; added more info about #f2 LOOP and ANIMATIONS in general
;;
;; 2014-01-16
;; Completely documented DrawText (2c5e)
;;
;; 2014-01-12
;; Text string decodings (0x3713, 0x3d00) for readibility
;; Animation code engine at 0x34a9
;; Animation code lists at 0x8251, Rosetta stone at 0x8395
;;
;; 2014-01-06
;; Don Hodges' documentation work added
;; bugfix section added.
;; HACK8 -> BUGFIX01
;; HACK9 -> BUGFIX02
;; HACK10 -> HACK8
;; HACK11 -> HACK9
;;
;; 2014-01-02
;; Added "OTTOPATCH" information from Crazy Otto source
;;
;; 2009-12-16
;; Added some Crazy Otto notes
;;
;; 2009-01-18
;; Added content from Don Hodges for much of the undocumented code
;;
;; 2008-06-20
;; Added content from Frederic Vecoven for all of the sound code
;;
;; 2007-09-03
;; added more notes about mspac blocks in 8000/9000
;; RAM layout, data tables from M.A.B. in the VIGASOCO project (pac)
;;
;; 2004-12-28
;; added Interrupt Mode 1/2 documentation
;;
;; 2004-12-22
;; added HACK12 - the C000 text mirror bug fix
;;
;; 2004-03-21
;; added information for most of the reference tables for map-related-data
;;
;; 2004-03-15
;; working on figuring out RST 28
;;
;; 2004-03-09
;; added comments about how the text rendering works (at 0x2c5e)
;; added more details about the text string look up table
;; added information about midway logo rendering at 0x964a
;; changed all of the RST 28 calls to have data after them
;;
;; 2004-03-03
;; mapped out most of the patches in 8000-81ef range
;; (some are unused ff's, some I couldn't find...)
;;
;; 2004-03-02
;; HACK10: Dave Widel's fast intermission fix (based on Dock Cutlip's code)
;; (now HACK8)
;; HACK11: Dave Widel's coin light blink with power pellets
;; (now HACK9)
;;
;; 2004-02-18
;; HACK8: Mark Spaeth's "20 byte" level 255 Pac-Man rom fix (BUGFIX01)
;; HACK9: Mark Spaeth's Ms. Pac-Man level fix (BUGFIX02)
;;
;; 2004-01-10
;; figured out some of the sound generation triggering
;;
;; 2004-01-09
;; added notes about HACK7 : eliminating all of the startup tests
;; figured out the easter egg routine as well as storage method for data
;;
;; 2004-01-05
;; added notes about HACK6 : the standard "HARD" romset
;; changed all of the HACK numbers
;;
;; 2004-01-04
;; added notes from Fred K's roms about skipping the self test HACK4
;; added notes about the pause routine HACK5
;; added notes from Fred K about 018c game loop
;;
;; 2004-01-03
;; added note about 0068-008c being junk - INCORRECT! (ed.)
;;
;; 2004-01-02
;; added in more information about controllers
;; added info about the always-on fast upgrade HACK2
;; added info about the P1P2 cheat HACK3
;;
;; 2004-01-01
;; integrated in Mark Spaeth's random fruit doc.
;;
;; 2003-07-16
;; added in red ghost AI code documentation (2730, 9561)
;;
;; 2003-03-26
;; changed some 'kick the dog' text
;; added a note about the checksum hack ; HACK1
;;
;; 2003-03
;; cleaned up some notes, added the "Made By Namco" egg notes
;;
;; + 2001-07-13
;; more notes from David Widel. Ram variables, $2a23m $8768
;;
;; + 2001-06-25,26
;; integrated in some notes from David Widel (THANKS!)
;;
;; 2001-03-06
;; integrated in Fred K's pacman notes.
;;
;; 2001-03-04
;; corrected text strings in the lookup table at 36a5
;; commented some of the text string routines
;;
;; 2001-02-28
;; added text string lookup tables
;; added indirect lookup at 36a5
;; added more commenting over from the pacman.asm file
;;
;; 2001-02-27
;; table data pulled out, and bogus opcodes removed.
;; more score information found as well
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Documented Hacks
;;
;; these are common hacks done to this codebase
HACK1
Skips the traditional bad-rom checksum routine.
HACK2
Traditional "Fast Chip" hack
HACK3
Dock Cutlip's Fast/Invincibility hack.
Press P1 start for super speed
Press P2 start for invincibility
HACK4
Self-Test skip
Reclaims rom space 3006 - 30c0 for custom code use
HACK5
Game pause routine
Press P1 start to pause
Press P2 start to unpause
HACK6
The standard "HARD" romset.
Unknown exactly what the changes are. (data table)
HACK7
Skips the Test startup display
(Alternate) just skips the grid.
HACK8 (formerly HACK10)
Dave Widel's faster intermission fix
Based on Dock Cutlip's code
Pac moves at normal speeds in intermissions
(this is a hack, not a fix, since it's based on a hack/mod
HACK9 (formerly HACK11)
Dave Widel's coin light blink with power pellets
Coin lights blink when power pellets blink now
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Documented bugfixes
;;
;; these are bugfixes to the code base
BUGFIX01 - Level 255 Pac-Man kill screen killer
from: Mark Spaeth
notes: Mark Spaeth's level 255 Pac-Man fix
Mspac never gets to 255, so this fix is pac-only
BUGFIX02 - Level 141 Ms. Pac-Man kill screen killer
ref: http://www.funspotnh.com/discus/messages/10/508.html?1077146991
from: Mark Spaeth
notes: This fix is Ms. Pac only, but will work for pac as well.
BUGFIX03 - Blue Maze
from: Don Hodges
ref: http://donhodges.com/ms_pacman_bugs.htm
symptoms: Sometimes when starting Ms Pac, the first
board is blue.
BUGFIX04 - Marquee left side animation fix
from: Don Hodges
ref: http://donhodges.com/ms_pacman_bugs.htm
symptoms: incorrect character in the intro screen
causes the intro marquee to not work on the left side
BUGFIX05 - Map discoloration fix
from: Don Hodges
ref: http://donhodges.com/ms_pacman_bugs.htm
symptoms: The marquee doesn't light correctly,
Other characters glitch on gameplay maps
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Known Ms. Pac variants:
;
; Pac variants:
; Puckman Namco "original"
; Hanglyman Maze disappears sometimes, vertical tunnel?
; Pac-Man Namco/Midway
; Pac-Man Hard (table changes)
; Pac-Man Plus Midway upgrade - New ghosts,
; harder gameplay, disappearing map
;
; (pre-release GCC versions:)
; Crazy Otto 10/12/1981 (P1) Pac-man intro, legs, monsters,
; GENCOMP logo,
; no eyes when ghosts return to jail
; Crazy Otto 10/20/1981 (P2) Marquee (Mspac) intro, legs,
; ghosts, Midway logo
; Super Pac-Man 10/29/1981 (P3) Same as P2, with no legs, monsters
; Super Pac-Man 10/29/1981 (P4) Same as P3, ghosts
; Miss Pac-Man 11/12/1981 (P5) Marquee, "Pac-Woman" graphics, monsters
; Ms. Pac-Man 11/25/1981 (P6) Same as P5, MsPac graphics, Bonnie
;
' (Released versions)
; Ms. Pac-Man 12/18/1981 Original GCC/Midway w/ aux board
; (hardware protected)
; Ms. Pac-Man Bootleg (various) decoded aux board
; (no hardware protection)
; Ms. Pac-Man Attack four new maps, broken fruit movement
; Miss Pac Plus four new maps (same as Attack, reversed)
; and of course, the "fast" and "cheat" versions of those above.
;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; JUNK REGIONS OF ROMSPACE
;;
There are a few regions of rom space that are unused by
the ms-pac program. These can be used for your own patches,
or for data, or whatever.
This list is most definitely incomplete.
Not all of these regions have been tested.
The list is inclusive of the start and end byte listed below.
Some routines (like the self-test) can be dropped to give
you more romspace to work with. You should be careful
however in that some chunks of romspace might not be free
with some rom hacks.
(0f3c - 0f4b for example)
003b - 0041 7 bytes Tested
0f3c - 0fff 195 bytes Untested, nops
1fa9 - 1fff 87 bytes Untested, nops, 48 used for HACK3 cheat
2fba - 2fff 70 bytes Untested, nops
3ce0 - 3cff 32 bytes Untested, nops
8000 - 81ef 1f0 bytes Untested, bootleg hardware ONLY!
97c4 - 97cf c bytes Untested, FF's
97d0 - 97f0 30 bytes Untested, message
9800 - 9fff 400 bytes not available on "pure" mspac.
Similarly, there are chunks of code in the 0x0000-0x3fff area that are previously
used for Pac functionality that has been replaced by the aux roms, which can be
re-purposed.
If you're working with a bootleg romset, then the roms specific
to the Aux Board, namely "BOOT5" 0x8000-0x8fff, has a lot of space
previously used by the patching mechanism, in 0x8000-0x87ff, which
can be re-used for other code/tables.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Ms Pacman Aux board information (GCC/Midway Pac-Man "Upgrade")
ED note: The U5, U6 and U7 notes below have yet to be confirmed.
It turns out the bootleg is the decrypted version with the
checksum check removed and interrupt mode changed to 1.
u7= boot 4($3000-$3fff) other than 4 bytes(checksum check
and interupt mode)
u6= boot 6($9000-$9fff). The second half of u6 gets mirrored
Renders to the second half of boot5($8800-$8fff) where it
is used.
u5= first half of boot5($8000-$87ff)
$8000-$81ef contain 8 byte patches that are overlayed on
locations in $0000-$2fff
The Ms Pacman aux board is not activated with the
mainboard. As near as I can tell it requires a sequence
of bytes starting at around 3176 and ending with 3196. The
location of the bytes doesn't seem to matter, just that
those bytes are executed. That sequence of bytes includes
a write to 5006 so I'm using that to bankswitch, but that
is not accurate. The actual change is I believe at $317D.
The aux board can also be deactivated. A read to any
of the several 8 byte chunks listed will cause the Ms Pac
roms to disappear and Pacman to show up. As a result I
couldn't verify what they contained. They should be the
same as the pacman roms, but I don't see how it could
matter. These areas can be accessed by the random number
generator at $2a23 and the board is deactivated but is
immediately reactivated. So the net result is no change.
The exact trigger for this is not yet known.
deactivation, 8 bytes starting at:
$38,$3b0,$1600,$2120,$3ff0,$8000
David Widel
d_widel@hotmail.com
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Ghost names:
Pac-Man Otto Ms pre Ms Release
Red Shadow/Blinky Mad Dog/Plato Blinky Blinky
Pink Speedy/Pinky Killer/Darwin Pinky Pinky
Cyan Bashful/Inky Brute/Freud Inky Inky
Orange Pokey/Clyde Sam/Newton Bonnie Sue
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; ram:
; 4c00 unknown
; 4c01 unknown
;
; Sprite variables
;
; 4c02 red ghost sprite number
; 4c03 red ghost color entry
; 4c04 pink ghost sprite number
; 4c05 pink ghost color entry
; 4c06 blue ghost sprite number
; 4c07 blue ghost color entry
; 4c08 orange ghost sprite number
; 4c09 orange ghost color entry
; 4c0a pacman sprite number
; 4c0b pacman color entry
; 4c0c fruit sprite number
; 4c0d fruit sprite entry
;
; 4c20 sprite data that goes to the hardware sprite system
;
; 4c22-4c2f sprite positions for spriteram2
; 4c32-4c3f sprite number and color for spriteram
;
; 4C40-4C41 used for moving fruit positions
; 4C42-4C43 used to hold address of the fruit path
; 4c44-4c7f unused/unknown
;
; Tasks and Timers
;
; 4c80 \ pointer to the end of the tasks list
; 4c81 /
; 4c82 \ pointer to the beginning of the tasks list
; 4c83 /
; 4c84 8 bit counter (0x00 to 0xff) used by sound routines
; 4c85 8 bit counter (0xff to 0x00) (unused)
; 4c86 counter 0: 0..5 10..15 20..25 .. 90..95 - hundreths
; 4c87 counter 1: 0..9 10..19 20..29 .. 50..59 - seconds
; 4c88 counter 2: 0..9 10..19 20..29 .. 50..59 - minutes
; 4c89 counter 3: 0..9 10..19 20..29 .. 90..99 - hours
;
; 4c8a number of counter limits changes in this frame (to init time)
; 0x01 1 hundredth
; 0x02 10 hundredths
; 0x03 1 second
; 0x04 10 seconds
; 0x05 1 minute
; 0x06 10 minutes
; 0x07 1 hour
; 0x08 10 hours
; 0x09 100 hours
; 4c8b random number generation (unused)
; 4c8c random number generation (unused)
;
; 4c90-4cbf scheduled tasks list (run inside IRQ)
; 16 entries, 3 bytes per entry
; Format:
; byte 0: scheduled time
; 7 6 5 4 3 2 1 0
; | | | | | | | |
; | | ------------ number of time units to wait
; | |
; ---------------- time units
; 0x40 -> 10 hundredths
; 0x80 -> 1 second
; 0xc0 -> 10 seconds
; byte 1: index for the jump table
; byte 2: parameter for b
; these tasks are assigned using RST #30, with the three data bytes immediatly after the call used for the timer, index and parameter
; these tasks are decoded at routine starting at #0221
;
; 4cc0-4ccf tasks to execute outside of IRQ
; 0xFF fill for empty task
; 16 entries, 2 bytes per entry
; Format:
; byte 0: routine number
; byte 1: parameter
; these tasks are assigned using RST #28, with the two data bytes immedately after the call used for the routine number and parameter
alternately, tasks can be assigned by manually loading B and C with routine and parameter, and then executing call #0042
; tasks are decoded at routine starting at #238D
;
; Game variables
; ** note - need to be sorted
;
; 4DD2 FRUITP fruit position
; 4DD4 FVALUE value of the current fruit (0=no fruit)
; 4C40 COUNT current place in fruit path
; 4E0C FIRSTF flag to indicate that first fruit has been released
; 4E0D SECONDF flag to indicate that second fruit has been eaten
; 4C41 BCNT current place within bounce
; 4C42 PATH pointer to the path the fruit is currently following
; 4E0E DOTSEAT how many dots the current player has eaten
; 4EBC BNOISE set bit 5 of BNOISE to make the bounce sound
; 4d00 red ghost Y position (bottom to top = decreases)
; 4d01 red ghost X position (left to right = decreases)
; 4d02 pink ghost Y position (bottom to top = decreases)
; 4d03 pink ghost X position (left to right = decreases)
; 4d04 blue ghost Y position (bottom to top = decreases)
; 4d05 blue ghost X position (left to right = decreases)
; 4d06 orange ghost Y position (bottom to top = decreases)
; 4d07 orange ghost X position (left to right = decreases)
;
; 4d08 pacman Y position
; 4d09 pacman X position
;
; 4d0a red ghost Y tile pos (mid of tile) (bottom to top = decrease)
; 4d0b red ghost X tile pos (mid of tile) (left to right = decrease)
; 4d0c pink ghost Y tile pos (mid of tile) (bottom to top = decrease)
; 4d0d pink ghost X tile pos (mid of tile) (left to right = decrease)
; 4d0e blue ghost Y tile pos (mid of tile) (bottom to top = decrease)
; 4d0f blue ghost X tile pos (mid of tile) (left to right = decrease)
; 4d10 orange ghost Y tile pos (mid of tile) (bottom to top = decrease)
; 4d11 orange ghost X tile pos (mid of tile) (left to right = decrease)
; 4d12 pacman tile pos in demo and cut scenes
; 4d13 pacman tile pos in demo and cut scenes
;
; for the following, last move was
; (A) 0x00 = left/right, 0x01 = down, 0xff = up
; (B) 0x00 = up/down, 0x01 = left, 0xff = right
; 4d14 red ghost Y tile changes (A)
; 4d15 red ghost X tile changes (B)
; 4d16 pink ghost Y tile changes (A)
; 4d17 pink ghost X tile changes (B)
; 4d18 blue ghost Y tile changes (A)
; 4d19 blue ghost X tile changes (B)
; 4d1a orange ghost Y tile changes (A)
; 4d1b orange ghost X tile changes (B)
; 4d1c pacman Y tile changes (A)
; 4d1d pacman X tile changes (B)
;
; 4d1e red ghost y tile changes
; 4d1f red ghost x tile changes
; 4d20 pink ghost y tile changes
; 4d21 pink ghost x tile changes
; 4d22 blue ghost y tile changes
; 4d23 blue ghost x tile changes
; 4d24 orange ghost y tile changes
; 4d25 orange ghost x tile changes
; 4d26 wanted pacman tile changes
; 4d27 wanted pacman tile changes
;
; character orientations:
; 0 = right, 1 = down, 2 = left, 3 = up
; 4d28 previous red ghost orientation (stored middle of movement)
; 4d29 previous pink ghost orientation (stored middle of movement)
; 4d2a previous blue ghost orientation (stored middle of movement)
; 4d2b previous orange ghost orientation (stored middle of movement)
; 4d2c red ghost orientation (stored middle of movement)
; 4d2d pink ghost orientation (stored middle of movement)
; 4d2e blue ghost orientation (stored middle of movement)
; 4d2f orange ghost orientation (stored middle of movement)
;
; 4d30 pacman orientation
;
; these are updated after a move
; 4d31 red ghost Y tile position 2 (See 4d0a)
; 4d32 red ghost X tile position 2 (See 4d0b)
; 4d33 pink ghost Y tile position 2
; 4d34 pink ghost X tile position 2
; 4d35 blue ghost Y tile position 2
; 4d36 blue ghost X tile position 2
; 4d37 orange ghost Y tile position 2
; 4d38 orange ghost X tile position 2
;
; 4d39 pacman Y tile position (0x22..0x3e) (bottom-top = decrease)
; 4d3a pacman X tile position (0x1e..0x3d) (left-right = decrease)
;
; 4d3c wanted pacman orientation
;
; path finding algorithm:
; 4d3b best orientation found
; 4d3d saves the opposite orientation
; 4d3e-4d3f saves the current tile position
; 4d40-4d41 saves the destination tile position
; 4d42-4d43 temp resulting position
; 4d44-4d45 minimum distance^2 found
;
; 4dc7 current orientation we're trying
; 4d46-4d85 speed bit patterns (difficulty dependant)
; 4D46-4D49 speed bit patterns for pacman in normal state
; 4D4A-4D4D speed bit patterns for pacman in big pill state
; 4D4E-4D51 speed bit patterns for second difficulty flag
; 4D52-4D55 speed bit patterns for first difficulty flag
; 4D56-4D59 speed bit patterns for red ghost normal state
; 4D5A-4D5D speed bit patterns for red ghost blue state
; 4D5E-4D61 speed bit patterns for red ghost tunnel areas
; 4D62-4D65 speed bit patterns for pink ghost normal state
; 4D66-4D69 speed bit patterns for pink ghost blue state
; 4D6A-4D6D speed bit patterns for pink ghost tunnel areas
; 4D6E-4D71 speed bit patterns for blue ghost normal state
; 4D72-4D75 speed bit patterns for blue ghost blue state
; 4D76-4D79 speed bit patterns for blue ghost tunnel areas
; 4D7A-4D7D speed bit patterns for orange ghost normal state
; 4D7E-4D81 speed bit patterns for orange ghost blue state
; 4D82-4D83 speed bit patterns for orange ghost tunnel areas
;
; 4d86-4d93
; Difficulty related table. Each entry is 2 bytes, and
; contains a counter value. when the counter at 4DC2
; reaches each entry value, the ghosts changes their
; orientation and 4DC1 increments it's value to point to
; the next entry
;
; 4d94 counter related to ghost movement inside home
; 4d95-4d96 number of units before ghost leaves home (no change w/ pills)
; 4d97-4d98 inactivity counter for units of the above
;
; 4d99 - 4d9c
; These values are normally 0, but are changed to 1 when a ghost has
; entered a tunnel slowdown area
; 4d99 aux var used by red ghost to check positions
; 4d9a aux var used by pink ghost to check positions
; 4d9b aux var used by blue ghost to check positions
; 4d9c aux var used by orange ghost to check positions
;
; 4d9d delay to update pacman movement
; not 0xff - the game doesn't move pacman, but decrements instead
; 0x01 when eating pill
; 0x06 when eating big pill
; 0xff when not eating a pill
; 4d9e related to number of pills eaten before last pacman move
; 4d9f eaten pills counter after pacman has died in a level
; used to make ghosts go out of home after # pills eaten
;
; ghost substates:
; 0 = at home
; 1 = going for pac-man
; 2 = crossing the door
; 3 = going to the door
;
; 4da0 red ghost substate (if alive)
; 4da1 pink ghost substate (if alive)
; 4da2 blue ghost substate (if alive)
; 4da3 orange ghost substate (if alive)
; 4da4 # of ghost killed but no collision for yet [0..4]
; 4da5 pacman dead animation state (0 if not dead)
; 4da6 power pill effect (1=active, 0=no effect)
;
; 4da7 red ghost blue flag (0=not blue)
; 4da8 pink ghost blue flag (0=not blue)
; 4da9 blue ghost blue flag (0=not blue)
; 4daa orange ghost blue flag (0=not blue)
;
; 4dab killing ghost state
; 0 = nothing
; 1 = kill red ghost
; 2 = kill pink ghost
; 3 = kill blue ghost
; 4 = kill orange ghost
;
; ghost states:
; 0 = alive
; 1 = dead
; 2 = entering home after being killed
; 3 = go left after entering home after dead (blue)
; 3 = go right after entering home after dead (orange)
; 4dac red ghost state
; 4dad pink ghost state
; 4dae blue ghost state
; 4daf orange ghost state
;
; 4db0 related to difficulty, appears to be unused
;
; with these, if they're set, ghosts change orientation
; 4db1 red ghost change orientation flag
; 4db2 pink ghost change orientation flag
; 4db3 blue ghost change orientation flag
; 4db4 orange ghost change orientation flag
; 4bd5 pacman change orientation flag
;
; Difficulty settings
;
; 4db6 1st difficulty flag (rel 4dbb) (cruise elroy 1)
; 0: red ghost goes to upper right corner on scatter
; 1: red ghost goes for pacman on scatter
; 1: red ghost goes faster
; 4db7 2nd difficulty flag (rel 4dbc) (cruise elroy 2)
; when set, red uses a faster bit speed pattern
; 0: not set
1: faster movement
; 4db8 pink ghost counter to go out of home limit (rel 4e0f)
; 4db9 blue ghost counter to go out of home limit (rel 4e10)
; 4dba orange ghost counter to go out of home limit (rel 4e11)
; 4dbb remainder of pills when first diff. flag is set (cruise elroy 1)
; 4dbc remainder of pills when second diff. flag is set (cruise elroy 2)
; 4dbd-4dbe Time the ghosts stay blue when pacman eats a big pill
;
; 4dbf 1=pacman about to enter a tunnel, otherwise 0
;
; Counters
;
; 4dc0 changes every 8 frames; used for ghost animations
; 4dc1 orientation changes index [0..7]. used to get value 4d86-4d93
; 0: random ghost movement, 1: normal movement (?)
; 4dc2-4dc3 counter related to ghost orientation changes
; 4dc4 counter 0..8 to handle things once every 8 times
; 4dc5-4dc6 counter started after pacman killed
; 4dc7 counter for current orientation we're trying
; 4dc8 counter used to change ghost colors under big pill effects
;
; 4dc9-4dca pointer to pick a random value from the ROM (routine 2a23)
;
; 4dcb-4dcc counter while ghosts are blue. effect ceases at 0
; 4dce counter started after insert coin (LED and 1UP/2UP blink)
; 4dcf counter to handle power pill flashes
; 4dd0 current number of killed ghosts (0..4) (rel 4da5)
;
; 4dd1 killed ghost animation state
; if 4da4 != 0:
; 4dd1 = 0: killed, showing points per kill
; 4dd1 = 1: wating
; 4dd1 = 2: clearing killed ghost, changing state to 0
; 4dd2-4dd3 fruit position (sometimes for other sprite)
;
; 4dd4 entry to fruit points or 0 if no fruit
; 4dd6 used for LED state( 1: game waits for 1P/2P start button press)
;
; Main States
;
; 4e00 main routine number
; 0: init
; 1: demo
; 2: coin inserted
; 3: playing
; 4e01 main routine 0, subroutine #
; 4e02 main routine 1, subroutine # (related to blue maze bug)
; 4e03 main routine 2, subroutine #
; 4e04 level state subroutine #
; 3=ghost move, 2=ghost wait for start
; (set to 2 to pause game)
;
; 4e06 state in first cutscene (pac-man only)
; 4e07 state in second cutscene (pac-man only)
; 4e08 state in third cutscene (pac-man only)
;
; 4e09 current player number: 0=P1, 1=P2
;
; 4e0a-4e0b pointer to current difficulty settings
;
; 4C40 COUNT current place in fruit path
; 4E0C FIRSTF flag to indicate that first fruit has been released
; 4E0D SECONDF flag to indicate that second fruit has been eaten
; 4C41 BCNT current place within bounce
; 4C42 PATH pointer to the path the fruit is currently following
; 4E0E DOTSEAT how many dots the current player has eaten
; 4EBC BNOISE set bit 5 of BNOISE to make the bounce sound
;
; 4e0c first fruit flag (1 if fruit has appeared)
; 4e0d second fruit flag (1 if fruit has appeared)
; 4e0e number of pills eaten in this level
; 4e0f counter incremented if orange, blue and pink ghosts are home
; and pacman is eating pills.
; used to make pink ghost leave home (rel 4db8)
; 4e10 counter incremented if orange, blue and pink ghosts are home
; and pacman is eating pills.
; used to make blue ghost leave home (rel 4db9)
; 4e11 counter incremented if orange, blue and pink ghosts are home
; and pacman is eating pills.
; used to make orange ghost leave home (rel 4db9)
; 4e12 1 after dying in a level, reset to 0 if ghosts have left home
; because of 4d9f
;
; 4e13 current level
; 4e14 real number of lives
; 4e15 number of lives displayed
;
; 4e16-4e33 0x13 pill data entries. each bit means if a pill is there
; or not (1=yes 0=no)
; the pills start at upper right corner, go down, then left.
; first pill is bit 7 of 4e16
; 4e34-4e37 power pills data entries
; 4e38-4e65 copy of level data (430a-4e37)
;
; coins, credits
;
; 4e66 last 4 SERVICE1 to detect transitions
; 4e67 last 4 COIN2 to detect transitions
; 4e68 last 4 COIN1 to detect transitions
;
; 4e69 coin counter (coin->credts, this gets decremented)
; 4e6a coin counter timeout, used to write coin counters
;
; these are copied from the dipswitches
; 4e6b number of coins per credit
; 4e6c number of coins inserted
; 4e6d number of credits per coin
; 4e6e number of credits, 0xff for free play
; 4e6f number of lives
; 4e70 number of players (0=1 player, 1=2 players)
; 4e71 bonus/life
; 0x10 = 10000 0x15 = 15000
; 0x20 = 20000 0xff = none
; 4e72 cocktail mode (0=no, 1=yes)
; 4e73-4e74 pointer to difficulty settings
; 4e73: 68=normal 7d=hard checked at start of game
; 4e75 ghost names mode (0 or 1)
;
; SCORE AABBCC
; 4e80-4e82 score P1 80=CC 81=BB 82=CC
; 4e83 P1 got bonus life? 1=yes
; 4e84-4e86 score P2 84=CC 85=BB 86=CC
; 4e87 P2 got bonus life? 1=yes
; 4e88-4e8a high score 88=CC 89=BB 8A=CC
;
; Sound Registers
;; these 16 values are copied to the hardware every vblank interrupt.
CH1_FREQ0 EQU 4e8c ; 20 bits
CH1_FREQ1 EQU 4e8d
CH1_FREQ2 EQU 4e8e
CH1_FREQ3 EQU 4e8f
CH1_FREQ4 EQU 4e90
CH1_VOL EQU 4e91
CH2_FREQ1 EQU 4e92 ; 16 bits
CH2_FREQ2 EQU 4e93
CH2_FREQ3 EQU 4e94
CH2_FREQ4 EQU 4e95
CH2_VOL EQU 4e96
CH3_FREQ1 EQU 4e97 ; 16 bits
CH3_FREQ2 EQU 4e98
CH3_FREQ3 EQU 4e99
CH3_FREQ4 EQU 4e9a
CH3_VOL EQU 4e9b
SOUND_COUNTER EQU 4c84 ; counter, incremented each VBLANK
; (used to adjust sound volume)
EFFECT_TABLE_1 EQU 3b30 ; channel 1 effects. 8 bytes per effect
EFFECT_TABLE_2 EQU 3b40 ; channel 2 effects. 8 bytes per effect
EFFECT_TABLE_3 EQU 3b80 ; channel 3 effects. 8 bytes per effect
#if MSPACMAN
SONG_TABLE_1 EQU 9685 ; channel 1 song table
SONG_TABLE_2 EQU 967d ; channel 2 song table
SONG_TABLE_3 EQU 968d ; channel 3 song table
#else
SONG_TABLE_1 EQU 3bc8
SONG_TABLE_2 EQU 3bcc
SONG_TABLE_3 EQU 3bd0
#endif
CH1_E_NUM EQU 4e9c ; effects to play sequentially (bitmask)
CH1_E_1 EQU 4e9d ; unused
CH1_E_CUR_BIT EQU 4e9e ; current effect
CH1_E_TABLE0 EQU 4e9f ; table of parameters, initially copied from ROM
CH1_E_TABLE1 EQU 4ea0
CH1_E_TABLE2 EQU 4ea1
CH1_E_TABLE3 EQU 4ea2
CH1_E_TABLE4 EQU 4ea3
CH1_E_TABLE5 EQU 4ea4
CH1_E_TABLE6 EQU 4ea5
CH1_E_TABLE7 EQU 4ea6
CH1_E_TYPE EQU 4ea7
CH1_E_DURATION EQU 4ea8
CH1_E_DIR EQU 4ea9
CH1_E_BASE_FREQ EQU 4eaa
CH1_E_VOL EQU 4eab
; 4EAC repeats the above for channel 2
; 4EBC repeats the above for channel 3
CH1_W_NUM EQU 4ecc ; wave to play (bitmask)
CH1_W_1 EQU 4ecd ; unused
CH1_W_CUR_BIT EQU 4ece ; current wave
CH1_W_SEL EQU 4ecf
CH1_W_4 EQU 4ed0
CH1_W_5 EQU 4ed1
CH1_W_OFFSET1 EQU 4ed2 ; address in ROM to find the next byte
CH1_W_OFFSET2 EQU 4ed3 ; (16 bits)
CH1_W_8 EQU 4ed4
CH1_W_9 EQU 4ed5
CH1_W_A EQU 4ed6
CH1_W_TYPE EQU 4ed7
CH1_W_DURATION EQU 4ed8
CH1_W_DIR EQU 4ed9
CH1_W_BASE_FREQ EQU 4eda
CH1_W_VOL EQU 4edb
;
; 4EDC repeats the above for channel 2
; 4EEC repeats the above for channel 3
;
;
; Runtime
;
; 4F00 Is set to 1 during intermissions and parts of the attract mode, otherwise 0
; 4F01-4FBF Stack
; 4FC0-4FEF Unused
; 4FF0-4FFF Sprite RAM
;
;
;
;
; Memory mapped ports:
; Read ports:
; port# Name ; condition & change Example value
; ----------------------------------------------------------------------
; 5000 IN0 ; When Nothing pressed #FF
; ; Joystick 1 UP clears bit 0 #FE
; ; Joystick 1 LEFT clears bit 1 #FD
; ; Joystick 1 RIGHT clears bit 2 #FB
; ; Joystick 1 DOWN clears bit 3 #F7
; ; Rack test clears bit 4 #EF
; ; Coin 1 inserted clears bit 5 #DF
; ; Coin 2 inserted clears bit 6 #BF
; ; Service 1 pressed clears bit 7 #7F
;
; 5040 IN1 ; When Nothing pressed #FF
; ; Joystick 2 UP clears bit 0 #FE
; ; Joystick 2 LEFT clears bit 1 #FD
; ; Joystick 2 RIGHT clears bit 2 #FB
; ; Joystick 2 DOWN clears bit 3 #F7
; ; service mode switch clears bit 4 #EF
; ; Player 1 start button clears bit 5 #DF
; ; Player 2 start button clears bit 6 #BF
; ; Cocktail cabinet DIP clears bit 7 #7F
;
; 5080 DSW 1 ; controls free play/coins per credit, # of lives per game,
; ; points needed for bonus, rack test, game freeze
;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; PAC-MAN SPRITE CODES
;
; 00-07 fruits
; 08-0D naked ghosts for cutscenes
; 0E-0F empty
; 10-1B big pacman
; 1C-1D ghost in panic mode
; 1E-1F empty
; 20-27 ghosts
; 28-2B points
; 2C-2F pacmans
; 30 big pacman
; 31 explosion
; 32-33 broken ghost
; 34-3F pacman dead
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; MS. PAC-MAN SPRITE CODES
;
; 00 cherry
; 01 strawberry
; 02 peach
; 03 pretzel
; 04 apple
; 05 pear
; 06 banana
; 07 sack that is dropped from stork in act 3
; 08 100
; 09 200
; 0A 500
; 0B 700
; 0C 1000
; 0D 2000
; 0E 5000
; 0F junior pac-man seen in act 3
; 10-17 parts of ACT director's sign
; 18 stork
; 19-1B pac-man
; 1C-1D ghost in panic mode
; 1E heart
; 1F empty
; 20-27 ghosts
; 28 200
; 29 400
; 2A 800
; 2B 1600
; 2C stork
; 2D ms pacman
; 2E pac-man
; 2F ms pacman
; 30 stork head + beak
; 31 ms pacman
; 32 pac-man
; 33-3F ms pacman (used during dying animation)
; 40-7F same as 00-3F, but upside down
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; PACMAN TILE CODES
;
; 00-0F hex digits
; 10-15 pills
; 16-1F empty
; ...
; 40-5B space + ASCII chars
; 5C copyright
; 5D-5F PTS
; ...
; C0-FF map obstacles
;
; SPECIAL COLOR ENTRIES
;
; 18 for ghost's door
; 1A for pacman's and ghost's initial map positions
; 1B for tunnel area
;
; PACMAN TILE CONFIGURATION
;
; tile position x can go from 0x1e to 0x3d.
; 0x1d == wraparound -> 0x3d
; 0x3e == wraparound -> 0x1e
; tile position y can go from 0x22 to 0x3e.
; Why?
; Because of the graphics hardware.
; With that configuration, you can convert directly between
; tile position to hardware sprite positions
;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; rst 0 - initialization
; init
0000 f3 di ; Disable interrupts
0001 3e00 ld a,#00 ; A := #00
0003 ed47 ld i,a ; Clear interrupt status register
0005 c30b23 jp #230b ; jump to startup test
;; PAC
;0001 3e3f ld a,#3f
;;
; rst 8 - memset()
; Fill HL to HL+B with A
0008 77 ld (hl),a ; store A
0009 23 inc hl ; next memory
000a 10fc djnz #0008 ; loop until B == #00
000c c9 ret ; return
; arrive here from #23A7
000d c30e07 jp #070e ; sets up difficulty
; rst 10 (for dereferencing pointers to bytes)
; HL = HL + A, , A := (HL)
; HL = base address of table
; A = index
; after the call, A gets the data in HL+A
0010 85 add a,l ; Add L into A
0011 6f ld l,a ; copy result into L
0012 3e00 ld a,#00 ; A := #00
0014 8c adc a,h ; Add with carry into H
0015 67 ld h,a ; copy result into H
0016 7e ld a,(hl) ; load A with value in HL
0017 c9 ret ; return
; rst 18 (for dereferencing pointers to words)
; hl = hl + 2*b, (hl) -> e, (++hl) -> d, de -> hl
; HL = base address of table
; B = index
; after the call, HL gets the data in HL+(2*B). DE becomes HL+2B
; modified: DE, A
0018 78 ld a,b ; load A with B
0019 87 add a,a ; double it
001a d7 rst #10 ; A:= data in (HL + 2B), HL := HL + 2B
001b 5f ld e,a ; copy result into E
001c 23 inc hl ; next HL
001d 56 ld d,(hl) ; D := (HL+2B+1)
001e eb ex de,hl ; Exchange DE with HL.
001f c9 ret ; return
; rst 20 (jump table)
; Uses A as a vector to jump to the location indicated by 2*A after the call
; For example, if A has #00 and the two bytes following the call are #AB and #CD, the program will jump to #CDAB
0020: E1 pop hl ; load HL with return address. This is the next byte after the call.
0021: 87 add a,a ; A := 2*A
0022: D7 rst #10 ; HL += A, A = (HL)
0023: 5F ld e,a ; Copy first (low) byte to E
0024: 23 inc hl ; next Address
0025: 56 ld d,(hl) ; D = (HL+1) [high byte], so DE = 16-bit address at 2*A after the call
0026: EB ex de,hl ; DE <-> HL
0027: E9 jp (hl) ; jump to HL
; rst 28
; takes the 2 bytes after the call as data and inserts them into the task list
0028 e1 pop hl ; HL = next byte after call, first data element
0029 46 ld b,(hl) ; load B with first data byte
002a 23 inc hl ; next data byte
002b 4e ld c,(hl) ; load C with second data byte
002c 23 inc hl ; HL now has the proper return address
002d e5 push hl ; push to stack so RET will return properly
002e 1812 jr #0042 ; continue this sub below
; rst #30
; when rst #30 is called, the 3 data bytes following the call are inserted
; into the timed task list at the next available location. Up to #10 (16 decimal)
; locations are searched before giving up.
0030: 11 90 4C ld de,#4C90 ; load DE with starting address of task table
0033: 06 10 ld b,#10 ; For B = 1 to #10
0035: C3 51 00 jp #0051 ; continue this sub below
; rst 38 (vblank)
; INTERRUPT MODE 1 handler
0038 c39b1f jp #1f9b ; patched jump from pacman.
003b ----50 ; junk from pac-man
003c 320750 ld (#5007),a ; junk from pac-man
003f c33800 jp #0038 ; junk from pac-man
;; INTERRUPT MODE 2 (original hardware, non-bootlegs, puckman, pac plus)
;0038 af xor a
;0039 320050 ld (#5000),a
;003c 320750 ld (#5007),a
;003f c33800 jp #0038
;;
; continuation of rst 28 from #002E
; this sub can be called with call #0042, if B and C are loaded manually
; B and C have the data bytes
0042 2a804c ld hl,(#4c80) ; load HL with address pointing to the beginning of the task list
0045 70 ld (hl),b ; store task
0046 2c inc l ; next address
0047 71 ld (hl),c ; store parameter
0048 2c inc l ; next address
0049 2002 jr nz,#004d ; If non zero, skip next step
004b 2ec0 ld l,#c0 ; else load L with C0 to cycle HL back to #4CC0 (spins #C0-#FF)
004d 22804c ld (#4c80),hl ; store new task pointer back (4c80, 4c81) = hl
0050 c9 ret ; return to program
; continuation of rst 30 from #0035 (Task manager)
0051: 1A ld a,(de) ; load A with task
0052: A7 and a ; == #00 ?
0053: 28 06 jr z,#005B ; yes, skip ahead, we will insert the new task here
0055: 1C inc e ; else inc E by 3
0056: 1C inc e
0057: 1C inc e ; DE now at next task
0058: 10 F7 djnz #0051 ; Next B, loops up to #10 times
005A: C9 ret ; return
005B: E1 pop hl ; HL = data address of the 3 data bytes to be inserted
005C: 06 03 ld b,#03 ; For B = 1 to 3
005E: 7E ld a,(hl) ; load A with table value
005F: 12 ld (de),a ; store into task list
0060: 23 inc hl ; next HL
0061: 1C inc e ; next DE
0062: 10 FA djnz #005E ; next B
0064: E9 jp (hl) ; return to program (HL now has return address following the 3 data bytes)
; this is a common call
; converts pac-mans sprite position into a grid position
0065 c32d20 jp #202d
; difficulty settings table data - normal #0068
; these are assigned at a routine starting at #070E
0068 00 01 02 03 04 05 06 07
0070 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14
; difficulty settings table data - hard #007D
; these are assigned at a routine starting at #070E
007D 01 03 04
0080 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 14
;; part of the interrupt routine (non-test)
;; continuation of RST 38 partially... (vblank)
;; (gets called from the #1f9b patch, from #0038)
008d f5 push af ; save AF [restored at #01DA]
008e 32c050 ld (#50c0),a ; kick the dog
0091 af xor a ; 0 -> a
0092 320050 ld (#5000),a ; disable hardware interrupts
0095 f3 di ; disable cpu interrupts
; save registers. they are restored starting at #01BF
0096 c5 push bc ; save BC
0097 d5 push de ; save DE
0098 e5 push hl ; save HL
0099 dde5 push ix ; save IX
009b fde5 push iy ; save IY
;;
;; VBLANK - 1 (SOUND)
;;
;; load the sound into the hardware
;;
009d ld hl,#CH1_FREQ0 ; pointer to frequencies and volumes of the 3 voices
00a0 ld de,#5050 ; hardware address
00a3 ld bc,#0010 ; #10 (16 decimal) byte to copy
00a6 ldir ; copy
;; voice 1 wave select
00a8 ld a,(#CH1_W_NUM) ; if we play a wave
00ab and a
00ac ld a,(#CH1_W_SEL) ; then WaveSelect = CH1_W_SEL
00af jr nz,#00b4
00b1 ld a,(#CH1_E_TABLE0) ; else WaveSelect = CH1_E_TABLE0
00b4 ld (#5045),a ; write WaveSelect to hardware
;; voice 2 wave select
00b7 ld a,(#CH2_W_NUM)
00ba and a
00bb ld a,(#CH2_W_SEL)
00be jr nz,#00c3
00c0 ld a,(#CH2_E_TABLE0)
00c3 ld (#504a),a
;; voice 3 wave select
00c6 ld a,(#CH3_W_NUM)
00c9 and a
00ca ld a,(#CH3_W_SEL)
00cd jr nz,#00d2
00cf ld a,(#CH3_E_TABLE0)
00d2 ld (#504f),a
; copy last frame calculated sprite data into sprite buffer
00d5 21024c ld hl,#4c02 ; load HL with source address (calculated sprite data)
00d8 11224c ld de,#4c22 ; load DE with destination (sprite buffer)
00db 011c00 ld bc,#001c ; load counter with #1C bytes to copy
00de edb0 ldir ; copy
; update sprite data, adjusting to hardware
00e0 dd21204c ld ix,#4c20 ; load IX with start of sprite buffer
00e4 dd7e02 ld a,(ix+#02) ; load A with red ghost sprite
00e7 07 rlca
00e8 07 rlca ; rotate 2 bits up
00e9 dd7702 ld (ix+#02),a ; store
00ec dd7e04 ld a,(ix+#04) ; load A with pink ghost sprite
00ef 07 rlca
00f0 07 rlca ; rotate 2 bits up
00f1 dd7704 ld (ix+#04),a ; store
00f4 dd7e06 ld a,(ix+#06) ; load A with blue (inky) ghost sprite
00f7 07 rlca
00f8 07 rlca ; rotate 2 bits up
00f9 dd7706 ld (ix+#06),a ; store
00fc dd7e08 ld a,(ix+#08) ; load A with orange ghost sprite
00ff 07 rlca
0100 07 rlca ; rotate 2 bits up
0101 dd7708 ld (ix+#08),a ; store
0104 dd7e0a ld a,(ix+#0a) ; load A with ms pac sprite
0107 07 rlca
0108 07 rlca ; rotate 2 bits up
0109 dd770a ld (ix+#0a),a ; store
010c dd7e0c ld a,(ix+#0c) ; load A with fruit sprite
010f 07 rlca
0110 07 rlca ; rotate 2 bits up
0111 dd770c ld (ix+#0c),a ; store
0114 3ad14d ld a,(#4dd1) ; load A with killed ghost animation state
0117 fe01 cp #01 ; is there a ghost being eaten ?
0119 2038 jr nz,#0153 ; no , skip ahead
011b dd21204c ld ix,#4c20 ; else load IX with sprite data buffer start
011f 3aa44d ld a,(#4da4) ; load A with the unhandled killed ghost #
0122 87 add a,a ; A := A * 2
0123 5f ld e,a ; copy to E
0124 1600 ld d,#00 ; D := #00
0126 dd19 add ix,de ; add to index. now has the eaten ghost sprite
0128 2a244c ld hl,(#4c24) ; load HL with start of ghost sprite address
012b ed5b344c ld de,(#4c34) ; load DE with sprite number and color for spriteram
012f dd7e00 ld a,(ix+#00) ; load A with eaten ghost sprite
0132 32244c ld (#4c24),a ; store
0135 dd7e01 ld a,(ix+#01) ; load A with next ghost sprite
0138 32254c ld (#4c25),a ; store
013b dd7e10 ld a,(ix+#10) ; load A with eaten ghost spriteram
013e 32344c ld (#4c34),a ; store
0141 dd7e11 ld a,(ix+#11) ; load A with next ghost spriteram
0144 32354c ld (#4c35),a ; store
0147 dd7500 ld (ix+#00),l ;
014a dd7401 ld (ix+#01),h
014d dd7310 ld (ix+#10),e
0150 dd7211 ld (ix+#11),d ; store L, H, E, and D
0153 3aa64d ld a,(#4da6) ; load A with power pill effect (1=active, 0=no effect)
0156 a7 and a ; is a power pill active ?
0157 ca7601 jp z,#0176 ; no, skip ahead
; power pill active
015a ed4b224c ld bc,(#4c22) ; else swap pac for first ghost. load BC with red ghost sprite
015e ed5b324c ld de,(#4c32) ; load DE with highest sprite for spriteram
0162 2a2a4c ld hl,(#4c2a) ; load HL with fruit sprite
0165 22224c ld (#4c22),hl ; store into highest priority sprite
0168 2a3a4c ld hl,(#4c3a) ; load HL with ms pac spriteram
016b 22324c ld (#4c32),hl ; store into highest priority spriteram
016e ed432a4c ld (#4c2a),bc ; store first ghost sprite
0172 ed533a4c ld (#4c3a),de ; store first ghost spriteram
;
0176 21224c ld hl,#4c22 ; load source address with start of sprites
0179 11f24f ld de,#4ff2 ; load destiantion address with spriteram2
017c 010c00 ld bc,#000c ; set counter at #0C bytes
; green eyed ghost bug encountered here
; 4FF2,3 -
; 4FF2,3 - red ghost (8x,11)
; 4FF4,5 - pink ghost (8x,11)
; 4FF6,7 - blue ghost (8x,11)
; 4FF8,9 - orange ghost (8x,11)
017f edb0 ldir ; copy
0181 21324c ld hl,#4c32 ; load source address with start of spriteram
0184 116250 ld de,#5062 ; load destination address with hardware sprite
0187 010c00 ld bc,#000c ; set counter at #0C bytes
018a edb0 ldir ; copy [write updated sprites to spriteram]
;
; Core game loop
;
018c cddc01 call #01dc ; update all timers
018f cd2102 call #0221 ; check timed tasks and execute them if it is time to do so
0192 cdc803 call #03c8 ; runs subprograms based on game mode, power-on stuff, attract mode, push start screen, and core loops for game playing
0195 3a004e ld a,(#4e00) ; load A with game mode
0198 a7 and a ; is the game still in power-on mode ?
0199 2812 jr z,#01ad ; yes, skip over next calls
019B cd9d03 call #039d ; check for double size pacman in intermission (pac-man only)
019E cd9014 call #1490 ; when player 1 or 2 is played without cockatil mode, update all sprites
01a1 cd1f14 call #141f ; when player 2 is played on cockatil mode, update all sprites
01a4 cd6702 call #0267 ; debounce rack input / add credits
01a7 cdad02 call #02ad ; debounce coin input / add credits
01aa cdfd02 call #02fd ; blink coin lights
; print player 1 and player two
; check for game mode 3
; draw cprt stuff
01ad 3a004e ld a,(#4e00) ; load A with game mode
01b0 3d dec a ; are we in the demo mode ?
01b1 2006 jr nz,#01b9 ; no, skip next 2 steps ; set to jr #01b9 to enable sound in demo
01B3: 32 AC 4E ld (#4EAC),a ; yes, clear sound channel 2
01B6: 32 BC 4E ld (#4EBC),a ; clear sound channel 3
;; VBLANK - 2 (SOUND)
;;
;; Process sound
01b9 call #2d0c ; process effects
01bc call #2cc1 ; process waves
; restore registers. they were saved at #0096
01bf fde1 pop iy ; restore IY
01c1 dde1 pop ix ; restore IX
01c3 e1 pop hl ; restore HL
01c4 d1 pop de ; restore DE
01c5 c1 pop bc ; restore BC
;
01c6 3a004e ld a,(#4e00) ; load A with game mode
01c9 a7 and a ; is this the initialization?
01ca 2808 jr z,#01d4 ; yes, skip ahead
01cc 3a4050 ld a,(#5040) ; else load A with IN1
01cf e610 and #10 ; is the service mode switch set ?
; elimiate test mode ; HACK7
;01d1 00 nop
;01d2 00 nop
;01d3 00 nop
;
01d1 ca0000 jp z,#0000 ; yes, reset
01d4 3e01 ld a,#01 ; else A := #01
01d6 320050 ld (#5000),a ; reenable hardware interrupts
01d9 fb ei ; enable cpu interrupts
01da f1 pop af ; restore AF [was saved at #008D]
01db c9 ret ; return
; called from #018C
; this sub increments the timers and random numbers from #4C84 to #4C8C
01dc 21844c ld hl,#4c84 ; load HL with sound counter address
01df 34 inc (hl) ; increment
01e0 23 inc hl ; load HL with 2nd sound counter address
01e1 35 dec (hl) ; decrement
01e2 23 inc hl ; next address. HL now has #4C86
01e3 111902 ld de,#0219 ; load DE with start of table data
01e6 010104 ld bc,#0401 ; C := #01, For B = 1 to 4,
01e9 34 inc (hl) ; increase memory
01ea 7e ld a,(hl) ; load A with this value
01eb e60f and #0f ; mask bits, now between #00 and #0F
01ed eb ex de,hl ; DE <-> HL
01ee be cp (hl) ; compare with value in table
01ef 2013 jr nz,#0204 ; if not equal, break out of loop
01f1 0c inc c ; else C := C + 1
01f2 1a ld a,(de) ; load A with the value
01f3 c610 add a,#10 ; add #10
01f5 e6f0 and #f0 ; mask bits
01f7 12 ld (de),a ; store result
01f8 23 inc hl ; next table value
01f9 be cp (hl) ; compare with value in table
01fa 2008 jr nz,#0204 ; if not equal, break out of loop
01fc 0c inc c ; else C := C + 1
01fd eb ex de,hl ; DE <-> HL
01fe 3600 ld (hl),#00 ; clear the value in HL
0200 23 inc hl ; next HL
0201 13 inc de ; next table value
0202 10e5 djnz #01e9 ; loop
; set up psuedo random number generator values, #4C8A, #4C8B, #4C8C
0204 218a4c ld hl,#4c8a ; load HL with timer address
0207 71 ld (hl),c ; store C which was computed above
0208 2c inc l ; next address. HL now has #4C8B
0209 7e ld a,(hl) ; load A with the value from this timer
020a 87 add a,a ; A := A * 2
020b 87 add a,a ; A := A * 2
020c 86 add a,(hl) ; A := A + (HL) (A is now 5 times what it was)
020d 3c inc a ; increment. (A is now 5 times plus 1 what it was)
020e 77 ld (hl),a ; store new value
020f 2c inc l ; next address. HL now has #4C8C
0210 7e ld a,(hl) ; load A with the value from this timer
0211 87 add a,a ; A := A * 2
0212 86 add a,(hl) ; A := A + (HL) (A is now 3 times what it was)
0213 87 add a,a ; A := A * 2
0214 87 add a,a ; A := A * 2
0215 86 add a,(hl) ; A := A + (HL) (A is now 13 times what it was)
0216 3c inc a ; increment. (A is now 13 times plus 1 what it was)
0217 77 ld (hl),a ; store result
0218 c9 ret ; return
; data used in subrotine above, loaded at #01E3
0219 06 A0 0A 60 0A 60 0A A0
; checks timed tasks
; counts down timer and executes the task if the timer has expired
; called from #018F
0221: 21 90 4C ld hl,#4C90 ; load HL with task list address
0224: 3A 8A 4C ld a,(#4C8A) ; load A with number of counter limits changes in this frame
0227: 4F ld c,a ; save to C for testing in line #0232
0228: 06 10 ld b,#10 ; for B = 1 to #10
022A: 7E ld a,(hl) ; load A with task list first value (timer)
022B: A7 and a ; == #00 ? (is this task empty?)
022C: 28 2F jr z,#025D ; Yes, jump ahead and loop for next task
022E: E6 C0 and #C0 ; else mask bits with binary 1100 0000 - the left 2 bits (6 and 7) are the time units
0230: 07 rlca
0231: 07 rlca ; rotate twice left. The time unit bits are now rightmost, in bits 0 and 1. EG #02 for seconds
0232: B9 cp c ; compare to counter. is it time to count down the timer?
0233: 30 28 jr nc,#025D ; if no, jump ahead and loop for next task
0235: 35 dec (hl) ; else decrease the task timer
0236: 7E ld a,(hl) ; load A with new task timer
0237: E6 3F and #3F ; mask bits with binary 0011 1111. This will erase the units in the left 2 bits. is the timer counted all the way down?
0239: 20 22 jr nz,#025D ; no, jump ahead and loop for next task
023B: 77 ld (hl),a ; yes, store A into task timer. this should be zero and effectively clears the task
023C: C5 push bc ; save BC
023D: E5 push hl ; save HL
023E: 2C inc l ; HL now has the coded task number address
023F: 7E ld a,(hl) ; load A with task number, used for jump table below
0240: 2C inc l ; HL now has the coded task parameter address
0241: 46 ld b,(hl) ; load B with task parameter
0242: 21 5B 02 ld hl,#025B ; load HL with return address
0245: E5 push hl ; push to stack so a RET call will return to #025B
0246: E7 rst #20 ; jump based on A
0247: 94 08 ; A==0, #0894 ; increases main subroutine number (#4E04) and returns
0249: A3 06 ; A==1, #06A3 ; increments main routine 2, subroutine # (#4E03)
024B: 8E 05 ; A==2, #058E ; increases the main routine # (#4E02)
024D: 72 12 ; A==3, #1272 ; increases killed ghost animation state when a ghost is eaten
024F: 00 10 ; A==4, #1000 ; clears the fruit sprite
0251: 0B 10 ; A==5, #100B ; clears the fruit score sprite
0253: 63 02 ; A==6, #0263 ; clears the "READY!" message
0255: 2B 21 ; A==7, #212B ; to increase state in 1st cutscene (#4E06) (pac-man only)
0257: F0 21 ; A==8, #21F0 ; to increase state in 2nd cutscene (#4E07) (pac-man only)
0259: B9 22 ; A==9, #22B9 ; to increase state in 3rd cutscene (#4E08) (pac-man only)
025B: E1 pop hl ; restore HL
025C: C1 pop bc ; restore BC
025D: 2C inc l
025E: 2C inc l
025F: 2C inc l ; next task
0260: 10 C8 djnz #022A ; next B
0262: C9 ret ; return
; timed task #06 - clears ready message
0263 EF rst #28 ; insert task #1C, parameter 86 to clear the "READY!" message
0264 1C 86 ; task data
0266 C9 ret ; return
;; debounce rack input / add credits (if 99 or over, return)
; called from #01A4
0267 3a6e4e ld a,(#4e6e) ; load A with number of current credits in BCD
026a fe99 cp #99 ; == #99 ? (99 is max number of credits avail)
026c 17 rla ; rotate left A
026d 320650 ld (#5006),a ; store into #5006 (coin lockout, not used ?)
0270 1f rra ; rotate right A
0271 d0 ret nc ; return if 99 credits
0272 3a0050 ld a,(#5000) ; load A with IN0 input (joystick, credits, service mode button)
0275 47 ld b,a ; copy to B
0276 cb00 rlc b ; rotate left
0278 3a664e ld a,(#4e66) ; load A with service mode indicator
027b 17 rla ; rotate left with carry
027c e60f and #0f ; and it with #0F
027e 32664e ld (#4e66),a ; put it back
0281 d60c sub #0c ; subtract #0C. is the service mode being used to add a credit?
0283 ccdf02 call z,#02df ; If yes, call #02df ; add credit
0286 cb00 rlc b ; rotate left B
0288 3a674e ld a,(#4e67) ; load A with coin input #1
028b 17 rla ; rotate left
028c e60f and #0f ; mask bits
028e 32674e ld (#4e67),a ; put back
0291 d60c sub #0c ; subtract C. is a coin being inserted?
0293 c29a02 jp nz,#029a ; no, skip ahead
0296 21694e ld hl,#4e69 ; yes, load HL with coin counter
0299 34 inc (hl) ; increase counter
029a cb00 rlc b ; rotaate left B
029c 3a684e ld a,(#4e68) ; load A with coint input #2
029f 17 rla ; rotate left
02a0 e60f and #0f ; maks bits
02a2 32684e ld (#4e68),a ; put back
02a5 d60c sub #0c ; subtract #0C. is a coin being inserted?
02a7 c0 ret nz ; no, return
02a8 21694e ld hl,#4e69 ; else load HL with coin counter
02ab 34 inc (hl) ; increase
02ac c9 ret ; return
;; debounce coin input / add credits
; called from #01A7
02ad 3a694e ld a,(#4e69) ; load A with coin counter
02b0 a7 and a ; == #00 ?
02b1 c8 ret z ; yes, return
02b2 47 ld b,a ; else copy coin counter to B
02b3 3a6a4e ld a,(#4e6a) ; load A with coin counter timeout
02b6 5f ld e,a ; copy timeout to E
02b7 fe00 cp #00 ; is the timeout == #00?
02b9 c2c402 jp nz,#02c4 ; no, skip ahead
02bc 3e01 ld a,#01 ; else A := #01
02be 320750 ld (#5007),a ; store into coin counter
02c1 cddf02 call #02df ; call coins -> credits routine
02c4 7b ld a,e ; load A with timeout
02c5 fe08 cp #08 ; is the timeout == #08 ?
02c7 c2ce02 jp nz,#02ce ; no, skip next 2 steps
02ca af xor a ; A := #00
02cb 320750 ld (#5007),a ; clear coin counter
02ce 1c inc e ; increment timeout
02cf 7b ld a,e ; copy to A
02d0 326a4e ld (#4e6a),a ; store into coin counter timeout
02d3 d610 sub #10 ; subtract #10. did the timeout end?
02d5 c0 ret nz ; no, return
02d6 326a4e ld (#4e6a),a ; else clear the counter timeout [A now has #00]
02d9 05 dec b ; decrement B, this was a copy of the coin counter
02da 78 ld a,b ; copy to A
02db 32694e ld (#4e69),a ; store into coin counter
02de c9 ret ; return
;; coins -> credits routine
02df 3a6b4e ld a,(#4e6b) ; load A with #coins per #credits
02e2 216c4e ld hl,#4e6c ; load HL with # of leftover coins
02e5 34 inc (hl) ; add 1
02e6 96 sub (hl) ; subract this value from A
02e7 c0 ret nz ; if not zero, then not enough coins for credits. return
02e8 77 ld (hl),a ; else store A into leftover coins
02e9 3a6d4e ld a,(#4e6d) ; load A with #credits per #coins
02ec 216e4e ld hl,#4e6e ; load HL with #credits
02ef 86 add a,(hl) ; add # credits
02f0 27 daa ; decimal adjust
02f1 d2f602 jp nc,#02f6 ; if no carry, skip ahead
02f4 3e99 ld a,#99 ; else load a with #99
02f6 77 ld (hl),a ; store #credits, max #99
02f7 219c4e ld hl,#4e9c ; load HL with sound register
02fa cbce set 1,(hl) ; play credit sound
02fc c9 ret ; return
;; blink coin lights, print player 1 and player 2, check for mode 3
; called from #01AA
02fd 21ce4d ld hl,#4dce ; load HL with counter started after insert coin (LED and 1UP/2UP blink)
0300 34 inc (hl) ; increment counter
0301 7e ld a,(hl) ; load A with counter
0302 e60f and #0f ; mask 4 left bits to zero
0304 201f jr nz,#0325 ; skip ahead if result is not zero
0306 7e ld a,(hl) ; load A with counter
0307 0f rrca
0308 0f rrca
0309 0f rrca
030a 0f rrca ; shift right 4 times
030b 47 ld b,a ; copy A to B
;; blink coin lights to pellets ; HACK9
;;
;; 030c 3aa74d ld a,(#4da7)
;; 030f 4f ld c,a
;; 0310 180b jr #0317
;;
030c 3ad64d ld a,(#4dd6) ; load A with LED state (1: game waits for 1P/2P start button press)
030f 2f cpl ; 1's complement of A
0310 b0 or b ; or with B
0311 4f ld c,a ; load C with result
0312 3a6e4e ld a,(#4e6e) ; load A with number of credits
0315 d601 sub #01 ; subtract one from it.
0317 3002 jr nc,#031b ; if no carry then skip next 2 steps
0319 af xor a ; A := #00
031a 4f ld c,a ; c := #00
031b 2801 jr z,#031e ; If zero then skip next step
031d 79 ld a,c ; else load A with C
031e 320550 ld (#5005),a ; Store A into player 2 start lamp
0321 79 ld a,c ; load A with C
0322 320450 ld (#5004),a ; store A into player 1 start lamp
0325 dd21d843 ld ix,#43d8 ; load IX with start address where the screen shows "1UP"
0329 fd21c543 ld iy,#43c5 ; load IY with start address where the screen shows "1UP"
032d 3a004e ld a,(#4e00) ; load A with game mode
0330 fe03 cp #03 ; is a game being played ?
0332 ca4403 jp z,#0344 ; Yes, Jump ahead
0335 3a034e ld a,(#4e03) ; else load A with main routine 2, subroutine #
0338 fe02 cp #02 ; <= 2 ?
033a d24403 jp nc,#0344 ; yes, skip ahead
033d cd6903 call #0369 ; else draw "1UP"
0340 cd7603 call #0376 ; draw "2UP"
0343 c9 ret ; return
;; display and blink 1UP/2UP depending on player up
0344 3a094e ld a,(#4e09) ; load A with current player number: 0=P1, 1=P2
0347 a7 and a ; is this player 1 ?
0348 3ace4d ld a,(#4dce) ; load A with counter started after insert coin (LED and 1UP/2UP blink)
034b c25903 jp nz,#0359 ;
034e cb67 bit 4,a ; test bit 4 of the counter. is it on?
0350 cc6903 call z,#0369 ; no, draw "1UP"
0353 c48303 call nz,#0383 ; yes, clear "1UP"
0356 c36103 jp #0361 ; skip ahead
0359 cb67 bit 4,a ; test bit 4 of the counter. is it on?
035b cc7603 call z,#0376 ; no, draw "2UP"
035e c49003 call nz,#0390 ; yes, clear "2UP"
0361 3a704e ld a,(#4e70) ; load A with player# (0=player1, 1=player2)
0364 a7 and a ; is this player 1 ?
0365 cc9003 call z,#0390 ; yes, clear "2UP"
0368 c9 ret ; return
; draw "1UP"
0369 dd360050 ld (ix+#00),#50 ; 'P'
036d dd360155 ld (ix+#01),#55 ; 'U'
0371 dd360231 ld (ix+#02),#31 ; '1'
0375 c9 ret
; draw "2UP"
0376 fd360050 ld (iy+#00),#50 ; 'P'
037a fd360155 ld (iy+#01),#55 ; 'U'
037e fd360232 ld (iy+#02),#32 ; '2'
0382 c9 ret
; clear "1UP"
0383 dd360040 ld (ix+#00),#40 ; ' '
0387 dd360140 ld (ix+#01),#40 ; ' '
038b dd360240 ld (ix+#02),#40 ; ' '
038f c9 ret
; clear "2UP"
0390 fd360040 ld (iy+#00),#40 ; ' '
0394 fd360140 ld (iy+#01),#40 ; ' '
0398 fd360240 ld (iy+#02),#40 ; ' '
039c c9 ret
; draws big pacman in intermission. used for pac-man only, not ms.pac
; called from #019b
039d 3a064e ld a,(#4e06) ; load A with 1st intermission counter
03a0 d605 sub #05 ; is big-pac onscreen ?
03a2 d8 ret c ; no, return. (always returns in ms. pacman)
; draw big pac (pac-man only, during 1st cutscene)
03a3 2a084d ld hl,(#4d08)
03a6 0608 ld b,#08
03a8 0e10 ld c,#10
03aa 7d ld a,l
03ab 32064d ld (#4d06),a
03ae 32d24d ld (#4dd2),a
03b1 91 sub c
03b2 32024d ld (#4d02),a
03b5 32044d ld (#4d04),a
03b8 7c ld a,h
03b9 80 add a,b
03ba 32034d ld (#4d03),a
03bd 32074d ld (#4d07),a
03c0 91 sub c
03c1 32054d ld (#4d05),a
03c4 32d34d ld (#4dd3),a
03c7 c9 ret
;; enable sound out and other stuff
; called from #0192
03c8 3a004e ld a,(#4e00) ; load A with game mode
03cb e7 rst #20 ; jump based on A
03cc d4 03 ;#03D4 ;#4E00 = 0 ;GAME POWER ON
03ce fe 03 ;#03FE ;#4E00 = 1 ;ALL ATTRACT MODES. this runs until a credit is inserted
03d0 e5 05 ;#05E5 ;#4E00 = 2 ;PLAYER 1 OR 2 SCREEN. draw screen and wait for start to be pressed
03d2 be 06 ;#06BE ;#4E00 = 3 ;PLAYER 1 OR 2 PLAYING. runs core game loop
; arrive here after power on
03d4 3a014e ld a,(#4e01) ; load A with main routine 0, subroutine #
03d5 e7 rst #20 ; jump based on A
03D8: DC 03 ; #03DC
03DA: 0C 00 ; #000C. returns immediately (to #0195)
; arrive here after powering on
; this sets up the following tasks
03DC: EF rst #28 ; insert task to clear the whole screen
03DD: 00 00 ; data for above, task #00
03DF: EF rst #28 ; insert task to clear the color RAM
03E0: 06 00 ; data for above, task #06
03e2 ef rst #28 ; insert task color the maze
03e3 01 00 ; data for above, task #01
03e5 ef rst #28 ; insert task to check all dip switches and assign memories to the settings indicated
03e6 14 00 ; data for above, task #14
03e8 ef rst #28 ; insert task - draws "high score" and scores. clears player 1 and 2 scores to zero.
03e9 18 00 ; data for above, task #18
03eb ef rst #28 ; insert task - resets a bunch of memories
03ec 04 00 ; data for above, task #04
03ee ef rst #28 ; insert task - clear fruit, pacman, and all ghosts
03ef 1e 00 ; data for above, task #1E
03f1 ef rst #28 ; insert task - set game to demo mode
03f2 07 00 ; data for above, task #07
03F4: 21 01 4E ld hl,#4E01 ; load HL with main routine 0, subroutine #
03F7: 34 inc (hl) ; increase so this sub doesn't run again.
03f8 210150 ld hl,#5001 ; load HL with sound address
03fb 3601 ld (hl),#01 ; enable sound
03fd c9 ret ; return
; attract mode main routine
03fe cda12b call #2ba1 ; write # of credits on screen
0401 3a6e4e ld a,(#4e6e) ; load A with # of credits
0404 a7 and a ; == #00 ?
0405 280c jr z,#0413 ; yes, skip ahead
0407 af xor a ; else A := #00
0408 32044e ld (#4e04),a ; clear level state subroutine #
040b 32024e ld (#4e02),a ; clear main routine 1, subroutine #
040e 21004e ld hl,#4e00 ; load HL with game mode
0411 34 inc (hl) ; increase game mode to press start screen
0412 c9 ret ; return (to #0195)
; table lookup
; OTTOPATCH
;PATCH FOR NEW ATTRACT MODE
ORG 0413H
JP ATTRACT
0413 c35c3e jp #3e5c ; jump to mspac patch when there are no credits - controls the demo mode
; code resumes at #045F
; Pac-man code:
; 0413 3a024e ld a,(#4e02) ; load A with main routine 1, subroutine #
; end Pac-man code
0416 e7 rst #20 ; jump based on A (pac-man only)
; jump table based from value in #4E02
; task routine to draw out the attract screen, only used in pac-man, not ms. pac
0417 5f 04 ; #045F ;(#4e02)=#00 ; clear screen, reset memories, clear sprites
0419 0c 00 ; #000C ;(#4e02)=#01 ; returns immediately
041b 71 04 ; #0471 ;(#4e02)=#02 ; draw red ghost
041d 0c 00 ; #000C ;(#4e02)=#03 ; returns immediately
041f 7f 04 ; #047F ;(#4e02)=#04 ; draw "-SHADOW"
0421 0C 00 ; #000C ;(#4e02)=#05 ; returns immediately
0423 85 04 ; #0485 ;(#4e02)=#06 ; draw ""BLINKY""
0425 0c 00 ; #000C ;(#4e02)=#07 ; returns immediately
0427 8b 04 ; #048B ;(#4e02)=#08 ; draw pink ghost
0429 0c 00 ; #000C ;(#4e02)=#09 ; returns immediately
042b 99 04 ; #0499 ;(#4e02)=#0A ; draw "-SPEEDY"
042d 0c 00 ; #000C ;(#4e02)=#0B ; returns immediately
042f 9f 04 ; #049F ;(#4e02)=#0C ; draw ""PINKY""
0431 0c 00 ; #000C ;(#4e02)=#0D ; returns immediately
0433 a5 04 ; #04A5 ;(#4e02)=#0E ; draw blue ghost (inky)
0435 0c 00 ; #000C ;(#4e02)=#0F ; returns immediately
0437 b3 04 ; #04B3 ;(#4E02)=#10 ; draw "-BASHFUL"
0439: 0C 00 ; #000C ;(#4E02)=#11 ; returns immediately
043B: B9 04 ; #04B9 ;(#4E02)=#12 ; draw ""INKY""
043D: 0C 00 ; #000C ;(#4E02)=#13 ; returns immediately
043F: BF 04 ; #04BF ;(#4E02)=#14 ; draw orange ghost
0441: 0C 00 ; #000C ;(#4E02)=#15 ; returns immediately
0443: CD 04 ; #04CD ;(#4E02)=#16 ; draw "-POKEY"
4445: 0C 00 ; #000C ;(#4E02)=#17 ; returns immediately
0447: D3 04 ; #04D3 ;(#4E02)=#18 ; draw ""CLYDE""
0449: 0C 00 ; #000C ;(#4E02)=#19 ; returns immediately
044B: D8 04 ; #04D8 ;(#4E02)=#1A ; draw ". 10 Pts" and "o 50pts"
044D: 0C 00 ; #000C ;(#4E02)=#1B ; returns immediately
044F: E0 04 ; #04E0 ;(#4E02)=#1C ; get demo ready and draw invisible maze
0451: 0C 00 ; #000C ;(#4E02)=#1D ; returns immediately
0453: 1C 05 ; #051C ;(#4E02)=#1E ; start and run demo
0455: 4B 05 ; #054B ;(#4E02)=#1F ; check to release pink ghost
0457: 56 05 ; #0556 ;(#4E02)=#20 ; check to release inky
0459: 61 05 ; #0561 ;(#4E02)=#21 ; check to release orange ghost
045B: 6C 05 ; #056C ;(#4E02)=#22 ; check for completion of demo
045D: 7C 05 ; #057C ;(#4E02)=#23 ; end demo and return to program
; ms. pac code resumes here
; arrive here from #3E67 when subroutine # = 00
; sets up the attract mode
045f ef rst #28 ; insert task #00 - clears the maze
0460 00 01
0462 ef rst #28 ; insert task #01 - colors the screen
0464 01 00
0465 ef rst #28 ; insert task #04 - resets a bunch of memories
0466 04 00
0468 ef rst #28 ; insert task #1E - clear fruit, pacman and all ghosts
0469 1e 00
046b 0e0c ld c,#0c ; load C with text code for "Ms Pac Man"
046d cd8505 call #0585 ; draw text to screen, increase subroutine #
0470 c9 ret ; return (to #0195)
; pac-man only attract mode code from #0471 to #0579
0471 210443 ld hl,#4304 ; load HL with starting screen address of stationary red ghost
0474 3e01 ld a,#01 ; load A with the color code for red
0476 cdbf05 call #05bf ; draw stationary red ghost on screen
0479 0e0c ld c,#0c ; load C with text code for "CHARACTER / NICKNAME"
047b cd8505 call #0585 ; insert task to write text to screen
047e c9 ret ; return
047f 0e14 ld c,#14 ; load C with text code for "-SHADOW"
0481 cd9305 call #0593 ; draw text to screen
0484 c9 ret ; return
0485 0e0d ld c,#0d ; load C with text code for ""BLINKY""
0487 cd9305 call #0593 ; draw text to screen
048a c9 ret ; return
048b 210743 ld hl,#4307 ; load HL with starting screen address of stationary pink ghost
048e 3e03 ld a,#03 ; load A with color code for pink
0490 cdbf05 call #05bf ; draw stationary pink ghost on screen
0493 0e0c ld c,#0c ; load C with text code for "CHARACTER / NICKNAME"
0495 cd8505 call #0585 ; insert task to write text to screen
0498 c9 ret ; return
0499 0e16 ld c,#16 ; load C with text code for "-SPEEDY"
049b cd9305 call #0593 ; draw text to screen
049e c9 ret ; return
049f 0e0f ld c,#0f ; load C with text code for ""PINKY""
04a1 cd9305 call #0593 ; draw text to screen
04a4 c9 ret ; return
04a5 210a43 ld hl,#430a ; load HL with starting screen address of stationary blue ghost (inky)
04a8 3e05 ld a,#05 ; load A with color code for light blue
04aa cdbf05 call #05bf ; draw stationary inky on screen
04ad 0e0c ld c,#0c ; load C with text code for "CHARACTER / NICKNAME"
04af cd8505 call #0585 ; insert task to write text to screen
04b2 c9 ret ; return
04b3 0e33 ld c,#33 ; load C with text code for "-BASHFUL"
04b5 cd9305 call #0593 ; draw text to screen
04b8 c9 ret ; return
04b9 0e2f ld c,#2f ; load C with text code for ""INKY""
04bb cd9305 call #0593 ; draw text to screen
04be c9 ret ; return
04bf 210d43 ld hl,#430d ; load HL with starting screen address of staionary orange ghost
04c2 3e07 ld a,#07 ; load A with color code for orange
04c4 cdbf05 call #05bf ; draw stationary orange ghost on screen
04c7 0e0c ld c,#0c ; load C with text code for "CHARACTER / NICKNAME"
04c9 cd8505 call #0585 ; insert task to write text to screen
04cc c9 ret ; return
04cd 0e35 ld c,#35 ; load C with text code for "-POKEY"
04cf cd9305 call #0593 ; draw text on screen
04d2 c9 ret ; return
04d3 0e31 ld c,#31 ; load C with text code for ""CLYDE""
04d5 c38005 jp #0580 ; draw text and increase game mode
04d8 ef rst #28 ; insert task to write text ". 10 Pts"
04d9 1c 11
04da 0e12 ld c,#12
04dd c38505 jp #0585 ; insert task to write text "o 50 Pts"
04e0 0e13 ld c,#13 ; load C with text code for "(C) MIDWAY MFG CO"
04e2 cd8505 call #0585 ; insert task to write text to screen
04e5 cd7908 call #0879 ; setup game start variables
04e8 35 dec (hl)
04e9 ef rst #28 ; set task #11 to clear memories #4d00 through #4dff
04ea 11 00
04ec ef rst #28 ; set task #05 to reset ghost home counter
04ed 05 01
04EF ef rst #28 ; set task #10 to set up difficulty
04F0 10 14
04f2 ef rst #28 ; set task #04 to reset a bunch of memories and set up sprite locations for demo mode
04f3 04 01
04f4 3e01 ld a,#01 ; A := #01
04f7 32144e ld (#4e14),a ; store into number of lives left
04fa af xor a ; A := #00
04fb 32704e ld (#4e70),a ; store into number of players ( 0=1 1=2 )
04fe 32154e ld (#4e15),a ; store into number of lives displayed
0501 213243 ld hl,#4332 ; load HL with screen address where energizer is in attract mode
0504 3614 ld (hl),#14 ; draw energizer
0506 3efc ld a,#fc ; load A with code for invisible maze block
0508 112000 ld de,#0020 ; load DE with offset for columns
050b 061c ld b,#1c ; For B = 1 to #1C
050d dd214040 ld ix,#4040 ; load IX with start address of video memory for playfield
0511 dd7711 ld (ix+#11),a ; draw invisible maze block
0514 dd7713 ld (ix+#13),a ; draw invisible maze block
0517 dd19 add ix,de ; add offset for next column
0519 10f6 djnz #0511 ; Next B
051b c9 ret ; return
; called during attract mode, pac-man only, not ms. pac
051c 21a04d ld hl,#4da0 ; load HL with red ghost substate address
051f 0621 ld b,#21 ; B := #21
0521 3a3a4d ld a,(#4d3a) ; load A with pacman X tile position
0524 90 sub b ; has pacman/ghost reached the far right side of the screen?
0525 2005 jr nz,#052c ; no, skip ahead and do a core loop
0527 3601 ld (hl),#01 ; yes, change ghost substate to going for pac-man
0529 c38e05 jp #058e ; jump ahead, increase game state and return
; a core game loop used in pac-man demo mode only, not used in ms. pac
052c cd1710 call #1017 ; another core game loop which does many things
052f cd1710 call #1017 ; another core game loop which does many things
0532 cd230e call #0e23 ; change animation of ghosts every 8th frame
0535 cd0d0c call #0c0d ; handle power pill flashes
0538 cdd60b call #0bd6 ; set ghost colors
053b cda505 call #05a5 ; check for direction reversal after eating power pill
053e cdfe1e call #1efe ; check for red ghost direction reversal
0541 cd251f call #1f25 ; check for pink ghost direction reversal
0544 cd4c1f call #1f4c ; check for blue ghost (inky) direction reversal
0547 cd731f call #1f73 ; check for orange ghost direction reversal
054a c9 ret
054b 21a14d ld hl,#4da1 ; load HL with pink ghost substate
054e 0620 ld b,#20 ; B := #20
0550 3a324d ld a,(#4d32) ; load A with red ghost X tile position 2
0553 c32405 jp #0524 ; check for reaching position to release next ghost
0556 21a24d ld hl,#4da2 ; load HL with blue ghost (inky) substate
0559 0622 ld b,#22 ; B := #22
055b 3a324d ld a,(#4d32) ; load A with red ghost X tile position 2
055e c32405 jp #0524 ; check for reaching position to release next ghost
0561 21a34d ld hl,#4da3 ; load HL with orange ghost substate
0564 0624 ld b,#24 ; B := #24
0566 3a324d ld a,(#4d32) ; load A with red ghost X tile position 2
0569 c32405 jp #0524 ; check for reaching position to release next ghost
056c 3ad04d ld a,(#4dd0) ; load A with current number of killed ghosts
056f 47 ld b,a ; copy to B
0570 3ad14d ld a,(#4dd1) ; load A with killed ghost animation state
0573 80 add a,b ; add to number of killed ghosts
0574 fe06 cp #06 ; == #06? (are we done ?)
0576 ca8e05 jp z,#058e ; yes, skip ahead and increase subroutine number
0579 c32c05 jp #052c ; no, loop back again to core loop
; arrive here in demo mode from #3ECD
057c cdbe06 call #06be ; jump to new subroutine based on game state
057f c9 ret ; returns to #0195
; pac-man only ???
; arrive here from #04D5
0580 3a754e ld a,(#4e75) ; load A with ghost name mode (0 or 1)
0583 81 add a,c
0584 4f ld c,a
; called from #046D and other places. C is preloaded with the text code to display
0585 061c ld b,#1c ; load B with task code for text display
0587 cd4200 call #0042 ; insert task to display text, parameter = variable text
058a f7 rst #30 ; insert timed task to increase the main routine # (#4E02)
058b 4a 02 00 ; timer = #4A, task = 2, parameter = 0
; BUGFIX03 - Blue maze - Don Hodges
058b 41 02 00 ; 41 is 1/10 second rather than 1 second
; called from # 0246 from jump table based on game state
; or, timed task number #02 has been encountered, arrive from #0246
; also arrive from #3E93 during marquee mode in demo
058e 21024e ld hl,#4E02 ; load HL with main routine 1, subroutine #
0591 34 inc (hl) ; increase
0592 c9 ret ; return
; pac-man only - used in demo mode for introducing ghost names
; called from several places after C has been preloaded with ghost name code
0593 3a754e ld a,(#4e75) ; Load A with ghost name mode (0 or 1)
0596 81 add a,c ; add to C
0597 4f ld c,a ; load result into C
0598 061c ld b,#1c ; load B with task code for text display
059a cd4200 call #0042 ; set task to display ghost name
059d f7 rst #30 ; set timed task to increase the main routine # (#4E02)
059e 45 02 00 ; data for rst #30 above. timer=45, task=2, param=0
05a1 cd8e05 call #058e ; increase main routine 1, subroutine # (#4E02)
05a4 c9 ret ; return
; pac-man only, used during attract mode when pac-man moves toward energizer followed by the 4 ghosts
05a5 3ab54d ld a,(#4db5) ; load A with pacman change orientation flag
05a8 a7 and a ; == #00 ?
05a9 c8 ret z ; yes, return
; pac-man only, used during attract mode when pac-man reaches the energizer
05aa af xor a ; no, A := #00
05ab 32b54d ld (#4db5),a ; store into pacman change orientation flag
05ae 3a304d ld a,(#4d30) ; load A with pacman orientation
05b1 ee02 xor #02 ; flip bit = change direction
05b3 323c4d ld (#4d3c),a ; store into wanted pacman orientation
05b6 47 ld b,a ; store into B
05b7 21ff32 ld hl,#32ff ; load HL with tile direction table
05ba df rst #18 ; load HL with tile direction based on direction
05bb 22264d ld (#4d26),hl ; store into wanted pacman tile changes
05be c9 ret ; return
; pac-man only, used during attract mode to draw the stationary ghosts during introductions
; HL is preloaded with starting screen address,
; A is preloaded with the ghost color code
05bf 36b1 ld (hl),#b1 ; draw first part of ghost
05c1 2c inc l
05c2 36b3 ld (hl),#b3 ; draw 2nd part of ghost
05c4 2c inc l
05c5 36b5 ld (hl),#b5 ; draw 3rd part of ghost
05c7 011e00 ld bc,#001e ; load BC with offset for next column
05ca 09 add hl,bc ; add offset
05cb 36b0 ld (hl),#b0 ; draw 4th part of ghost
05cd 2c inc l
05ce 36b2 ld (hl),#b2 ; draw 5th part of ghost
05d0 2c inc l
05d1 36b4 ld (hl),#b4 ; draw last part of ghost
05d3 110004 ld de,#0400
05d6 19 add hl,de ; add offset for color
05d7 77 ld (hl),a ; color last part of ghost
05d8 2d dec l
05d9 77 ld (hl),a ; color 5th part of ghost
05da 2d dec l
05db 77 ld (hl),a ; color 4th part of ghost
05dc a7 and a ; clear carry flag
05dd ed42 sbc hl,bc ; subtract offset for previous column
05df 77 ld (hl),a ; color 3rd part of ghost
05e0 2d dec l
05e1 77 ld (hl),a ; color 2nd part of ghost
05e2 2d dec l
05e3 77 ld (hl),a ; color first part of ghost
05e4 c9 ret ; return
; arrive from #03CB
; arrive here when credit has been inserted and game is waiting for start button to be pressed
05E5: 3A 03 4E ld a,(#4E03) ; load A with main routine 2, subroutine #
05E8: E7 rst #20 ; jump based on A
05E9: F3 05 ; #05F3 ; inserts tasks to draw info on screen
05EB: 1B 06 ; #061B ; display 1/2 player and check start buttons
05ED: 74 06 ; #0674 ; run when start button pressed, gets game ready to be played
05EF: 0C 00 ; #000C ; returns immediately
05F1: A8 06 ; #06A8 ; draw remaining lives at bottom of screen and start game
05F3: CD A1 2B call #2BA1 ; write # of credits on screen
05F6: EF rst #28 ; insert task to clear the maze
05F7: 00 01 ; task #00, parameter #01
05F9: EF rst #28 ; insert task to color the maze
05FB: 01 00 ; task #01
05FC: EF rst #28 ; insert task to display "PUSH START BUTTON"
05FD: 1C 07 ; task #1c, parameter #07.
05FF: EF rst #28 ; insert task to display "ADDITIONAL AT 000"
0600: 1C 0B ; task #1C, parameter #0B.
0602: EF rst #28 ; insert task to clear fruit, pacman, and all ghosts
0603: 1E 00 ; task #1E
0605: 21 03 4E ld hl,#4E03 ; load HL with main routine 2, subroutine #
0608: 34 inc (hl) ; increase
0609: 3E 01 ld a,#01 ; A := #01
060B: 32 D6 4D ld (#4DD6),a ; store in LED state ( 1: game waits for 1P/2P start button press)
060E: 3A 71 4E ld a,(#4E71) ; load A with setting for bonus life
0611: FE FF cp #FF ; does this game award any bonus lives?
0613: C8 ret z ; no, return
0614: EF rst #28 ; else insert task to draw the MS PAC MAN graphic which appears between "ADDITIONAL" and "AT 10,000 pts"
0615: 1C 0A ; task data
0617: EF rst #28 ; insert task to write points needed for extra life digits to screen
0618: 1F 00 ; task data
061A: C9 ret ; return
;; jump here from #05E8
;; display 1/2 player and check start buttons
061b cda12b call #2ba1 ; write # of credits on screen
061e 3a6e4e ld a,(#4e6e) ; load A with # of credits
0621 fe01 cp #01 ; is it 1?
0623 0609 ld b,#09 ; load B with message #9: "1 OR 2 PLAYERS"
0625 2002 jr nz,#0629 ; if >= 2 credits, skip next step
0627 0608 ld b,#08 ; load B with message #8: "1 PLAYER ONLY"
0629 cd5e2c call #2c5e ; print message
062c 3a6e4e ld a,(#4e6e) ; load A with # of credits
062f fe01 cp #01 ; 1 credit?
0631 3a4050 ld a,(#5040) ; load A with IN1 (player start buttons)
0634 280c jr z,#0642 ; don't check p2 with 1 credit
0636 cb77 bit 6,a ; check for player 2 start button
0638 2008 jr nz,#0642 ; if not, pressed, skip ahead to check for player 1 start
063a 3e01 ld a,#01 ; else set 2 players
063c 32704e ld (#4e70),a ; store into # of players (0=1 player, 1=2 players)
063f c34906 jp #0649 ; jump ahead
0642 cb6f bit 5,a ; player 1 start being pressed ?
0644 c0 ret nz ; no, return
0645 af xor a ; A := #00
0646 32704e ld (#4e70),a ; store into # of players (0=1 player, 1=2 players)
0649 3a6b4e ld a,(#4e6b) ; load A with number of coins per credit
064c a7 and a ; Is free play activated?
064d 2815 jr z,#0664 ; Yes, skip ahead
064f 3a704e ld a,(#4e70) ; else load A with # of players
0652 a7 and a ; Is this a 1 player game?
0653 3a6e4e ld a,(#4e6e) ; load A with number of credits
0656 2803 jr z,#065b ; If 1 player game, skip ahead and only subtract 1 credit
0658 c699 add a,#99 ; else subtract 2 credits. one here...
065a 27 daa ; decimal adjust
065b c699 add a,#99 ; subtract a credit
065d 27 daa ; decimal adjust
065e 326e4e ld (#4e6e),a ; save result in credits counter
0661 cda12b call #2ba1 ; write # of credits on screen
0664 21034e ld hl,#4e03 ; load HL with main routine 2, subroutine #
0667 34 inc (hl) ; increase
0668 af xor a ; A := #00
0669 32d64d ld (#4dd6),a ; store in LED state ( 1: game waits for 1P/2P start button press)
066c 3c inc a ; A := #01
066d 32cc4e ld (#4ecc),a ; store in wave to play (begins intro music tune)
0670 32dc4e ld (#4edc),a ; store in wave to play (beigns intro music tune)
0673 c9 ret ; return (to #0195)
; arrive from #05E8 when start button has been pressed
0674 ef rst #28 ; set task #00, parameter #01 - clears the maze
0675 00 01
0677 ef rst #28 ; set task #01, parameter #01 - colors the maze
0678 01 01
067a ef rst #28 ; set task #02, parameter #00 - draws the maze
067b 02 00
067d ef rst #28 ; set task #12, parameter #00 - sets up coded pill and power pill memories
067e 12 00
0680 ef rst #28 ; set task #03, parameter #00 - draws the pellets
0681 03 00
0683 ef rst #28 ; set task #1C, parameter #03 - draws text on screen "PLAYER 1"
0684 1c 03
0686 ef rst #28 ; set task #1C, parameter #06 - draws text on screen "READY!" and clears the intermission indicator
0687 1c 06
0689 ef rst #28 ; set task #18, parameter #00 - draws "high score" and scores. clears player 1 and 2 scores to zero.
068a 18 00
068c ef rst #28 ; set task #1B, parameter #00 - draws fruit at bottom right of screen
068d 1b 00
068f af xor a ; A := #00
0690 32134e ld (#4e13),a ; current board level = 0
0693 3a6f4e ld a,(#4e6f) ; load number of lives to start
0696 32144e ld (#4e14),a ; set number of lives
0699 32154e ld (#4e15),a ; set number of lives displayed
069c ef rst #28 ; set task #1A, parameter #00 - draws remaining lives at bottom of screen
069d 1a 00
069f f7 rst #30 ; set timed task to increment main routine 2, subroutine # (#4E03)
06a0 57 01 00 ; task data: timer=#57, task=01, parameter=0.
; also arrive here from #0246. This is timed task #01
06a3 21 03 4E ld hl,#4E03 ; load HL with main routine 2, subroutine #
06a6 34 inc (hl) ; increase
06a7 c9 ret ; return
;; draw lives displayed onto the screen
06a8 21154e ld hl,#4e15 ; load HL with lives displayed on screen loc
06ab 35 dec (hl) ; decrement
06ac cd6a2b call #2b6a ; draw remaining lives at bottom of screen
06af af xor a ; A := #00
06b0 32034e ld (#4e03),a ; clear main routine 2, subroutine #
06b3 32024e ld (#4e02),a ; clear main routine 1, subroutine #
06b6 32044e ld (#4e04),a ; clear level state subroutine #
06b9 21004e ld hl,#4e00 ; load HL with game mode address
06bc 34 inc (hl) ; inc game mode. game mode is now 3 = game is just now starting
06bd c9 ret ; return
; arrive here from #03CB or from #057C, when someone or demo is playing
06BE: 3A 04 4E ld a,(#4E04) ; load A with level state
06C1: E7 rst #20 ; jump based on A
06C2: 79 08 ; #0879 ; set up game initialization
06C4: 99 08 ; #0899 ; set up tasks for beginning of game
06C6: 0C 00 ; #000C ; returns immediately
06C8: CD 08 ; #08CD ; demo mode or player is playing
06CA: 0D 09 ; #090D ; when player has collided with hostile ghost (died)
06CC: 0C 00 ; #000C ; returns immediately
06CE: 40 09 ; #0940 ; check for game over, do things if true
06D0: 0C 00 ; #000C ; returns immediately
06D2: 72 09 ; #0972 ; end of demo mode when ms pac dies in demo. clears a bunch of memories.
06D4: 88 09 ; #0988 ; sets a bunch of tasks and displays "ready" or "game over"
06D6: 0C 00 ; #000C ; returns immediately
06D8: D2 09 ; #09D2 ; begin start of maze demo after marquee
06DA: D8 09 ; #09D8 ; clears sounds and sets a small delay. run at end of each level
06DC: 0C 00 ; #000C ; returns immediately
06DE: E8 09 ; #09E8 ; flash screen
06E0: 0C 00 ; #000C ; returns immediately
06E2: FE 09 ; #09FE ; flash screen
06E4: 0C 00 ; #000C ; returns immediately
06E6: 02 0A ; #0A02 ; flash screen
06E8: 0C 00 ; #000C ; returns immediately
06EA: 04 0A ; #0A04 ; flash screen
06EC: 0C 00 ; #000C ; returns immediately
06EE: 06 0A ; #0A06 ; flash screen
06F0: 0C 00 ; #000C ; returns immediately
06F2: 08 0A ; #0A08 ; flash screen
06F4: 0C 00 ; #000C ; returns immediately
06F6: 0A 0A ; #0A0A ; flash screen
06F8: 0C 00 ; #000C ; returns immediately
06FA: 0C 0A ; #0A0C ; flash screen
06FC: 0C 00 ; #000C ; returns immediately
06FE: 0E 0A ; #0A0E ; set a bunch of tasks
0700: 0C 00 ; #000C ; returns immediately
0702: 2C 0A ; #0A2C ; clears all sounds and runs intermissions when needed
0704: 0C 00 ; #000C ; returns immediately
0706: 7C 0A ; #0A7C ; clears sounds, increases level, increases difficulty if needed, resets pill maps
0708: A0 0A ; #0AA0 ; get game ready to play and set this sub back to #03
070A: 0C 00 ; #000C ; returns immediately
070C: A3 0A ; #0AA3 ; sets sub # back to #03
; arrive here from #000D
; sets up game difficulty
070e 78 ld a,b ; load A with parameter from task
070f a7 and a ; == #00 ?
0710 2004 jr nz,#0716 ; no, skip ahead
0712 2a0a4e ld hl,(#4e0a) ; else load HL with difficulty setting pointer. EG #0068
0715 7e ld a,(hl) ; load A with difficulty, EG #00
0716 dd219607 ld ix,#0796 ; load IX with difficulty table start
071a 47 ld b,a
071b 87 add a,a
071c 87 add a,a
071d 80 add a,b
071e 80 add a,b ; A is now 6 times what it was
071f 5f ld e,a
0720 1600 ld d,#00
0722 dd19 add ix,de ; adjust IX based on current difficulty
0724 dd7e00 ld a,(ix+#00) ; load A with first value from table
0727 87 add a,a
0728 47 ld b,a
0729 87 add a,a
072a 87 add a,a
072b 4f ld c,a
072c 87 add a,a
072d 87 add a,a
072e 81 add a,c
072f 80 add a,b
0730 5f ld e,a
0731 1600 ld d,#00
0733 210f33 ld hl,#330f ; load HL with start of data table - speeds of ghosts and pacman
0736 19 add hl,de ; add offset computed above
0737 cd1408 call #0814 ; copy data into #4d46 through #4d94
073a dd7e01 ld a,(ix+#01) ; load A with second value from table
073d 32b04d ld (#4db0),a ; store. appears to be unused
0740 dd7e02 ld a,(ix+#02) ; load A with third value from table
0743 47 ld b,a ; copy to B
0744 87 add a,a ; A := A*2
0745 80 add a,b ; A is now 3 times value in table
0746 5f ld e,a ; store in E
0747 1600 ld d,#00 ; D := #00
0749 214308 ld hl,#0843 ; load HL with hard/easy data table check
074c 19 add hl,de ; add offset computed above
074d cd3a08 call #083a ; copy difficulty info to #4DB8 to #4DBA
0750 dd7e03 ld a,(ix+#03) ; load A with fourth value from table
0753 87 add a,a ; A := A * 2
0754 5f ld e,a ; copy to E
0755 1600 ld d,#00 ; D := #00
0757 fd214f08 ld iy,#084f ; load IY with data table start
075b fd19 add iy,de ; add offset
075d fd6e00 ld l,(iy+#00) ;
0760 fd6601 ld h,(iy+#01) ; load HL with table data
0763 22bb4d ld (#4dbb),hl ; store into remainder of pills when first diff. flag is set
0766 dd7e04 ld a,(ix+#04) ; load A with fifth value from table
0769 87 add a,a ; A := A * 2
076a 5f ld e,a ; store into E
076b 1600 ld d,#00 ; clear D
076d fd216108 ld iy,#0861 ; load IY with start of table that controls time that ghosts stay blue
0771 fd19 add iy,de ; add offset
0773 fd6e00 ld l,(iy+#00) ;
0776 fd6601 ld h,(iy+#01) ; load HL with data from table
0779 22bd4d ld (#4dbd),hl ; store into time the ghosts stay blue when pacman eats a power pill
077c dd7e05 ld a,(ix+#05) ; load A with sixth value from table
077f 87 add a,a ; A := A * 2
0780 5f ld e,a ; copy to E
0781 1600 ld d,#00 ; clear D
0783 fd217308 ld iy,#0873 ; load IY with start of difficulty table - number of units before ghosts leaves home
0787 fd19 add iy,de ; add offset
0789 fd6e00 ld l,(iy+#00)
078c fd6601 ld h,(iy+#01) ; load HL with data from table
078f 22954d ld (#4d95),hl ; store
0792 cdea2b call #2bea ; draw fruit at bottom of screen
0795 c9 ret ; return (to # 238D ?)
; -- difficulty related table
; each entry is 6 bytes
; byte 0: (0..6) speed bit patterns and orientation changes (table at #330F)
; byte 1: (00, 01, 02) stored at #4DB0 - seems to be unused
; byte 2: (0..3) ghost counter table to exit home (table at #0843)
; byte 3: (0..7) remaining number of pills to set difficulty flags (table at #084F)
; byte 4: (0..8) ghost time to stay blue when pacman eats the big pill (table at #0861)
; byte 5: (0..2) number of units before a ghost goes out of home (table at #0873)
0796 03 01 01 00 02 00
079c 04 01 02 01 03 00
07a2 04 01 03 02 04 01
07a8 04 02 03 02 05 01
07ae 05 00 03 02 06 02
07b4 05 01 03 03 03 02
07ba 05 02 03 03 06 02
07c0 05 02 03 03 06 02
07c6 05 00 03 04 07 02
07cc 05 01 03 04 03 02
07d2 05 02 03 04 06 02
07d8 05 02 03 05 07 02
07de 05 00 03 05 07 02
07e4 05 02 03 05 05 02
07ea 05 01 03 06 07 02
07f0 05 02 03 06 07 02
07f6 05 02 03 06 08 02
07fc 05 02 03 06 07 02
0802 05 02 03 07 08 02
0808 05 02 03 07 08 02
080e 06 02 03 07 08 02
; called from #0737
; copies difficulty-related data into #4d46 through #4d94
; includes 4d58 which is blinky's normal speed
; include 4d86 which controls timing of reversals
0814 11464d ld de,#4d46 ; set destination
0817 011c00 ld bc,#001c ; set counter
081a edb0 ldir ; copy
081c 010c00 ld bc,#000c ; set counter
081f a7 and a ; clear carry flag
0820 ed42 sbc hl,bc ; subtract from source
0822 edb0 ldir ; copy
0824 010c00 ld bc,#000c ; set counter
0827 a7 and a ; clear carry flag
0828 ed42 sbc hl,bc ; subtract from source
082a edb0 ldir ; copy
082c 010c00 ld bc,#000c ; set counter
082f a7 and a ; clear carry flag
0830 ed42 sbc hl,bc ; subtract source
0832 edb0 ldir ; copy
0834 010e00 ld bc,#000e ; set counter
0837 edb0 ldir ; copy
0839 c9 ret ; return
; called from #0749
083a 11b84d ld de,#4db8 ; load destination with #4DB8
083d 010300 ld bc,#0003 ; set bytes to copy at 3
0840 edb0 ldir ; copy
0842 c9 ret ; return
;-- table related to difficulty - each entry is 3 bytes
; b0: when counter at 4E0F reaches this value, pink ghost goes out of home
; b1: when counter at 4E10 reaches this value, blue ghost goes out of home
; b2: when counter at 4E11 reaches this value, orange ghost goes out of home
; these don't seem to be used in ms-pac at all.
0843 14 1e 46 00 1e 3c 00 00 32 00 00 00
; hard hack: HACK6
; 0843 0f 14 37 04 18 34 02 06 28 00 04 08
;
; -- difficulty table --
; each entry is 2 bytes
; b1: remaining number of pills when first difficulty flag is set (cruise elroy 1)
; b2: remaining number of pills when second difficulty flag is set (cruise elroy 2)
084f 14 0a
0851 1e 0f
0853 28 14
0855 32 19
0857 3c 1e
0859 50 28
085B 64 32
085D 78 3c
085F 8c 46
; difficulty table - Time the ghosts stay blue when pacman eats a big pill
; -- do not use with l set up at #076D
0861 c0 03 ; 03c0 (960) 8 seconds (not used)
0863 48 03 ; 0348 (840) 7 seconds (not used)
0865 d0 02 ; 02d0 (720) 6 seconds
0867 58 02 ; 0258 (600) 5 seconds
0869 e0 01 ; 01e0 (480) 4 seconds
086b 68 01 ; 0168 (360) 3 seconds
086d f0 00 ; 00f0 (240) 2 seconds
086f 78 00 ; 0078 (120) 1 second
0871 01 00 ; 0001 (1) 0 seconds
; difficulty table - number of units before ghosts leaves home
; set up at #0783
0873 f0 00 ; 00f0 (240) 2 seconds
0875 f0 00 ; 00f0 (240) 2 seconds
0877 b4 00 ; 00b4 (180) 1.5 seconds
; main routine #3. arrive here at the start of the game when a new game is started
; arrive from #04E5 or #06C1
0879 21094e ld hl,#4e09 ; load HL with player # address
087c af xor a ; A := #00
087d 060b ld b,#0b ; set counter to #0B
087f cf rst #8 ; clear memories from #4E09 through #4E09 + #0B
0880 cdc924 call #24c9 ; set up pills and power pills in RAM
0883 2a734e ld hl,(#4e73) ; load HL with difficulty
0886 220a4e ld (#4e0a),hl ; store difficulty
0889 210a4e ld hl,#4e0a ; load source with difficulty
088c 11384e ld de,#4e38 ; load destination with difficulty
088f 012e00 ld bc,#002e ; set byte counter at #2E
0892 edb0 ldir ; copy
; arrive here from #09CF
; this is also timed task #00, arrive from #0246
0894 21044e ld hl,#4e04 ; load HL with main subroutine number
0897 34 inc (hl) ; increment
0898 c9 ret ; return
; arrive from #06C1
0899 3a004e ld a,(#4e00) ; load A with game mode
089c 3d dec a ; are we in the demo mode ?
089d 2006 jr nz,#08a5 ; no, skip ahead
089f 3e09 ld a,#09 ; yes, load A with #09
08a1 32044e ld (#4e04),a ; store in main subroutine
08a4 c9 ret ; return
08a5 ef rst #28 ; insert task #11 - clears memories from #4D00 through #4DFF
08a6 11 00
08a8 ef rst #28 ; insert task #1C, parameter #83 - displays or clears text
08a9 1c 83
08ab ef rst #28 ; insert task #04 - resets a bunch of memories and
08ac 04 00
08ae ef rst #28 ; insert task #05 - resets ghost home counter
08af 05 00
08b1 ef rst #28 ; insert task #10 - sets up difficulty
08b2 10 00
08b4 ef rst #28 ; insert task #1A - draws remaining lives at bottom of screen
08b5 1a 00
08b7 f7 rst #30 ; set timed task to increase the main subroutine number (#4E04)
08b8 54 00 00 ; task timer=#54, task=0, param=0
08bb f7 rst #30 ; set timed task to clear the "READY!" message
08bc 54 06 00 ; task timer=#54, task=6, param=0
08bf 3a724e ld a,(#4e72) ; load A with cocktail or upright
08c2 47 ld b,a ; copy to B
08c3 3a094e ld a,(#4e09) ; load A with current player #
08c6 a0 and b ; is this game cockatil mode and player # 2 ? If so , this value becomes 1
08c7 320350 ld (#5003),a ; store into flip screen register
08ca c39408 jp #0894 ; loop back to increment level complete register and return
; demo or game is playing
08cd 3a0050 ld a,(#5000) ; load A with IN0
08d0 cb67 bit 4,a ; is rack test on?
08d2 c2de08 jp nz,#08de ; no, skip ahead
08d5 21044e ld hl,#4e04 ; else rack switch on, so advance. load HL with game state
08d8 360e ld (hl),#0e ; store value of #0E. this signals end of level
08da ef rst #28 ; insert task #13 with parameter #00 - clears the sprites
08db 13 00
08dd c9 ret ; return
;; routine to determine the number of pellets which must be eaten
08de 3a0e4e ld a,(#4e0e) ; load A with number of pellets eaten
; OTTOPATCH
;PATCH TO ADJUST THE TOTAL DOT NUMBER
ORG 08E1H
JP MOREDOTS
NOP
08e1 c3a194 jp #94a1 ; jump to ms pac man new check for end of level routine
08e4 00 nop ; junk
; returns here if the level is complete
08e5 21044e ld hl,#4e04 ; load HL with game state
08e8 360c ld (hl),#0c ; store value of #0C, signals end of level
08ea c9 ret ; return
;; pacman original:
; 08de 3a0e4e ld a,(#4e0e) ; load A with number of pellets eaten
; 08e1 fef4 cp #f4 ; == 244 ?
; 08e3 2006 jr nz,#08eb ; No, jump ahead
; 08e5 21044e ld hl,#4e04 ; Yes, then end of level. Load HL with main subroutine #
; 08e8 360c ld (hl),#0c ; store #0C into main sub #to signal end of level
; 08ea c9 ret ; return
;;
; returns here if level is not complete
; core game loop
08eb cd1710 call #1017 ; another core game loop that does many things
08ee cd1710 call #1017 ; another core game loop that does many things
08f1 cddd13 call #13dd ; check for release of ghosts from ghost house
08f4 cd420c call #0c42 ; adjust movement of ghosts if moving out of ghost house
08f7 cd230e call #0e23 ; change animation of ghosts every 8th frame
08fa cd360e call #0e36 ; periodically reverse ghost direction based on difficulty (only when energizer not active)
08fd cdc30a call #0ac3 ; handle ghost flashing and colors when power pills are eaten
0900 cdd60b call #0bd6 ; color dead ghosts the correct colors
0903 cd0d0c call #0c0d ; handle power pill (dot) flashes
0906 cd6c0e call #0e6c ; change the background sound based on # of pills eaten
0909: CD AD 0E call #0EAD ; check for fruit to come out. (new ms. pac sub actually at #86EE.)
090C: C9 ret ; return ( to #0195 )
; arrive here from #06C1 when player has died
090d 3e01 ld a,#01 ; A := #01
090f 32124e ld (#4e12),a ; store into player dead flag
; 4e12 1 after dying in a level, reset to 0 if ghosts have left home
; because of 4d9f
0912 cd8724 call #2487 ; save pellet info to memory
0915 21044e ld hl,#4e04 ; load HL with main subroutine number
0918 34 inc (hl) ; increase it
0919 3a144e ld a,(#4e14) ; load A with number of lives left
091c a7 and a ; == #00 ?
091d 201f jr nz,#093e ; no, skip ahead
091f 3a704e ld a,(#4e70) ; else game over. load A with number of players (0=1 player, 1=2 players)
0922 a7 and a ; is this a one player game?
0923 2819 jr z,#093e ; yes, skip ahead
0925 3a424e ld a,(#4e42) ; else load A with game state
0928 a7 and a ; is this the demo mode ?
0929 2813 jr z,#093e ; yes, skip ahead
092b 3a094e ld a,(#4e09) ; else load A with current player number: 0=P1, 1=P2
092e c603 add a,#03 ; add #03, result is either #03 or #04
0930 4f ld c,a ; store into C for call below
0931 061c ld b,#1c ; load B with #1C for task call below
0933 cd4200 call #0042 ; insert task to draw to screen either "PLAYER ONE" or "PLAYER TWO"
0936 ef rst #28 ; insert task to draw "GAME OVER"
0937 1c 05
0939 f7 rst #30 ; set timed task to increase the main subroutine number (#4E04)
093a 54 00 00 ; task timer=#54, task=0, param=0
093d c9 ret ; return
093e 34 inc (hl) ; increase game state
093f c9 ret ; return
; arrive from #06C1
0940 3a704e ld a,(#4e70) ; load A with number of players
0943 a7 and a ; == #00 ?
0944 2806 jr z,#094c ; yes, skip ahead if 1 player
0946 3a424e ld a,(#4e42) ; else load A with game state
0949 a7 and a ; is a game being played ?
094a 2015 jr nz,#0961 ; yes, skip ahead and switch from player 1 to player 2 or vice versa
094c 3a144e ld a,(#4e14) ; else load A with number of lives left
094f a7 and a ; are there any lives left ?
0950 201a jr nz,#096c ; yes, jump ahead
; change 0950 to
; 0950 18 1a jr #096C ; always jump ahead
; for never-ending pac goodness
0952 cda12b call #2ba1 ; else draw # credits or free play on bottom of screen
0955 ef rst #28 ; insert task #1C , parameter #05 . Draws text on screen "GAME OVER"
0956 1c 05 ; task data
0958 f7 rst #30 ; set timed task to increase main subroutine number (#4E04)
0959 54 00 00 ; task timer=#54, task=0, param=0
095c 21044e ld hl,#4e04 ; Load HL with level state subroutine #
095f 34 inc (hl) ; increment
0960 c9 ret ; return
; arrive here from #094a when there 2 players, when a player dies
0961 cda60a call #0aa6 ; transposes data from #4e0a through #4e37 into #4e38 through #4e66
0964 3a094e ld a,(#4e09) ; load A with current player number: 0=P1, 1=P2
0967 ee01 xor #01 ; flip bit 0
0969 32094e ld (#4e09),a ; store result. toggles between player 1 and 2
096c 3e09 ld a,#09 ; A := #09
096e 32044e ld (#4e04),a ; store into level state subroutine #
0971 c9 ret ; return
; arrive from #06C1 when subroutine# (#4E04)= #08
; zeros some important variables
; arrive here after demo mode finishes (ms pac man dies in demo)
0972 af xor a ; A := #00
0973 32024e ld (#4e02),a ; clear main routine 1, subroutine #
0976 32044e ld (#4e04),a ; clear level state subroutine #
0979 32704e ld (#4e70),a ; clear number of players
097c 32094e ld (#4e09),a ; clear current player number
097f 320350 ld (#5003),a ; clear flip screen register
0982 3e01 ld a,#01 ; A := #01
0984 32004e ld (#4e00),a ; set game mode to demo
0987 c9 ret ; return (to #057F)
; arrive from #06C1 when (#4E04==#09) when marquee mode ends or after player has been killed
; or from #06C1 when (#4E04 == #20) when a level has ended and a new one is about to begin
0988 ef rst #28 ; set task #00, parameter = #01. - clears the maze
0989 00 01
098b ef rst #28 ; set task #01, parameter = #01. - colors the maze
098c 01 01
098e ef rst #28 ; set task #02, parameter = #00. - draws the maze
098f 02 00
0991 ef rst #28 ; set task #11, parameter = #00. - clears memories from #4D00 through #4DFF
0992 11 00
0994 ef rst #28 ; set task #13, parameter = #00. - clears the sprites
0995 13 00
0997 ef rst #28 ; set task #03, parameter = #00. - draws the pellets
0998 03 00
099a ef rst #28 ; set task #04, parameter = #00. - resets a bunch of memories
099b 04 00
099d ef rst #28 ; set task #05, parameter = #00. - resets ghost home counter
099e 05 00
09a0 ef rst #28 ; set task #10, parameter = #00. - sets up difficulty
09a1 10 00
09a3 ef rst #28 ; set task #1A, parameter = #00. - draws remaining lives at bottom of screen
09a4 1a 00
09a6 ef rst #28 ; set task #1C, parameter = #06. Draws text on screen "READY!" and clears the intermission indicator
09a7 1c 06
09a8 3a004e ld a,(#4e00) ; load A with game state
09ac fe03 cp #03 ; is someone playing ?
09ae 2806 jr z,#09b6 ; Yes, skip ahead
09b0 ef rst #28 ; set task #1C, parameter = #05. Draws text on screeen "GAME OVER"
09b1 1c 05
09b3 ef rst #28 ; set task #1D - write # of credits on screen
09b4 1d 00
09b6 f7 rst #30 ; set timed task to increase main subroutine number (#4E04)
09b7 54 00 00 ; taks timer = #54, task = 00, parameter = 00
09ba 3a004e ld a,(#4e00) ; load A with game sate
09bd 3d dec a ; is this the demo mode ?
09be 2804 jr z,#09c4 ; yes, skip next step
09c0 f7 rst #30 ; set timed task to clear the "READY!" text from the screen
09c1 54 06 00 ; timer = #54, task = 6, parameter = 00
09c4 3a724e ld a,(#4e72) ; load A with cocktail mode (0=no, 1=yes)
09c7 47 ld b,a ; copy to B
09c8 3a094e ld a,(#4e09) ; load A with current player #
09cb a0 and b ; mix together
09cc 320350 ld (#5003),a ; flip screens if player 2 in cocktail mode, else screen is set upright
09cf c39408 jp #0894 ; increase main routine # and return from sub
; called after marquee mode is done during demo
; called from #06C1 when (#4E04 == #0B)
09d2 3e03 ld a,#03 ; A := #03
09d4 32044e ld (#4e04),a ; store into main routine #. signals the maze part of game is on
09d7 c9 ret ; return
; called from #06C1 when (#4E04 == #0C)
; arrive here at end of level
09d8 f7 rst #30 ; set timed task to increase main subroutine number (#4E04)
09d9 54 00 00 ; timer = #54, task = #00, parameter = #00
09DC: 21 04 4E ld hl,#4E04 ; load HL with game subroutine #
09DF: 34 inc (hl) ; increase
09E0: AF xor a ; A := #00
09E1: 32 AC 4E ld (#4EAC),a ; clear sound channel 2
09E4: 32 BC 4E ld (#4EBC),a ; clear sound channel 3
09E7: C9 ret ; return
; Called from #06C1 when (#4E04 == #0E)
09e8 0e02 ld c,#02 ; C := #02
09ea 0601 ld b,#01 ; B := #01
09ec cd4200 call #0042 ; set task #01 with parameter #02, or task #01 with parameter #00
09ef f7 rst #30 ; set timed task to increase main subroutine number (#4E04)
09f0 42 00 00 ; timer = #42, task = #00, parameter = #00
09f3 210000 ld hl,#0000 ; clear HL
09f6 cd7e26 call #267e ; clears all ghosts from screen
09f9 21044e ld hl,#4e04 ; load HL with game subroutine #
09fc 34 inc (hl) ; increase
09fd c9 ret ; return
; the following calls are made at end of level to flash the screen
09fe 0e00 ld c,#00 ; set code to flash screen
0a00 18e8 jr #09ea ; flash screen
0a02 18e4 jr #09e8 ; flash screen
0a04 18f8 jr #09fe ; flash screen
0a06 18e0 jr #09e8 ; flash screen
0a08 18f4 jr #09fe ; flash screen
0a0a 18dc jr #09e8 ; flash screen
0a0c 18f0 jr #09fe ; flash screen
; arrive here at end of level after screen has flashed several times
; called from #06C1 when (#4E04 == #14)
0a0e ef rst #28 ; insert task #00, parameter #01 - clears the maze
0a0f 00 01
0a11 ef rst #28 ; insert task #06, parameter #00 - clears the color RAM
0a12 06 00
0a14 ef rst #28 ; insert task #11, parameter #00 - clears memories from #4D00 through #4DFF
0a15 11 00
0a17 ef rst #28 ; insert task #13, parameter #00 - clears the sprites
0a18 13 00
0a1a ef rst #28 ; insert task #04, parameter #01 - resets a bunch of memories
0a1b 04 01
0a1d ef rst #28 ; insert task #05, parameter #01 - resets ghost home counter
0a1e 05 01
0a20 ef rst #28 ; insert task #10, parameter #13 - sets up difficulty
0a21 10 13
0a23 f7 rst #30 ; set timed task to increase main subroutine number (#4E04)
0a24 43 00 00 ; task timer = #43, task #00, parameter #00
0a27 21044e ld hl,#4e04 ; load HL with main subroutine number
0a2a 34 inc (hl) ; increase subroutine number
0a2b c9 ret ; return
; arrive here at end of level
; called from #06C1 when (#4E04 == #16)
; clear sounds and run intermissions when needed
0A2C: AF xor a ; A := #00
0A2D: 32 AC 4E ld (#4EAC),a ; clear sound channel #2
0A30: 32 BC 4E ld (#4EBC),a ; clear sound channel #3
0A33: 18 06 jr #0A3B ; skip next 2 steps
; junk from pac-man
0A35: 32CC4E ld (#4ECC),a
0A38: 32DC4E ld (#4EDC),a
0a3b 3a134e ld a,(#4e13) ; load A with current board level
0a3e fe14 cp #14 ; > #14 ?
0a40 3802 jr c,#0a44 ; no, skip next step
0a42 3e14 ld a,#14 ; else load A with #14
0a44 e7 rst #20 ; jump based on A
; jump table to control when cutscenes occur
0a45 6f 0a ; #0A6F ; increment level state and stop sound
0a47 08 21 ; #2108 ; cut scene 1
0a49 6f 0a ; #0A6F ; increment level state and stop sound
0a4b 6f 0a ; #0A6F ; increment level state and stop sound
0a4d 9e 21 ; #219E ; cut scene 2
0a4f 6f 0a ; #0A6F ; increment level state and stop sound
0a51 6f 0a ; #0A6F ; increment level state and stop sound
0a53 6f 0a ; #0A6F ; increment level state and stop sound
0a55 97 22 ; #2297 ; cut scene 3
0a57 6f 0a ; #0A6F ; increment level state and stop sound
0a59 6f 0a ; #0A6F ; increment level state and stop sound
0a5b 6f 0a ; #0A6F ; increment level state and stop sound
0a5d 97 22 ; #2297 ; cut scene 3
0a5f 6f 0a ; #0A6F ; increment level state and stop sound
0a61 6f 0a ; #0A6F ; increment level state and stop sound
0a63 6f 0a ; #0A6F ; increment level state and stop sound
0a65 97 22 ; #2297 ; cut scene 3
0a67 6f 0a ; #0A6F ; increment level state and stop sound
0a69 6f 0a ; #0A6F ; increment level state and stop sound
0a6b 6f 0a ; #0A6F ; increment level state and stop sound
0a6d 6f 0a ; #0A6F ; increment level state and stop sound
; increment level state and stop sound
0a6f 21044e ld hl,#4e04 ; load HL with level state subroutine #
0a72 34 inc (hl)
0a73 34 inc (hl) ; increase twice
0a74 af xor a ; A := #00
0a75 32cc4e ld (#4ecc),a ; clear sound
0a78 32dc4e ld (#4edc),a ; clear sound
0a7b c9 ret ; return
;; we're about to start the next board, (it's about to be drawn)
; called from #06C1 when (#4E04 == #18)
0a7c af xor a ; A := #00
0a7d 32cc4e ld (#4ecc),a ; clear sound
0a80 32dc4e ld (#4edc),a ; clear sound
0a83 0607 ld b,#07 ; B := #07
0a85 210c4e ld hl,#4e0c ; load HL with start address to clear
0a88 cf rst #8 ; clear #4e0c through #4e0c+7. these flags are reset at beginning of each level
0a89 cdc924 call #24c9 ; set addresses #4E16 through #4E39 with #FF and #14 (pill map???)
0a8c 21044e ld hl,#4e04 ; load HL with subroutine #
0a8f 34 inc (hl) ; increase
; level 255 pac fix ; BUGFIX01 (1 of 2)
; 0a90 c3800f jp #0f88
; 0a93 00 nop
;
; level 141 mspac fix ; BUGFIX02 (1 of 2)
; 0a90 c3960f jp #0f96
; 0a93 00 nop
;
0a90 21134e ld hl,#4e13 ; load HL with current board level
0a93 34 inc (hl) ; increment board level
0a94 2a0a4e ld hl,(#4e0a) ; load HL with pointer to current difficulty settings (#0068 for easy, #007D for hard)
0a97 7e ld a,(hl) ; load A with the result
0a98 fe14 cp #14 ; == #14 (is this already the highest difficulty?)
0a9a c8 ret z ; yes, return
0a9b 23 inc hl ; else increase difficulty
0a9c 220a4e ld (#4e0a),hl ; store result
0a9f c9 ret ; return
; called from #06C1 when (#4E04 == #20)
0aa0 c38809 jp #0988 ;
; ; called from #06C1 when (#4E04 == #22)
0aa3 c3d209 jp #09d2 ;
; called from #0961
; transposes data from #4e0a through #4e37 into #4e38 through #4e66
; used to copy data in and out for 2 player games
0aa6 062e ld b,#2e ; For B = 1 to #2E
0aa8 dd210a4e ld ix,#4e0a ; load IX with group 1 start address
0aac fd21384e ld iy,#4e38 ; load IY with group 2 start address
0ab0 dd5600 ld d,(ix+#00) ; load D with data from group 1
0ab3 fd5e00 ld e,(iy+#00) ; load E with data from group 2
0ab6 fd7200 ld (iy+#00),d ; store D into group 2
0ab9 dd7300 ld (ix+#00),e ; store E into group 1
0abc dd23 inc ix ; next address
0abe fd23 inc iy ; next address
0ac0 10ee djnz #0ab0 ; next B
0ac2 c9 ret ; return
; called from #08FD
0ac3 3aa44d ld a,(#4da4) ; load A with # of ghost killed but no collision for yet [0..4]
0ac6 a7 and a ; is there a collision ?
0ac7 c0 ret nz ; yes, return
; this subroutine never gets called when the green-eyed ghost bug occurs
0ac8 dd21004c ld ix,#4c00 ; else load IX with start of sprites address
0acc fd21c84d ld iy,#4dc8 ; load IY with (counter used to change ghost colors under big pill effects?)
0ad0 110001 ld de,#0100 ; load DE with offset value of #0100. [used at #0AE7]
0ad3 fdbe00 cp (iy+#00) ; compare. is it time to flash?
0ad6 c2d20b jp nz,#0bd2 ; no, decrement (IY) and return
0ad9 fd36000e ld (iy+#00),#0e ; else reset counter to #0E
0add 3aa64d ld a,(#4da6) ; load A with power pill effect (1=active, 0=no effect)
0ae0 a7 and a ; is a power pill still active ?
0ae1 281b jr z,#0afe ; no, skip ahead
0ae3 2acb4d ld hl,(#4dcb) ; yes, load HL with counter while ghosts are blue
0ae6 a7 and a ; clear carry flag
0ae7 ed52 sbc hl,de ; subtract offset of #0100. has this counter gone under?
0ae9 3013 jr nc,#0afe ; no, skip ahead
; arrive here when ghosts start flashing after being blue
; this sub controls the flashing and the return
0AEB: 21 AC 4E ld hl,#4EAC ; yes, load HL with sound 2 channel
0AEE: CB FE set 7,(hl) ; play sound = high frequency
0AF0: 3E 09 ld a,#09 ; A := #09
0AF2: DD BE 0B cp (ix+#0b) ; compare with #4C0b = pacman color entry. is a ghost being eaten?
0AF5: 20 04 jr nz,#0AFB ; no, skip ahead
0AF7: CB BE res 7,(hl) ; clear sound
0AF9: 3E 09 ld a,#09 ; A := #09
0afb 320b4c ld (#4c0b),a ; set pacman color to yellow
0afe 3aa74d ld a,(#4da7) ; load A with red ghost blue flag (0=not blue)
0b01 a7 and a ; is red ghost blue (edible) ?
0b02 281d jr z,#0b21 ; no, skip ahead and set red ghost to red
0b04 2acb4d ld hl,(#4dcb) ; else load HL with counter while ghosts are blue
0b07 a7 and a ; clear carry flag
0b08 ed52 sbc hl,de ; subtract offset (#0100). has this counter gone under?
0b0a 3027 jr nc,#0b33 ; no, jump ahead and check next ghost
0b0c 3e11 ld a,#11 ; yes, A := #11
0b0e ddbe03 cp (ix+#03) ; compare with red ghost color. is red ghost blue ?
0b11 2807 jr z,#0b1a ; yes, skip ahead and change his color to white
0b13 dd360311 ld (ix+#03),#11 ; no, set red ghost to blue color
0b17 c3330b jp #0b33 ; skip ahead and check next ghost
0b1a dd360312 ld (ix+#03),#12 ; set red ghost color to white
0b1e c3330b jp #0b33 ; skip ahead and check next ghost
0b21 3e01 ld a,#01 ; A := #01
0b23 ddbe03 cp (ix+#03) ; compare with red ghost color. is the red ghost red?
0b26 2807 jr z,#0b2f ; yes, then jump ahead
0b28 dd360301 ld (ix+#03),#01 ; set red ghost back to red
0b2c c3330b jp #0b33 ; skip ahead
0b2f dd360301 ld (ix+#03),#01 ; set red ghost back to red
0b33 3aa84d ld a,(#4da8) ; load A with pink ghost blue flag
0b36 a7 and a ; is pink ghost blue (edible) ?
0b37 281d jr z,#0b56 ; no, skip ahead and set pink ghost to pink
0b39 2acb4d ld hl,(#4dcb) ; else load HL with counter while ghosts are blue
0b3c a7 and a ; clear carry flag
0b3d ed52 sbc hl,de ; subtract offset (#0100). has this counter gone under?
0b3f 3027 jr nc,#0b68 ; no, jump ahead and check next ghost
0b41 3e11 ld a,#11 ; A := #11
0b43 ddbe05 cp (ix+#05) ; compare with pink ghost color. is the pink ghost blue?
0b46 2807 jr z,#0b4f ; yes, jump ahead and change his color to white
0b48 dd360511 ld (ix+#05),#11 ; no, set pink ghost back to blue
0b4c c3680b jp #0b68 ; skip ahead
0b4f dd360512 ld (ix+#05),#12 ; set pink ghost color to white
0b53 c3680b jp #0b68 ; skip ahead
0b56 3e03 ld a,#03 ; A := #03
0b58 ddbe05 cp (ix+#05) ; is the pink ghost pink ?
0b5b 2807 jr z,#0b64 ; yes, skip ahead
0b5d dd360503 ld (ix+#05),#03 ; set pink ghost to pink
0b61 c3680b jp #0b68 ; jump ahead
0b64 dd360503 ld (ix+#05),#03 ; set pink ghost to pink
0b68 3aa94d ld a,(#4da9) ; load A with blue ghost (inky) blue flag
0b6b a7 and a ; is inky blue (edible) ?
0b6c 281d jr z,#0b8b ; no, skip ahead
0b6e 2acb4d ld hl,(#4dcb) ; else load HL with counter while ghosts are blue
0b71 a7 and a ; clear carry flag
0b72 ed52 sbc hl,de ; subtract offset (#0100). has this counter gone under?
0b74 3027 jr nc,#0b9d ; no, jump ahead and check next ghost
0b76 3e11 ld a,#11 ; A := #11
0b78 ddbe07 cp (ix+#07) ; is inky blue (edible) ?
0b7b 2807 jr z,#0b84 ; yes, jump ahead and change his color to white
0b7d dd360711 ld (ix+#07),#11 ; no, set inky to blue color
0b81 c39d0b jp #0b9d ; skip ahead
0b84 dd360712 ld (ix+#07),#12 ; set inky to white color
0b88 c39d0b jp #0b9d ; skip ahead
0b8b 3e05 ld a,#05 ; A := #05
0b8d ddbe07 cp (ix+#07) ; is inky his regular color ?
0b90 2807 jr z,#0b99 ; yes, skip ahead
0b92 dd360705 ld (ix+#07),#05 ; set inky to his regular color
0b96 c39d0b jp #0b9d ; skip ahead
0b99 dd360705 ld (ix+#07),#05 ; set inky to his regular color
0b9d 3aaa4d ld a,(#4daa) ; load A with orange ghost blue flag
0ba0 a7 and a ; is orange ghost blue (edible) ?
0ba1 281d jr z,#0bc0 ; no, skip ahead
0ba3 2acb4d ld hl,(#4dcb) ; else load HL with counter while ghosts are blue
0ba6 a7 and a ; clear carry flag
0ba7 ed52 sbc hl,de ; subtract offset (#0100). has this counter gone under?
0ba9 3027 jr nc,#0bd2 ; no, jump ahead
0bab 3e11 ld a,#11 ; A := #11
0bad ddbe09 cp (ix+#09) ; is orange ghost blue (edible) ?
0bb0 2807 jr z,#0bb9 ; yes, skip ahead and change to white
0bb2 dd360911 ld (ix+#09),#11 ; no, set orange ghost color to blue
0bb6 c3d20b jp #0bd2 ; skip ahead
0bb9 dd360912 ld (ix+#09),#12 ; set orange ghost color to white
0bbd c3d20b jp #0bd2 ; skip ahead
0bc0 3e07 ld a,#07 ; A := #07
0bc2 ddbe09 cp (ix+#09) ; is orange ghost orange ?
0bc5 2807 jr z,#0bce ; yes, skip ahead
0bc7 dd360907 ld (ix+#09),#07 ; set orange ghost to orange
0bcb c3d20b jp #0bd2 ; skip ahead
0bce dd360907 ld (ix+#09),#07 ; set orange ghost to orange
0bd2 fd3500 dec (iy+#00) ; decrease the flash counter
0bd5 c9 ret ; return
; called from #0900
; set the color for a dead ghost
0bd6 0619 ld b,#19 ; B := #19 - floating death eyes (good band name!)
0bd8 3a024e ld a,(#4e02) ; load A with main routine 1, subroutine #
0bdb fe22 cp #22 ; == #22 ? is code is used in pac-man only, not ms. pac. its checking for the routine where pacman heads towards the energizer followed by 4 ghosts
0bdd c2e20b jp nz,#0be2 ; no, skip next step
0be0 0600 ld b,#00 ; B := #00. code used to clear ghosts after they get eaten in the pac-man attract
0be2 dd21004c ld ix,#4c00 ; load IX with start of offset for ghost sprites and colors
0be6 3aac4d ld a,(#4dac) ; load A with red ghost state
0be9 a7 and a ; is red ghost alive ?
0bea caf00b jp z,#0bf0 ; yes, skip next step. only set color if not alive
0bed dd7003 ld (ix+#03),b ; store B into red ghost color entry
0bf0 3aad4d ld a,(#4dad) ; load A wtih pink ghost state
0bf3 a7 and a ; is pink ghost alive ?
0bf4 cafa0b jp z,#0bfa ; yes, skip next step
0bf7 dd7005 ld (ix+#05),b ; store B into pink ghost color entry
0bfa 3aae4d ld a,(#4dae) ; load A with blue ghost (inky) state
0bfd a7 and a ; is inky alive ?
0bfe ca040c jp z,#0c04 ; yes, skip next step
0c01 dd7007 ld (ix+#07),b ; store B into blue ghost (inky) color entry
0c04 3aaf4d ld a,(#4daf) ; load A with orange ghost state
0c07 a7 and a ; is orange ghost alive ?
0c08 c8 ret z ; yes, return
0c09 dd7009 ld (ix+#09),b ; store B into orange ghost color entry
0c0c c9 ret ; return
; called from #0903
; routine to handle power pill flashes
0c0d 21cf4d ld hl,#4dcf ; load HL with power pill counter
0c10 34 inc (hl) ; increment
0c11 3e0a ld a,#0a ; A := #0A
0c13 be cp (hl) ; is it time to flash the power pellets ?
0c14 c0 ret nz ; no, return
0c15 3600 ld (hl),#00 ; else we will flash the pellets. reset counter to #00
0c17 3a044e ld a,(#4e04) ; load A with game state indicator. this is #03 when game or demo is in play
0c1a fe03 cp #03 ; == #03 ? Is a game being played ?
0c1c 2015 jr nz,#0c33 ; no, skip ahead and flash the pellets in the demo screen where pac is chased by 4 ghosts and then eats a power pill and eats them all
; BUGFIX05 - Map discoloration fix - Don Hodges
0c1c 2000 jr nz,#0c1e ; no, do nothing
0c1e 216444 ld hl,#4464 ; else load HL with first power pellet address (legacy from pac-man. new routine loads new value)
; OTTOPATCH
;PATCH TO MAKE THE ENERGIZERS FLASH IN NEW AND EXCITING COLORS
ORG 0C21H
JP FLASHEN
0c21 c32495 jp #9524 ; jump to new ms pac routine to flash power pellets
;; Pac-man code:
; 0c21 3e10 ld a,#10 ; load A with code for power pellet
; 0c23 be cp (hl) ; is there already a power pellet there?
;; end pac-man code
; junk from pac-man, flashes power pellets for non-changing maze
0c24 2002 jr nz,#0c28 ; no, skip ahead
0c26 3e00 ld a,#00 ; yes, change code to empty graphic
0c28 77 ld (hl),a ; flash power pellet
0c29 327844 ld (#4478),a ; flash power pellet
0c2c 328447 ld (#4784),a ; flash power pellet
0c2f 329847 ld (#4798),a ; flash power pellet
0c32 c9 ret ; return
; arrive from #0C1C
; flash the pellets in the demo screen where pac is chased by 4 ghosts and then eats a power pill and eats them all
; this causes a very minor bug in pac-man and ms. pac man.
; potentially 2 screen elements can sometimes get colored wrong when player dies.
; in pac-man, a dot may disappear at #4678
0c33 213247 ld hl,#4732 ; load HL with screen color address (?)
0c36 3e10 ld a,#10 ; A := #10
0c38 be cp (hl) ; is the screen color in this address == #10 ?
0c39 2002 jr nz,#0c3d ; no, skip next step
0c3b 3e00 ld a,#00 ; A := #00
0c3d 77 ld (hl),a ; store #10 or #00 into this color location to flash the power pill in the demo
0c3e 327846 ld (#4678),a ; store into #4678 to flash the other power pill
0c41 c9 ret ; return (to #0906)
; called from #08f4
; handles ghost movements when they are moving around in or coming out of the ghost home
; red ghost
0c42 3aa44d ld a,(#4da4) ; load A with # of ghost killed but no collision for yet [0..4]
0c45 a7 and a ; == #00 ?
0c46 c0 ret nz ; return if no collision
0c47 3a944d ld a,(#4d94) ; else load A with counter related to ghost movement inside home
0c4a 07 rlca ; rotate left
0c4b 32944d ld (#4d94),a ; store result
0c4e d0 ret nc ; return if no carry
0c4f 3aa04d ld a,(#4da0) ; else load A with red ghost substate
0c52 a7 and a ; is red ghost out of the ghost house ?
0c53 c2900c jp nz,#0c90 ; yes, skip ahead and check next ghost
0c56 dd210533 ld ix,#3305 ; no, load IX with address for offsets to move up
0c5a fd21004d ld iy,#4d00 ; load IY with red ghost position
0c5e cd0020 call #2000 ; load HL with IY + IX = new position by moving up
0c61 22004d ld (#4d00),hl ; store into red ghost position
0c64 3e03 ld a,#03 ; A := #03
0c66 32284d ld (#4d28),a ; set previous red ghost orientation as moving up
0c69 322c4d ld (#4d2c),a ; set red ghost orientation as moving up
0c6c 3a004d ld a,(#4d00) ; load A with red ghost Y position
0c6f fe64 cp #64 ; is the red ghost out of the ghost house ?
0c71 c2900c jp nz,#0c90 ; no, skip ahead and check next ghost
0c74 212c2e ld hl,#2e2c ; yes, HL := #2E, 2C
0c77 220a4d ld (#4d0a),hl ; store into red ghost position
0c7a 210001 ld hl,#0100 ; HL := #01 00 (code for moving to left)
0c7d 22144d ld (#4d14),hl ; store into red ghost tile changes
0c80 221e4d ld (#4d1e),hl ; store into red ghost tile changes
0c83 3e02 ld a,#02 ; A := #02
0c85 32284d ld (#4d28),a ; set previous red ghost orientation as moving left
0c88 322c4d ld (#4d2c),a ; set red ghost orientation as moving left
0c8b 3e01 ld a,#01 ; A := #01
0c8d 32a04d ld (#4da0),a ; set red ghost indicator to outside the ghost house
; pink ghost
0c90 3aa14d ld a,(#4da1) ; load A with pink ghost substate
0c93 fe01 cp #01 ; is pink ghost out of the ghost house ?
0c95 cafb0c jp z,#0cfb ; yes, skip ahead and check next ghost
0c98 fe00 cp #00 ; is pink ghost waiting to leave the ghost house?
0c9a c2c10c jp nz,#0cc1 ; no, skip ahead
; pink ghost is moving up and down in the ghost house
0c9d 3a024d ld a,(#4d02) ; yes, load A with pink ghost Y position
0ca0 fe78 cp #78 ; is pink ghost at the upper limit of the ghost house?
0ca2 cc2e1f call z,#1f2e ; yes, reverse direction of pink ghost
0ca5 fe80 cp #80 ; is pink ghost at bottom of the ghost house?
0ca7 cc2e1f call z,#1f2e ; yes, reverse direction of pink ghost
0caa 3a2d4d ld a,(#4d2d) ; load A with pink ghost orientation
0cad 32294d ld (#4d29),a ; store into previous pink ghost orienation
0cb0 dd21204d ld ix,#4d20 ; load IX with pink ghost tile changes
0cb4 fd21024d ld iy,#4d02 ; load IY with pink ghost position
0cb8 cd0020 call #2000 ; load HL with IX + IY = new pink ghost position
0cbb 22024d ld (#4d02),hl ; store into pink ghost position
0cbe c3fb0c jp #0cfb ; skip ahead and check next ghost
; pink ghost is moving up out of the ghost house
0cc1 dd210533 ld ix,#3305 ; load IX with address for offsets to move up
0cc5 fd21024d ld iy,#4d02 ; load IY with pink ghost position
0cc9 cd0020 call #2000 ; load HL with IY + IX = new pink ghost position
0ccc 22024d ld (#4d02),hl ; store result into pink ghost position
0ccf 3e03 ld a,#03 ; A := #03
0cd1 322d4d ld (#4d2d),a ; set previous pink ghost orientation as moving up
0cd4 32294d ld (#4d29),a ; set pink ghost orientation as moving up
0cd7 3a024d ld a,(#4d02) ; load A with pink ghost Y position
0cda fe64 cp #64 ; is pink ghost out of the ghost house ?
0cdc c2fb0c jp nz,#0cfb ; no, skip ahead and check next ghost
; pink ghost has made it out of the ghost house
0cdf 212c2e ld hl,#2e2c ; HL := 2E, 2C
0ce2 220c4d ld (#4d0c),hl ; store into pink ghost position
0ce5 210001 ld hl,#0100 ; HL := #01 00 (code for moving left)
0ce8 22164d ld (#4d16),hl ; store into pink ghost tile changes
0ceb 22204d ld (#4d20),hl ; store into pink ghost tile changes
0cee 3e02 ld a,#02 ; A := #02
0cf0 32294d ld (#4d29),a ; set previous pink ghost orientation as moving left
0cf3 322d4d ld (#4d2d),a ; set pink ghost orientation as moving left
0cf6 3e01 ld a,#01 ; A := #01
0cf8 32a14d ld (#4da1),a ; set pink ghost indicator to outside the ghost house
; blue ghost (inky)
0cfb 3aa24d ld a,(#4da2) ; load A with blue ghost (inky) substate
0cfe fe01 cp #01 ; is inky out of the ghost house ?
0d00 ca930d jp z,#0d93 ; yes, skip ahead and check next ghost
0d03 fe00 cp #00 ; is inky waiting to leave the ghost house ?
0d05 c22c0d jp nz,#0d2c ; no, skip ahead
; inky is moving up and down in the ghost house
0d08 3a044d ld a,(#4d04) ; load A with inky Y position
0d0b fe78 cp #78 ; is inky at the upper limit of ghost house ?
0d0d cc551f call z,#1f55 ; yes, reverse direction of inky
0d10 fe80 cp #80 ; is inky at the bottom of the ghost house ?
0d12 cc551f call z,#1f55 ; yes, reverse direction of inky
0d15 3a2e4d ld a,(#4d2e) ; load A with inky orientation
0d18 322a4d ld (#4d2a),a ; store into previous inky orientation
0d1b dd21224d ld ix,#4d22 ; load IX with inky tile changes
0d1f fd21044d ld iy,#4d04 ; load IY with inky position
0d23 cd0020 call #2000 ; load HL with IX + IY = new inky position
0d26 22044d ld (#4d04),hl ; store into inky position
0d29 c3930d jp #0d93 ; skip ahead and check next ghost
0d2c 3aa24d ld a,(#4da2) ; load A with inky substate
0d2f fe03 cp #03 ; is inky moving to his right, on his way out of the ghost house?
0d31 c2590d jp nz,#0d59 ; no, skip ahead
; inky is on his way out of ghost house to right
0d34 dd21ff32 ld ix,#32ff ; yes, load IX with tile movement for moving right
0d38 fd21044d ld iy,#4d04 ; load IY with inky position
0d3c cd0020 call #2000 ; load HL with IX + IY = new inky position
0d3f 22044d ld (#4d04),hl ; store new position for inky
0d42 af xor a ; A := #00
0d43 322a4d ld (#4d2a),a ; set previous inky orientation as moving right
0d46 322e4d ld (#4d2e),a ; set inky orientation as moving right
0d49 3a054d ld a,(#4d05) ; load A with inky X position
0d4c fe80 cp #80 ; is inky exactly under the ghost house door ?