I am writing on behalf of the Game Preservation Society, dedicated to the important work of preserving our nation’s classic video games. We are holding a fundraiser to purchase a Fujitsu fi-7600 archival scanner, which will be invaluable in our mission.
This specialized high-end scanner will allow us to create digital copies of aging media such as game magazines, manuals and other documents. The fi-7600 is unmatched in its ability to digitize damaged, faded, or degraded materials while still maintaining precision and detail. For the fragile documents of past decades, this technology is essential.
The classics we strive to preserve defined generations of culture and advancement for Japan. They represent our history as a pioneer in interactive entertainment and technology. It is our solemn duty to maintain accessibility to these landmark works before they are lost forever.
We cannot accomplish this imperative work without support. I humbly request that you consider donating to our fundraiser for this urgently needed scanning equipment. Together, we can ensure that the cherished games which have shaped our society are preserved for future generations. Please join us in protecting our nation’s interactive legacy.
*This article was translated from Japanese using machine translation. If you would like to edit or correct it, or help in general with translations please contact us!
This is the Game Preservation Society public relations.
Thank you for always supporting our association.
We have published the latest issue of our Japanese newsletter, GPS News vol.21, so we would like to inform you.
In July 2023, we were able to successfully finish the 2022 fiscal year activities. This newsletter contains the 2022 fiscal year activity report, financial report, and the 2023 fiscal year activity plan.
In fiscal year 2022, in addition to continuing the Archive Project funded by the Agency for Cultural Affairs, our preservation research completed the 8-inch drive adapter for Pauline preservation device, and our awareness activities included the release of the documentary “Geimu” Part 2.
In addition, this issue features how the materials donated to our association are being stored.
Download the PDF of the latest newsletter here
Also, we discovered some incorrect figures in the prior fiscal year’s financial report in GPS News vol.18, so we have replaced it with a corrected version in both Japanese and English.
The newsletter is open for non-members to view as well, so if you know anyone interested or involved in game preservation, please share information about our activities.
We will continue our activities relying on your support, so thank you as always.
□Notice of change to newsletter delivery method for supporter members
When registering from Japan, you chose PDF or postal mail/PDF for delivery. If you wish to change the delivery method after registering, please update via “Change personal info” in your member page.
Today we have a special technical article from one of our supporting members going into great detail about Death Force, a classic game for the Fujitsu FM77AV with a hidden mystery, including a partial disassembly, memory analysis and gameplay strategies.
Death Force was released for Fujitsu FM77AV series 8-bit computer in 1987. The FM77AV had advanced graphics hardware, able to display up to 4,096 colors (along with other modes: 8 colors times 4 planes and 8 colors 2 planes + 64 colors). Death Force was one of the first software titles that made use of the color capabilities of FM77AV.
When I visited Game Preservation Society, one of the members raised a question: is it possible to play Death Force through all the way to the ending? The rumor was that the copy protection backfired, making it impossible to finish. According to another rumor, one user complained to the developer, Riverhill Soft, that the game was impossible to complete and was sent a fixed version. I wanted to find out if the rumors were true.
I did not buy Death Force when FM77AV was my primary computer, mainly due to budget reasons. Luckily, I was able to purchase an original copy of Death Force recently. The disks crossed the Pacific ocean with no apparent damage or mold, and I was able to make disk images using my working FM77AV40. The FM-7 series emulator XM7 could emulate the copy protection, and I was able to boot the program with no problem. I began my investigation into the rumors.
The disks used in this test
Both A and B disks had a number 6C184F 2D printed on the back side
Conclusion
I will jump right to the conclusion: we have confirmed that there are at least two versions of Death Force. One version can be completed while the other cannot.
In my version, it was impossible to finish. Not because it was too difficult, but because the entrance to the pathway leading to the last boss chamber is blocked by a wall. The coordinate of the entrance at ($19,$0D) is blocked.
This entrance is on the screen pictured below. Internally, it is identified as MAP $79. The Death Force “world” is made up of a 16×16 matrix of maps. Each map has two layers: above and below ground. The map in the top-left corner is $00, and the ID increments by $01 moving to the right. Moving down the map matrix, the ID increases by $10. So, MAP $79 is 7 maps down, 9 maps right from the top-left corner map.
The stairs are not hidden at all, as you can see, but you cannot enter.
Below is the table of the entrance (stairs) coordinates of the final stage, stage 9.
The first byte $14 is the number of stairs. There are $14 (20) stairs in the final stage. If you look at the fifth set of stairs, it has four numbers: $79, $19, $0D, and $01. $79 is the map ID. ($19,$0D) is the coordinate of the stairs in map $79. Each map consists of 40×37 smaller blocks. The coordinate ($19,$0D) means $19 (25) blocks to the right, $0D (13) blocks down from the top-left corner. The last $01 tells that you need to move downward to enter the stairs from the field down to the underground level.
The following is the table for collision check. If the bit 0 is 1, the block is solid. Each byte covers 1×2 blocks. The bytes highlighted red are blocking the entrance to the stairs leading to the last-boss chamber. The player can go down no farther than Y=$0A. Since the entrance to the stairs is checked before the wall, if the Y-coordinate of the entrance is $0B, you can enter the stairs. However, the Y-coordinate of the entrance was written as $0D, making it impossible to enter.
There are two solutions. One is to alter the Y-coordinate of the entrance from $0D to $0B. The problem with this method is that the coordinate is written in the program disk (A disk) track 15, side 0, sector 12. That would require modifying the disk data, so we want to avoid this. (Of course, it’s not a big deal if you are working with disk images, but you shouldn’t modify the few remaining original disks of such a classic game! If something fails, you may permanently destroy your copy. The original disk is a historic artifact. Don’t modify it if you own one.)
There is a better solution. The above wall table (at memory address $4C00) is constructed from 20×10 table when the player moves across maps. The 20×10 table is in the data disk, and it is copied from B disk before you start a new game. The 20×10 table for map $79 is as follows:
You can shift the stairs by two blocks by moving the highlighted 6 bytes by one row. The table is written in track 11, side 1, sector 9 of the data disk. By modifying the sector as follows, you can enter the stairs leading to the last-boss chamber.
This change moves down the stairs graphics by two blocks in map $79, as you can see below. This change will allow you to finish the game without altering Disk A.
Well, it’s not very kind to explain how to modify the sector without giving a way to do so. If you have a data disk image of Death Force, and are having a problem finding a way to the last-boss chamber, you can modify the data-disk image by the following Python script. I don’t like Python. I like C++ better, but maybe more people have Python interpreter rather than a C++ compiler.
import sys
inFName=sys.argv[1]
outFName=inFName+"_patched"
print("Input="+inFName)
print("Output="+outFName)
ifp=open(inFName,"rb")
bin=ifp.read()
ifp.close()
print("Python inferiority.")
print("Why do I have to convert an array to a list, edit,")
print("and then convert it back to an array?")
print("Surprisingly poor programming language.")
print("Ditch Python. Use C++.")
lst=[]
for b in bin:
lst.append(b)
print("Input Length="+str(len(lst))+" bytes")
nFound=0
for i in range(len(lst)-60):
if lst[i:i+5]==[0x0b,0x18,0x2d,0x2e,0x2f] and lst[i+20:i+25]==[0x09,0x19,0x46,0x47,0x5a]:
print("Found at 0x"+hex(i))
lst[i+42]=lst[i+22]
lst[i+43]=lst[i+23]
lst[i+44]=lst[i+24]
lst[i+22]=lst[i+2]
lst[i+23]=lst[i+3]
lst[i+24]=lst[i+4]
lst[i+2]=0
lst[i+3]=0
lst[i+4]=0
nFound+=1
if 1!=nFound:
print("This should occur only once.\n")
print("Something is not right.\n")
quit()
ofp=open(outFName,"wb")
ofp.write(bytearray(lst))
ofp.close()
print("Wrote to "+outFName)
print("Rename the extension before using.")
If the data disk image is DFORCEDATA.D77, and if you saved this script as dforcepatch.py, you can type as:
python dforcepatch.py DFORCEDATA.D77
It will create a file called DFORCEDATA.D77_patched. Please change the extension to D77 and use.
Also I made my data disks near the ending available. I couldn’t go through the violent offence from the enemies in the last stage. I altered the player data in the data disk. Also I used a different method to enter the stairs, so the map hasn’t been modified in these data disks.
Another rumor about Death Force is that one user complained to the developer, Riverhill Soft, that the game was unbeatable and was sent a fixed version that could be completed. Is it real or fake?
Based on the above observation, if such a bug-fix version exists, the change from the un-finish-able version most likely be in track 15 side 0 sector 12 of A disk, or track 11 side 1 sector 9 of B disk. If the user who received a bug-fix version disk was able to finish the game, the change should be in A disk because B disk is used only once when the user starts a new game.
This question was solved by a copy of Death Force owned by a member of the Game Preservation Society and also disks in the Game Preservation Society collection. The member’s disk had a serial number 75524X 2D on the back of the disk. My copy has 6C184F 2D. The number probably is the serial number for the batch of the disk, not the serial for Death Force. Nonetheless, since the highest digit of his serial number is 7, and mine is 6, his copy is likely to be a newer version.
Below is the dump of track 15 side 0 sector 12 of his disk.
Four bytes from offset $0011 are 79 19 0B 01 in his version and 79 19 0D 01 in my version. This change matches exactly with one of the possible corrections I predicted.
The Game Preservation Society kindly checked three Death Force disks in their collection. Two of the three disks had $0D (bugged version) at offset $0013 of the sector, and one had $0B (fixed). Overall, we have checked six A disks, four of them were bugged and two were fixed. Although we cannot completely exclude the probability that a user somehow figured how to bug-fix the disk and made the change, such a probability is very slim. Most likely Riverhill Soft realized the bug after shipping the first version then published a corrected version.
It was somewhat lucky that I received a bugged version disk from Yahoo auction. If I picked up a corrected version, I would have finished with no problem, and I could have concluded that the rumor was false.
Was it due to the backfire of the copy protection?
Regarding one of the questions, whether it was due to the copy protection gone wrong, I can not conclude for sure. However, I have a feeling that this was not the case. The reason for this is because there was no disk access for any sort of copy-protection check when the player enters the last stage (stage 9) until reaching map $79.
The copy protection of Death Force checks the presence of $F6 and $F7 sectors, then checks the content of the sectors, and also checks that the sectors give for a CRC error. It is a very common copy protection in Fujitsu FM-7 series computers. I have modified the source code of FM-7 emulator called XM7 so that it breaks in the debugger when $F5, $F6, or $F7 is written to the sector register $FD1A. It does break while booting the game, indicating that the emulator is detecting the copy protection check. However, it did not break in the last stage.
From this observation I strongly believe it was not due to a copy protection mistake.
Was it just a plain old bug?
I believe it was a regular old bug:
1. In the fixed version, the player character can enter the stairs leading to the last-boss chamber without doing anything special.
2. The last stage, stage 9, has numerous errors with the stairs coordinates, not just the one leading to the last-boss chamber. Several are inaccessible as they are blocked by a wall. For the same reason, there are many chambers that you can go in but never get out.
3. The game does not have many special tricks or features. As I played through the game, I saw only two special features: one, when all 15 seals are collected the player appearance and the BGM changes, and two, the BGM changes when you kill the last boss. Other than that, the game progresses with the same rules and the same code. I cannot believe the developer wrote special code just for this entrance.
4. If the developer intended to make a special trick for this particular entrance, it would more likely be an invisible stairs at the beginning, which becomes visible when certain conditions are met. It sounds very strange if the developer keep it visible all the time and then move the stairs on a certain condition.
If it was not a bug, there must be a way to enter the stairs without altering the data disk or the program disk. We cannot fully exclude the possibility that the first version had an additional secret that the user needs to discover to enter the last-boss chamber, but it was too difficult and removed in the later versions. Possibilities are:
1. the Y-coordinate of the entrance in map $79 changes from $0D to $0B,
2. the wall in map $79 blocking the entrance moves down by 2 blocks, or
3. the properties of map $79 changes so that the wall moves down by 2 blocks by a KEY, if certain conditions are satisfied.
Possibility 1 is very unlikely because the coordinate of the entrance is written in disk A, which is write protected. Therefore it wouldn’t be saved to the data disk.
Possibility 2 is unlikely, too. If there is a code that alters map $79 somewhere, the alteration must be saved to the data disk once the blockage is removed. I have experimented if the change to the map can be saved. In XM7 debugger, I modified the map data of map $79 and made sure the map appearance has changed. Then I saved the data and examined the disk image to test if the modification was saved. Also I restarted the game from where I saved. In this experiment, I did not observe the changes in the map in the data disk, and the map appeared the same as pre-modification after re-booting and re-loading the data. Changes to the map were not saved, therefore Possibility 2 is unlikely.
There still is a possibility that this particular change remains in one session, and the player needs to re-satisfy the condition if the program is re-booted. However, all other status are saved to the data disk. It is very strange if this only one state is not savable.
I believe that the possibility 3 is most likely among all possibilities. In map-changing code, there is a very interesting piece:
If the properties of a map is configured so that the map consumes a KEY, two temporary changes are made to the map when the player first enters. One is a change when the highest 2 bits match a certain pattern. If they match, the 2 bits will be replaced with a different pattern. However, since the binary code for the stairs has a different highest 2 bits, this change does not help. The second change is applied to overwrite arbitrary six bytes with arbitrary values. Six bytes are just enough to move the stairs.
The properties of map $79 is written in 32 bytes table at physical address $0B6B0. If bit 7 of the byte at offset $1F is 1, the map consumes a KEY. The bytes in offset $14 to $1E defines the six-byte modification to the map.
Importantly, this change will be saved to the data disk with other status.
With this modification, map $79 will become as following image when you enter with a KEY.
As you can see, the stairs graphics will be stretched unnaturally. Although this modification to the map properties opens the path to the last-boss chamber, and the status is savable, I doubt if the developer could have added such a feature that breaks the appearance of the graphics. Although it is most likely among the above possibilities, I think it is ultimately not the intention.
Again, being unable to find a code that opens the path to the last-boss chamber does not mean it doesn’t exist. I cannot say that there is absolutely no way of entering the chamber without modifying the program or data disk. And there may yet be another method for the player to enter the last-boss chamber that I haven’t considered.
Nonetheless, after considering the above possibilities, my conclusion is that it was just a plain bug that was blocking the pathway to the last-boss chamber.
Invincibility Commands
It is known that if you type “SILVER” (case sensitive) and space while the opening music is playing, the player character becomes invincible until you restart the game. You can play in invincible mode, save, and restart into normal mode. For example, you can force the way through difficult maps in the invincibility mode, save, and then continue in the normal mode. (Reference: http://fm-7.com/museum/database/urawaza/810101300.html)
The code disassembly revealed that two more keywords are checked when the user presses the space key during the opening demo. The keyword is not checked exactly. Instead, it checks the total and XOR of the six characters typed before the space key. Therefore, the order of the letters does not affect the consequence. Also there are multiple set of characters that works for the feature.
The keywords are as follows.
“SILVER” Invincible (Checksum 0x17D5)
“1VKJIC” Zero Life (Checksum 0x6CA8) <- This feature is nullified anyway because Life is then read from the data disk.
“ARKoxo” Invincible + Infinite keys + Continuous shots of the Bomb + ? (Checksum 0x2034)
There might be a meaningful keyword that enables the second and the third features. However, there are too many combinations, and I could not find the one that has a meaning. The following is a C++ source code I used for finding the keywords for the second and the third features. If you are patient, you may be able to find meaningful words among the candidates.
Last Boss: very similar to one of the other bosses
Ending (spoiler alert!)
Slow-Growth Problem of DUR Max
In this game, the player has four parameters: LIF, DUR, WEP, and MOV. The Maximum value of LIF, WEP, and MOV grows by collecting power-up items. There is no description of the condition that grows DUR Max in the manual, though, and the growth is extremely slow. DUR Max is written in $3C ($003C). I looked for the condition in disassembly that grows DUR Max. It turned out that DUR Max grows once every 128 times the player gets a damage.
The following disassembly is part of the damage routine.
1BFC 0C 48 INC <$48
1BFE 96 48 LDA <$48
1C00 84 7F ANDA #$7F
1C02 26 0D BNE $1C11 <- $48 is incremented for every damage.
This BNE passes once every 128 times.
1C04 96 51 LDA <$51 <- If the damage is from self-inflicting (by bomb) <$51=1.Otherwise 0.
1C06 26 09 BNE $1C11
1C08 96 3C LDA <$3C <- Reading DUR Max.
1C0A 81 FF CMPA #$FF
1C0C 27 03 BEQ $1C11 <- Preventing overflow.
1C0E 4C INCA <- Increment DUR Max.
1C0F 97 3C STA <$3C <- Writing DUR Max.
The game balance should have been adjusted so that DUR Max is reasonably high when the user is close to the last-boss battle. But, if you play this game with no prior knowledge, your DUR Max won’t grow much until the last stage. What is worse is that if you play well and avoid damage, you won’t be rewarded. Good game play should be rewarded. Rather, this game penalizes you if you play well. Back in 1987, we did not have such methodology for adjusting the game-balance.
The present value of DUR (not max) recovers automatically. But the recovery is painfully slow. After killing a few enemies, you will need to wait for 20 to 30 seconds until DUR recovers. I was hoping the recovery may become faster with the growth of the player character, but it was not the case. DUR recovers by 1 every 64 iterations of the main loop. It is hard coded and never changes. Waiting 20 to 30 seconds every few battles is obviously unacceptable with the current standards of gameplay balance. Death Force is a game from 1987 after all.
The following is disassembly of where DUR is incremented by 1 every 64 iterations.
05E5 96 24 LDA <$24 <- Counter: incremented every iteration of the main loop.
05E7 84 3F ANDA #$3F
05E9 26 0E BNE $05F9 <- Pass once every 64 iterations.
05EB 96 38 LDA <$38 <- Reading DUR current value.
05ED 91 3C CMPA <$3C
05EF 24 01 BCC $05F2 <- Passes if there is a room for recovery.
05F1 4C INCA <- Recover by one.
05F2 97 38 STA <$38 <- Writing DUR current value.
Death Force World Map
The following maps are created by trimming and stitching screenshots together using 2D Retro Map Tool. I had to add support for transparency to stitch underground map where only passable blocks are visible at one time. I will upload the upgraded version shortly.
Field
Underground
Playing Guide
Beginning
The basic gameplay involves (1) collecting all weapons and seals (I think the developer meant SEAL, but misspelled as SEEL in the game.), (2) killing the last boss, and (3) killing yourself. Aside from some hidden stairs, there are few tricks or secrets you need to find. Locations of the seals, weapons, and stairs are marked in the above maps.
This game is called an RPG, but unlike traditional role-playing games like Wizardry or Ultima, the player character does not grow just by killing enemies. You need to pick up items for increasing LIF, MOV, and WEP attributes, and take damages to increase DUR maximum. Boss characters drop items for increasing LIF, MOV, or WEP. The type of the item is random.
You also need to collect KEYs. You cannot get around without KEYs. One of the biggest nightmares in this game is that you can only carry up to 5 keys at one time. You cannot collect 100 keys before going into long travel. Therefore, you need to spend time on the way to re-supply keys when possible. Since the kind of item an enemy drops is random, you will spend a great deal of time on re-supplying keys. Even taking into account that the game is from 1987, it’s still very painful and takes tremendous patience.
If you play it on XM7 emulator, I suggest keeping a memory dump of the main system from $0000 to $007F always open. There the program keeps main parameters. Some of the parameters that I identified are listed in the Selected Technical Information section. You can carry only up to five keys at one time, but you cannot see how many keys you have. The game will torture you by not telling how many keys in your pocket! But the number of keys is in $003D. You’ll know when you finally have enough keys. Also you need to take damage 128 times to increase the internal value of DUR max by one. Extremely painful, but at least if you know how much more damage for increasing DUR max, it gets slightly more bearable. The damage count is $0048.
When you start a new game, the first thing to do is to collect keys. You need to work on this painfully boring task many times during the game play. What you can do is move to the map to the right from the starting map, and then go down. In there one L-PAC, which recovers your LIF, is hidden behind the wall. It is close to the top-right corner. The item re-appears when you get out and come back in to this map. Therefore you won’t need to worry about exhausting your LIF to death.
In some maps, enemies, items, and bosses never appear again once you kill them and pick them all. In other maps, they do re-appear indefinitely once you walk out and in to the map again. For example, you can quickly recover your LIF in such maps with indefinite L-PACs. One thing to be careful of is if the map consumes a key, you may exhaust your keys by walking in and out of the map many times. Some maps consumes a key but also you can get a key or two indefinitely. In those maps you won’t have to worry about exhausting keys. In a map that a weak boss re-appears indefinitely, you can kill a boss many times to train your L-MAX, W-MAX, and M-MAX.
Once you collect enough keys, go to MAP $21 and get 8-way shot. 8-way shot is very useful. If you kill all small enemies and get the 8-way shot, you will need to fight a boss. If you want to avoid a boss-battle, leave at least one small enemy.
After getting the 8-way shot, go to MAP $03 via underground. There you will see small enemies that drop an item. In this map, enemies and bosses will re-appear indefinitely. By killing enemies and collecting items, you can quickly recover your LIF, WEP, and MOV. If you also kill the bosses, you can train your L-MAX, W-MAX, and M-MAX. The bosses in this map are relatively weak. You can go close to the boss and blaze you 8-way shots. If you shoot from immediately above or below the boss, near the center, 3 of the 8 shots will hit the boss. It’s a good idea to exercise your patience, and spend several hours to train your L-MAX, W-MAX, and M_MAX in this map. You’ll need to do it before going to the last-boss battle. If you do it earlier, the rest of the game play will become easier.
MAP $03
Getting Guided Missile, Bomb, and Fire Thrower
After training in map $03 for several hours, you are ready to go and get three weapons, Guided Missile, Bomb, and Fire Thrower. Go to Stage 8 via underground and come out to the field in map $62. There are two bosses in map $62, but they are easy to defeat.
Then move to the map above (map $52). You will need to fight a relatively strong boss, which I call the “Water Bottle.” Try to blaze 8-way shots and attack physically at the same time. You may take substantial damage, but you should be able to win. Then go underground and get the Guided Missile. Once you have this weapon, it is easy to kill the Water Bottle. All you need to do is hide behind a wall and continue shooting the Guided Missiles. Actually if you have a wall, this strategy works for all the bosses, including the last boss.
Then go back to map $62 and go to the underground level. Walk to the south while re-supplying as needed and go to Stage 7. Go above ground at map $A0. Go down to $B0 and get the Flame Thrower. The boss at $B0 is strong. Therefore, leave one small enemy to avoid the boss battle.
Make sure to walk from map $C1 to $D1 from the right-hand side of the map. You need to kill two very strong bosses that I call “Sunny-Side Up” and “Pierrot” (“clown” in Japanese). Use hover to quickly take cover behind the wall and shoot guided missiles from there. These bosses won’t re-appear once you kill them, so they won’t be an issue in the return trip.
Then go to map $C0, and go underground. One very important thing in the underground level of map $C0 is to make sure you have at least one key when you go in, and then as soon as you go in, get two keys hidden behind the door. Since you can get two keys, you can go between maps $C0 and $B0 to recover your keys to max (five keys).
Once you have at least two keys, go to map $D0 and get the Bomb. This weapon is needed to see the ending roll because you will need to kill yourself after defeating the last boss.
Collecting Seals
Then all you need to do is collect the 15 seals. Locations of the seals are on the maps. You need to collect them in a specific order. I put numbers beside each in the maps so that you can know in what order you need to collect them.
I don’t know if you need to collect all the weapons as well. I have a feeling that you don’t, but I’ve not confirmed it. Maybe it is safe to also collect the Boomerang as well.
Training DUR Max
After collecting all seals, one last painful thing to do before fighting the last boss is to train DUR Max. In this game, DUR Max increases by one for every 128 times damage is taken. (By the way, the number you see on the screen is twice the internal value. It means that you need to take 256 times of damages to increase the number on screen by one.)
In my opinion, the most efficient location to train DUR Max is map $B5. Four small enemies with an item (I call them Shrimps) re-appears indefinitely. Also you can pick up two L-PACs. If you need more L-PAC, there is another one on map $B6. You can go to the secret underground level from a few maps below to recover WEP as well.
To kill these four small enemies, align them nearly horizontally and shoot 8-way shots. If you are lucky enough, four shots will hit them. Once you attack, they shoot you back. So you can get damages and train DUR Max.
You will need to continue this work for several hours. Remember: it’s a game from 1987 with dreadful gameplay balance.
Map $B5
Last Boss Battle
When your DUR grows like 50 on the screen, then you can go for the last-boss battle. I have drawn green lines to tell you how to get to the last-boss.
But, enemies in the last stage will fiercely attack you. You will get substantial damage before getting to the last-boss. The last place to recover is map $7B. There one of the weakest bosses, which I call Green, re-appears indefinitely. If you go down to $8B, you will need to fight a Pierrot, which will give you a good amount of damage. So, instead of going down and come back up, you can save and load to resurrect a Green. Since L-MAX, W-MAX, and M-MAX also recovers LIF, WEP, and MOV, you can easily top-off by repeating saving and loading in map $7B.
Last Supply Point. Map $7B
Then finally the last-boss battle. In the last-boss chamber, there are a bunch of small enemies which I call Blackberries. Blackberries are fast and blaze missiles at you. They move too quickly for guided missiles, so use your 8-way shots, bombs, and direct attacks to quickly kill them before getting too much damage.
Once you kill all Blackberries, you need to fight a normal Pierrot first, and then the last boss, which looks like a Pierrot, but with two eyes open. You can win by hiding behind a wall and shooting guided missiles.
After killing the last-boss, use Bomb to kill yourself to see the ending roll.
The Last Boss. Hide behind a wall and shoot guided missiles to win
Selected Technical Information
Main Loop
$230~$24E Initialization
$251~$277 Main Loop
$279~$28B PAUSE loop (runs until ESC key stroke)
0251 8D 26 BSR $0279 <- If the user presses the ESC, this loop blocks until another ESC key stroke.
0253 BD 22 0B JSR $220B
0256 25 D8 BCS $0230
0258 8E 00 00 LDX #$0000
025B 9F 0E STX <$0E
025D BD 0A 5F JSR $0A5F
0260 BD 02 8E JSR $028E
0263 BD 02 B6 JSR $02B6 <- Moving: item-acquisition is in this routine.
0266 BD 15 E4 JSR $15E4
0269 BD 14 D4 JSR $14D4
026C BD 0A 28 JSR $0A28
026F BD 21 29 JSR $2129
0272 BD 2A 4C JSR $2A4C
0275 0C 24 INC <$24
0277 20 D8 BRA $0251
Main CPU address space $0000 to $00FF (Physical address $30000 to $300FF)
DP=0x00
+00 Key stroke interpreted as joystick code.
+01 Player character direction (0 is up. 8 directions clockwise.)
+02 Block coordinate X $25 at the right edge.
+03 Block coordinate Y $22 at the bottom edge.
+04 Copy of block coordinate X.
+05 Copy of block coordinate Y.
+06 Copy of the joystick code.
+07 Alternate between 0 and <$06 copy.
+08
+09 Sword state. 0 is retracted. 3 is most extended.
+0A
+0B Move counter. The player character moves one step when it is zero. In normal mode it is reset to 3. In hover mode 2.
+0C Alternate 0 and <$0D copy while button is held down. Probably for continuous shooting.
+0D Last button state (for thrust event)
+0E Higher byte of the timer tick count
+0F Lower byte of the timer tick count
+10
+11
+12
+13 General purpose
+14
+15 Acquired item code
+16
+17 $0A92~$0BE1 loop counter. Probably for moving enemies.
+18
+19
+1A
+1B
+1C
+1D Stage ID
+1E [$7E00+MapID]
+1F
+20 Bit 0 indicates field or underground. Bit 1 is set to 1 when the player moved between the field and underground
to flag that the map needs to be updated. Bit 1 will be reset to 0 as soon as the map is updated.
+21
+22 Map ID
+23
+24 Incremented every iteration of the main loop
+25 When moving to a next map, [$7800+20*(Y/4)+(X/2)]&0xC0
+26 Pointer to the map properties set in the map-update routine.
+27
+28
+29
+2A
+2B
+2C
+2D Number of remaining enemies in the current map.
+2E Cannot enter the stairs unless it is 0. If bit 7 is set, the player cannot get out of the map until the boss is killed.
+2F Updated when the player moves across a stage border. The meaning is unknown yet.
+30 Updated when the player moves across a stage border. The meaning is unknown yet.
+31
+32
+33
+34 Counter since the last thrust or shooting.
+35 LIF
+36 MOV
+37 WEP
+38 DUR
+39 LIF Max
+3A MOV Max
+3B WEP Max
+3C DUR Max
+3D Remaining Keys
+3E Available weapon flags
+3F
+40 Number of acquired seals. (I believe SEEL in the game is misspelling)
+41
+42 Last-acquired item type for showing a message.
+43 GET **** I believe it is a counter for showing a message.
+44
+45
+46
+47
+48 Damage counter. DUR Max is incremented when its bit 7 flips.
+49 Updated when the player moves across a stage border. The meaning is unknown yet.
+4A Updated when the player moves across a stage border. The meaning is unknown yet.
+4B Updated when the player moves across a stage border. The meaning is unknown yet.
+4C Updated when the player moves across a stage border. The meaning is unknown yet.
+4D Updated when the player moves across a stage border. The meaning is unknown yet.
+4E Updated when the player moves across a stage border. The meaning is unknown yet.
+4F Updated when the player moves across a stage border. The meaning is unknown yet.
Identified Sub-Routines
$0694 Collision check with enemies and walls.
$0A14 Display message. <$42 is the message code. <$43 is probably the duration.
A register is probably the number of remaining items for the message.
$0E87 Change stage. Called from $245B (Change map)
$2414 D=20*(Y/4)+(X/2)
$241F D=$4500+B*#$28+A
$2429 Change map
$27A0 Update passable blocks after changing the map.
Tables
Entrance-coordinate table from $7C00 was particularly useful.
$2109~ Moving vector table?
$2199~ Moving vector table? $2199+(joystick code & 0x0F) $FF means unavailable direction.
$3200~ Probably parameter table of enemies.
$328A~ Seal acquisition flags. 1 byte per seal. 0 or 1.
$3299~ I think it is the enemy list. Not confident.
$3330~ Looks to be maps, but too short.
$38C0~ BGM work area? Some bytes are in sync with the BGM.
$4500~$4B3F Map for detecting collision between enemies and items.
'0' is the player character. $FF is an empty block.
$00~$2F are enemies. $30~$7F are items.
$4C00~$4F1F Map for detecting collision between the wall.
$7800~ Map.
$7C00~ The first byte is the number of stairs for the current stage.
Subsequent 4-byte entries mean MapID, X, Y, direction of entry.
$7D00~$7DFF Map ID to Stage ID table.
48 0F 0B 01
56 1B 09 04
57 19 0F 04 The entrance overlaps with the wall. Cannot enter.
58 0E 07 04
69 1E 13 04 Once enter, exit overlaps with the wall, therefore no exit. Is it intentional?
6A 0F 14 04
6B 1E 13 04
75 05 0C 01
77 17 1C 01
77 1C 07 04
78 07 1F 01
79 19 0D 01 Cannot enter. In the finish-able version, it is 79 19 0B 01.
7A 07 1D 01
7B 05 01 04
85 08 10 04 Bug? Intentional? It is off from the graphics.
87 1E 0F 04
88 13 0F 04
89 05 16 04 Once enter, exit overlaps with the wall, therefore no exit. Is it intentional?
8A 07 1D 01
8B 05 07 01
Item Acquisition
Item acquisition is processed in the routine from $0694. The same routine is used for collision check against enemies. The player does not get damage from the collision with an enemy, but cannot walk through an enemy.
JSR $15A8 will return the code of the item acquired. If it is greater than $0B (11), it is a seal, otherwise a regular item. Seals can only acquired in a specific order. The player can know that a seal is missed in an earlier stage if the player cannot pick up a new seal. The game is torturing the player with DUR, but this point was somewhat kind to the player.
If the player acquired a regular item, the program jumps to the address in the jump table $076B~.
06A9 BD 15 A8 JSR $15A8 <- Identify what item is acquired.
06AC 81 0B CMPA #$0B
06AE 22 22 BHI $06D2 <- Is a seal if the code is greater than $0B
06B0 C6 01 LDB #$01
06B2 96 15 LDA <$15
06B4 BD 15 A8 JSR $15A8 <- I think this sub-routine erases the item graphics.
06B7 97 15 STA <$15
06B9 8E 07 6B LDX #$076B
06BC 48 LSLA
06BD AD 96 JSR [A,X]
The following disassembly is for acquiring a seal.
06D2 8E 32 8A LDX #$328A <- Seals already acquire.
06D5 80 0C SUBA #$0C <- Item code 12 is seal 0. Therefore, subtract 12 from the item code.
06D7 27 08 BEQ $06E1 <- If it is seal 0, always pass.
06D9 4A DECA <- To test if the previous seal is already acquired, A=A-1
06DA E6 86 LDB A,X
06DC 10 27 00 28 LBEQ $0708 <- Is seal[A] already acquired?
06E0 4C INCA <- Bring the value of A back to previous.
06E1 6C 86 INC A,X <- Raise the seal-acquired flag.
06E3 0C 40 INC <$40 <- Increment the seal count.
Changing the Stage
By monitoring $7C00 to $7CFF, you can see that the player moved across a stage border. The same routine is called after a boss battle.
The stairs table from $7C00 is extremely important. If the copy-protection backfire theory is correct, most likely this routine checks the copy protection, and will correct the location of the stairs in map $79 if the check passes.
However, the stairs table is read at the bottom of this routine, and the routine returns by PULS B,PC. Therefore, the stairs table is unaltered in this routine.
Of course, there is a possibility that the table is corrected somewhere totally different. For example, the developer expected someone may look into the code, the developer could have separated the routine for reading the stairs table, and the routine for correcting the table.
Boss-battle mode shares the main loop with the normal mode. Once the player kills all small enemies in the map in which a boss or two exist, the player cannot get out of the map until all the bosses are killed. The conditions for a boss to appear are for all small enemies to be killed and no more items to exist in the map.
The boss number (2 bosses per map maximum) is written in <$2E. If bit 7 of <$2E is 1, the player cannot get out of the map until all the bosses are killed. If small enemies are still alive, but a boss exists in the map, <$2E is 1. The player can get out of the map, but cannot enter stairs.
Following addresses are controlling <$2E.
0F61 LDA #$80 STA <$2E Take all items->cannot escape boss fight.
0FDF LDA #$81 STA <$2E When boss appears, $80->$81
106B LDA #$01 STA <$32 STA <$2E Can escape the boss but cannot use the stairs.
11D5 LDA #$82 STA <$2E Looks like the second boss.
11FE CLRA STA <$2E STA <$32 <$32 and <$2E works together? Couldn't find the meaning of<$32 yet.
Boss-generation routine is from $0F69.
0F69 96 2E LDA <$2E
0F6B 10 2A 01 19 LBPL $1088 <- Skip if no boss exists.
0F6F 81 80 CMPA #$80
0F71 10 22 00 6E LBHI $0FE3 <- Already in the boss-battle mode?
0F75 96 23 LDA <$23
0F77 9B 2B ADDA <$2B
0F79 9B 52 ADDA <$52
>0F7B 10 26 FC 66 LBNE $0BE5 <- The boss won't materialize if the sum of <$23, <$2B, <$52 is non zero
Meaning not identified yet
0F7F F6 32 99 LDB $3299 <- Boss ID
0: Mint
1: Green brain
2: Silver brain
3: Sunny side up
4: Canteen
5: Robot
6: Octopus
7: Pierrot (or Clown)
8: Lady bug
9: Pierrot (or Clown)
A: Pierrot (as Last Boss)
0F82 D7 13 STB <$13
These names are my own; I don’t know the official names. What is interesting is that you can control which boss appears by stopping XM7 at $0F82 and modifying the value of B register.
The graphics corrupted when I set B=$0B. Also, the length of the boss table is 11. I believe there are no more than 11 kinds of bosses in total. There are two Pierrot types, aside from the last boss. One may be unused. Or perhaps both are used and I simply could not identify which was which.
Boss properties looks to be described in two tables below. I haven’t yet figured out the meanings of the tables.