A game by Sam Dicker, Noah Falstein, R.J. Mical and Richard Witt
Source code rewrite by SynaMax, started November 6th, 2023; complete ROM set rebuilt for the first time on January 12th, 2024 (sound and speech code added on the 15th and 16th respectively).
Original game concept by John Newcomer
Artwork by Jack Haeger
Sound ROM (VSNDRM9/VSNDRM10) programmed by Mike Metz
Speech routines programmed by John Kotlarik
Special thanks to: Kay Anderson, Harry Cline, Kristina Donofrio, Ken Fedesna, Ken Graham (RIP), Rich Grande, Ken Lantz, Pierre Maloka, Keith McMillen, John Meissen, Tim Murphy, Tom O'Meara, Bill Pfutzenreuter, Rudy Plemich, Dave Rzepka, Marc Stanis, Ed Suchocki, and Stewart West
SynaMax would like to thank: HistoricalSource, braedel, kgalocy, mecha, Daniel Lopez, Tony Temple, AT Gonzalez, Nick Bernhard, Alfred Arnold for creating {AS}, David "Haze" Haywood, "N-F", all my fans and subscribers from my YouTube channel, my Patreon supporters, everyone on KLOV who has shown their appreciation and encouragement; and last but not least, my spouse for their never-ending patience and support during this project.
The original source code for the game can be found at https://github.com/historicalsource/sinistar/
For the first time ever, the source code for the sound and speech ROMs are included with the game code. The older version of the recreated sound ROM source can be found here: https://github.com/synamaxmusic/Sinistar-Sound-ROM/
- Important Milestones
- Overview
- Build Instructions
- About the source code
- Rewriting the source code
- Source code map
- Debug Options
- Mods
- Mod Combos
- Experimental Debug Options
- Old deprecated defines
{Warning: flashing images below)
-
09/10/2024 - Added a new mod combo that enables Sam's "TAIL" routine, the Marquee title screen fix, and changes the default value of the additional points per extra ship factor from 30,000 to 5,000 (which was confirmed by Noah to be a quick way of increasing the game's difficulty without messing up the game's tuning). This mod combo (19645) is probably the closest we'll get to making a "perfect" ROM set: it has the originally intended special graphics that were removed and it has Noah's final tuning of the enemy populations, but now it's much easier to score lives by default. Note: it is required to do a factory reset to make sure the new default value for the extra ships is copied over to NVRAM.
-
08/09/2024 - When I first uploaded the codebase to Github, I was disappointed to see that there were a lot of spacing issues everywhere. Tabs were used extensively in the original code so when I did the rewrite, I copied what the programmers did. Unfortunately, all these tabs (other than the leading indentations) were ruining the code formatting; but then the code would display correctly in the online editor.
I wasn't sure how to fix this for the longest time and I've been pushing it off until today. I'm forever grateful to the devs of Notepad++ because I was able to quickly go through the entire codebase and convert all the tabs into spaces using that text editor's powerful macro playback features. Before doing all of this, I confirmed in a separate test branch that the tab conversion indeed fixed the issue. All extra trailing spaces have been removed as well. The codebase is so much nicer to look at now and can be compared side-to-side with the original codebase from historicalsource!
Another thing that I changed was moving all the debug and mod options into a brand new file called,
mods.ASM
. This reduces a lot of clutter inMAKE.ASM
. -
06/21/2024 - I have a surprise announcement! Sinistar's early "prototype" AMOA build from November 1982 is now rebuildable from the source code! In order to do this, I created a new repository and uploaded the AMOA edits there. This was done to keep the current codebase from getting too messy as there were a lot of edits that had to be made; it took ten days to get the ROMs to match up! With this code, we can finally start to completely understand what exactly changed between versions, other than the obvious missing stuff like the Sinistar biting the player ship. You can view the code here: https://github.com/synamaxmusic/sinistar-amoa
-
06/04/2024 - I just now discovered that back in February, Macro Assembler {AS} version 1.42 Build 262 changed the way it handles 6809 instructions that use an empty first argument on indexed address expressions (i.e. using
LDA X
instead ofLDA ,X
). This syntax is used extensively throughout the codebase and now results in errors when trying to build the game. A new instruction specific to AS has been inserted in theMAKE.ASM
file to fix this issue. -
05/24/2024 - I pushed an important fix for the new
SAMTAIL
mod. Braedel discovered by accident that the watchdog chip was still triggering a system reset after the initial "rug screen" checksum test. I narrowed down the problem to the initialization section of the TAIL routine where theINITRAM
routine is called a lot to to generate the thruster plume graphic effect. To insert the instructions needed to fix the issue, I found aCLRB
instruction that allowed me to use the B register without messing up anything else in the routine. According to Sean Riddle, preventing the watchdog from being triggered requires writing $39 to address $CBFF within 8 vertical blanking periods (about 133 milliseconds). The Williams devs refer to this as "stroking" or "feeding the watchdog". TheTAIL
routine was allowing just enough VBLANKs between writes to cause the watchdog to "bark" and reset the system. Of course, this doesn't happen currently with MAME emulation so the watchdog never resets the machine, like it was doing on hardware.The fact that I had to add the watchdog instructions to this routine make me wonder if this special effect was removed early in development before the watchdog chip was enabled.
-
02/26/2024 - Relocated the Bargraph debug feature over to the new allocated area in ROM 11, it seems to run a bit more stable now!
More importantly, I reimplmented the unused "TAIL" routine from Sam's module. This code draws a special effect jet exhaust behind the player ship. When I initally tried injecting this routine into the ROM data last October, it seemed to be very buggy and would crash the game. However, after inserting TAIL back into the rewritten codebase and using Macroassembler {AS} to build it, it works way better now! To my surprise, the blue flames that I first witnessed back in October were actually a glitch as now they're a lovely combination of red and yellow pixels, which produces a much more interesting flame effect!
No wonder why Jack Haeger's marquee artwork depicts the player ship with a flame trail!
The tail also appears to react to how far the 49-way joystick is being pushed. Slightly pulling on the stick results in a diminished flame tail, while not pressing it at all turns the effect off.
Use the
SAMTAIL
define inMAKE.ASM
to build the game with this feature. I made it to work with other mods as well, see Mod Combos for more info. -
02/13/2024 - Spent the last few days working with braedel on getting the pause mod and AMOA graphic to work on the original hardware. The original process of overwriting the RAM/ROM tests proved to be troublesome as it was messing around with the watchdog and preventing the machine from powering up. Instead, new mods are now relocated to overwrite the "Cross hatch", color bars and switch tests in ROM 11. This fixes the boot issues and allows mods to finally work outside of emulation!
-
02/09/2024 - I have added a new mod that allows the player to pause the game! Simply press the player 1 button during gameplay to pause; pressing it again resumes the action. Huge thanks to braedel and Chris Brooks over at Coinoplove.com for inspiring me to implement this new feature.
-
01/30/2024 - As mentioned in the readme for my Joust source code rewrite, I have finally figured out how to get Tim Murphy's Walsh Function Sound Machine macros to work. This means that we can reproduce the "Extra Ship" and "ERROAR" sound effects accurately by using these macros instead of just copying the bytes over from the sound ROM. We are still missing a couple of macro instructions related to the pitch commands for "ERROAR" and one of the unused sounds, as I'm still not sure how to recreate them with macros yet; however, all the data for the "Extra Ship" effect is now generated via these macros, exactly how it was done in 1982!
-
01/29/2024 - The source code for Joust has been completely rewritten and I have decided to add a new source file from that repository over here as well. In order for Sinistar to launch in MAME, two decoder ROMs are needed. Use decoder_roms.asm to build these two required files.
-
01/23/2024 - We have our first pull request! Daniel Lopez verified that the game assembles with the unofficial community-maintained package of Macroassembler {AS} in Arch Linux; however, some minor changes were required. All
!=
operators were changed to<>
in order for the code to build because the package uses a older verison of {AS}. The rest of the codebase uses<>
so this actually makes things more consistent. -
01/21/2024 - Added a mod called
QuickOperatorEntry
that allows the user to edit the attract mode operator message much faster than before. This also affects the speed for inputting high score initials so it's possible that it can be easier to mess up when entering your name/initials. -
01/20/2024 - Added a define that fixes the checksum byte found in the very beginning of
VSNDRM9.ASM
. The original byte is$AA
but this is incorrect and the diagnostic test fails as a result. Using$24
for Video Sound ROM 9 or$70
for Video Sound ROM 10 will fix this issue. -
01/16/2024 - Took the plunge today and got the speech ROMs disassembled. Managed to get the vast majority of the code figured out!
-
01/15/2024 - Video Sound ROM 9/10's recreated source code has been rewritten to target Macroassembler {AS} instead of vasm. This is the first time ever that both sources for the sound rom and the game are included in the same repository! Rewriting VSNDRM9 for {AS} actually made the sound rom source code more accurate to how it was originally written and instead of having two separate sources like how it was previously done in my old version, we now just have one complete file that builds a perfect copy of the sound rom. I'm also planning on adding IFDEF instructions so that both sound roms can be built with the correct checksums, which will allow the test button on the sound board to function again!
-
01/12/2024 - 2:23pm, I fixed the last remaining byte in the ROM that was different from the source code. We can finally produce a bit-perfect copy of the final version of Sinistar!
I added a new file called
BURN.BAT
for those who want to quickly generate the ROM files from thesinistar.p
file. ROM 11 is handled slightly differently from the other ROMs so an additional option for P2BIN has to be given. Already implemented some debug functions and hope to add more soon, along with a fix to re-enable the original Marquee title screen from the AMOA build. The debug defines are found inMAKE.ASM
. -
01/12/2024 - At 12:23am, I finally finished rewriting all the game's code, with the exception of the diagnostic ROM (which is treated separately from the game). This means 10 of Sinistar's 11 ROMs match up perfectly with this rewrite and that the game should be completely playable. Once T13.ASM is rewritten, we should be all done.
-
01/11/2024 - All four modules and Sam's patches are finished. This means all that's left are the patches from the three remaining programmers, plus seeing how much debug stuff we can get working again. We're getting really close to wrapping this up!
-
01/08/2024 - Noah's module is complete! Gameplay finally works, but with some caveats: the Sinistar now appears in the sector but with RJ's explosion routine missing, it behaves differently and is ultimately invincible as a result. If the player hits the Sinistar with enough bombs, the Sinistar will "think" it's dead, however the warp sequence never starts and the Sinistar will stay stunned until the player gets killed by a warrior. Once the player respawns, the Sinistar (still with one piece remaining) returns to its chasing state. Unless it is hit by another sinibomb again, it can bite the player.
Also worth pointing out is that the sinibombs fire but they are only visible in the scanner and produce graphical glitches when near the Sinistar
(one of Rich's patches is needed to fix these issues)(turns out I had a made a local section of code that was actually preventing the Sinibomb graphics from being drawn; removing theSECTION/ENDSECTION
instructions fixed this issue).Currently working on rewriting RJ's module: this includes the attract mode, service menu, high score and status screens, and explosion effects.
-
01/06/2024 - Rich's module is finally complete, we're halfway done!
-
01/03/2024 - I cleaned up some of my older comments and replaced my old
PUSH/PULLORG
hacks with the actual macros. The same goes for theROUTINE
macro; it's actually pretty useful as it shows messages in the listing output and makes it easier to understand.PAD
doesn't work exactly the same with the new assembler so it's only used sparringly in this rewrite when there are no macro arguments; anyPAD
macros that need to generate new lable names have been replaced with three lines of code that reproduces exactly what we need (see PAD for more info). -
12/30/2023 - I got several important and heavily-used macros to work properly after several tests. These macros include
PUSHORG
,PULLORG
,ROUTINE
,PAD
, and the Copyright string macro. Implementing these will require more work as I would have to undo edits, but this will make the assembly process more accurate to how the game was originally built. -
11/14/2023 - Sam Dicker's section of code is buildable and will produce a playable ROM that only has the player ship, joystick controls and background starfield scrolling. The scanner's "fin" graphics are drawn but the scanner logic itself does not work (because there are no enemies nearby).
-
11/06/2023 - Source code rewrite commences.
-
10/14/2023 - Got previously undocumented player ship "tail" jet exhaust graphics from Sam's module working. Hoping to get this working in the rewrite eventually.
-
10/07/2023 - After several days of playtesting and experiments, I completed my Difficulty Mod which reduces the enemy populations to make the game easier.
-
10/05/2023 - Managed to get the original AMOA "Marquee" title screen graphic working in the final version of the game. Turns out the source code is slightly different from the AMOA build and has the position of the graphics and copyright text slightly higher than before.
-
09/30/2023 - Not code-related but discovered that the Sinistar roar sound effect is actually a recording of a gorilla entitled, "Gorilla Heavy Panting And Two Roars" from a De Wolfe Sound Effects library originally released in 1975 (DW/FX LP No. 16 "Zoo Animals - Wildlife", track 12 on side A).
-
09/05/2023 - Started testing different tunings on on the enemy population tables and created a repository for all my RE notes.
-
07/07/2023 - Began studying the inital enemy population tables found in the source code.
-
05/07/2023 - Started looking over the original Sinistar codebase for the first time.
-
03/27/2023 - I began my reverse engineering work on Sinistar's separate sound ROM.
Four main programmers worked on Sinistar and each directory in the source code belongs to one of them (however there's evidence that all of them were modifying and editing each other's code).
The four modules that make up the codebase are assembled in this order:
- SAM
- WITT
- FALS
- MICA
Sam Dicker was the first software engineer to work on the game and his code deals with critical routines related to the game engine, the player's ship, and the Sinistar itself. This also includes joystick control handling, rendering graphics, sound call tables, and background multi-tasking routines for enemy AI and gameplay logic. Jack Haeger's pixel artwork is also represented in this module (located in the SAM/IMAGE.ASM
file).
After Sam's code, we move on to Rich Witt's files. He worked a large chunk of the game logic routines, sometimes modifying Sam's pre-existing code. Rich's work includes the Sinistar death/player warp routines, sinibomb pickups, enemy speed tables and AI, collsion handling, and the Sinistar's lip sync animation.
Noah Falstein's module is up next and he worked on further AI programming for the enemies, planetoid logic (vibrating, tossing crystals, swarming, shattering), enemy population difficulty tables, and the Sinistar's speech calls.
Finally, RJ Mical's code involves the game's attract mode, high score table, operator message/high score initial entry, and death explosion routines for the warriors, the Sinistar, and player ship. There's a fair amount of unused code located in this directory including an earlier version of RJ's explosion routine as well as Mike Metz and Ken Lantz's "Marquee" title screen that's only found in the AMOA '82 prototype build.
The MAKE.ASM
file in the top directory grabs all the source code files from all four folders and tells the assembler which order they go in the binary ROM data.
This source code was rewritten to target Macro Assembler {AS}.
To build Sinistar, place the four folders (SAM, WITT, FALS, MICA
) and the MAKE.ASM
file into the same directory as ASL and P2BIN.
Then, open a command prompt and type in:
asl make.asm -o sinistar.p
Once the sinistar.p
file is generated, we can use the BURN.BAT
file to create the 11 separate ROM files that make up Sinistar.
Address | ROM # | MAME ROM set Filename |
---|---|---|
0000-0FFF | ROM 1 | sinistar_rom_1-b_16-3004-53.1d |
1000-1FFF | ROM 2 | sinistar_rom_2-b_16-3004-54.1c |
2000-2FFF | ROM 3 | sinistar_rom_3-b_16-3004-55.1a |
3000-3FFF | ROM 4 | sinistar_rom_4-b_16-3004-56.2d |
4000-4FFF | ROM 5 | sinistar_rom_5-b_16-3004-57.2c |
5000-5FFF | ROM 6 | sinistar_rom_6-b_16-3004-58.2a |
6000-6FFF | ROM 7 | sinistar_rom_7-b_16-3004-59.3d |
7000-7FFF | ROM 8 | sinistar_rom_8-b_16-3004-60.3c |
8000-8FFF | ROM 9 | sinistar_rom_9-b_16-3004-61.3a |
9000-DFFF | (SPACE RESERVED FOR RAM) | |
E000-EFFF | ROM 10 | sinistar_rom_10-b_16-3004-62.4c |
F000-FFFF | ROM 11 | sinistar_rom_11-b_16-3004-63.4a |
If it's not possible to use BURN.BAT
, this can be typed into a command prompt instead:
p2bin sinistar.p sinistar_rom_1-b_16-3004-53.1d -r $0000-$0FFF
p2bin sinistar.p sinistar_rom_2-b_16-3004-54.1c -r $1000-$1FFF
p2bin sinistar.p sinistar_rom_3-b_16-3004-55.1a -r $2000-$2FFF
p2bin sinistar.p sinistar_rom_4-b_16-3004-56.2d -r $3000-$3FFF
p2bin sinistar.p sinistar_rom_5-b_16-3004-57.2c -r $4000-$4FFF
p2bin sinistar.p sinistar_rom_6-b_16-3004-58.2a -r $5000-$5FFF
p2bin sinistar.p sinistar_rom_7-b_16-3004-59.3d -r $6000-$6FFF
p2bin sinistar.p sinistar_rom_8-b_16-3004-60.3c -r $7000-$7FFF
p2bin sinistar.p sinistar_rom_9-b_16-3004-61.3a -r $8000-$8FFF
p2bin sinistar.p sinistar_rom_10-b_16-3004-62.4c -r $E000-$EFFF
p2bin sinistar.p sinistar_rom_11-b_16-3004-63.4a -r $F000-$FFFF
Building Video Sound Rom 9 (VSNDRM9) just requires two commands:
asl VSNDRM9.ASM -o vsndrm9.p
Then use P2BIN to generate the binary ROM file:
p2bin vsndrm9.p -l 00 video_sound_rom_9_std.808.ic12
To build the cockpit-exclusive Video Sound Rom 10, simply remove the semi-colon in front of STEREO EQU 1
in VSNDRM9.ASM
, save the file and repeat the build instructions above (use video_sound_rom_10_std.ic12
for the filename instead).
Type this into a command prompt/terminal:
asl SPEECH.ASM -o speech.p
Then run SPEECH_BURN.BAT
to generate the four speech ROMs.
If it's not possible to use SPEECH_BURN.BAT
, this can be manually typed into a command prompt instead:
p2bin speech.p 3004_speech_ic7_r1_16-3004-52.ic7 -r $B000-$BFFF
p2bin speech.p 3004_speech_ic6_r1_16-3004-51.ic6 -r $C000-$CFFF
p2bin speech.p 3004_speech_ic5_r1_16-3004-50.ic5 -r $D000-$DFFF
p2bin speech.p 3004_speech_ic4_r1_16-3004-49.ic4 -l 00 -r $E000-$EFFF
This is probably a little bit overkill but I also included code that builds the required decoder ROMs needed for the game to run. MAME will refuse to launch the game if these files are not included so I added a new source file, even though it's fairly easy to find these files online. Regardless, I added them for completeness sake.
Back in May 2023, I stumbled upon the fact that Sinistar's source code was leaked in 2021 and available on Github. After deliberating for a few months and conducting several tests with various 6809 macro assemblers, I decided to do something I've never done before and accept the challenge of rewriting the source code for Sinistar so that it can be buildable with a newer assembler. Considering the size of the codebase, this was not an easy or quick task.
Other Williams games have be rewritten before, such as mwenge's work for Defender and Robotron, both targeting the asm6809 assembler. His work inspired me to make the attempt at recreating the missing 6800 assembly code for Sinistar's Video Sound ROM 9 and 10.
Here is a video on how I achieved this and how the sound ROMs in Sinistar work.
The goal of both of these Sinistar repositories is to recreate the game's ROMs from scratch. With Video Sound ROM 9, two disassemblies were heavily relied on in order to piece together the ROM since the source code was missing and had to be cobbled together from looking at the surviving source code and comments from the other sound roms. With this project however, we have the original source code, so there's not as much guesswork involved (in theory). I did tests with several different assemblers, including asm6809 and vasm (which I used previously for Sinistar's sound ROM) but I was running into several issues. I wondered why Robotron and Defender were able to be retargeted for asm6809, but not Sinistar or even Joust.
Joust and Sinistar were the first two games developed by the new internal dev team at Williams, after Eugene Jarvis and Larry DeMar left Williams to form Vid Kidz. Because of this, the source code for both Joust and Sinistar are similar to each other but show a lot of differences from the code for Defender and Robotron, especially when it comes to the use of macros.
For those who don't know, a macro is sequence of instructions that can be inserted into the final code when called. They can be very flexible and powerful in that they can generate many lines of code with just one reference. Several important routines in Sinistar rely on macros for various tasks, like compressing the font sprites or parsing ASCII strings and converting them into Williams Electronics's pseudo codepage standard. Another set of macros called PUSHORG
and PULLORG
use an internal stack to keep track of where sections of the ROM code begin and end.
Macros do show up for Defender and Robotron, but there's not too many of them, and whenever they do show up, they are very simple and short. Joust's source utilizes more complex macros with more parameters but they too consist of just several lines of code. Meanwhile, Sinistar defines at least 33 macros in just one file alone, with some macros reaching 50+ lines of code. The surprising complexity of some of these macros required several days of troubleshooting to get them working in this rewrite.
Like Joust, Sinistar was written on VAX/VMS workstations. I'm not sure what assembler was used for Joust, but both codebases appear to use the same syntax and we know that Sinistar was written for a cross-assembler by the now-defunct Boston System Office (BSO). It had support for several macro instructions that only a few 6809 assemblers still use today, such as IRP
, IRPC
and REPT
. This particular assembler is currently lost (which is one of the main reasons why this project was started in the first place).
The BSO assembler also caused a lot of headaches for the dev team; one of the biggest issues was that the asssembler's symbol table size was very small, which made Sinistar's development even more difficult. To directly quote the developers from the source code's readme file:
The problem history with managing sources for 4 people while using an assembler with a very limited symbol table size is not amusing. Let it suffice that we did what was neccessary at the time.
As a result, additional precautions had to be made in order for the code to build properly and that all the symbols matched up with everyone else's library. For example, each of the four main software engineers had to generate their own files that listed every single EQU
, SET
, and symbol they used in their section of the game. Due to the limited table size, any symbol in these files that's over 6 characters in length is truncated.
At the end of the toolchain, a batch script file written in VAX DCL language collected all of the source files and fed them into the assembler in a specific order. It was a lot of work to make sure everything matched up but in the end, I'm really glad they were kinda forced to generate all these symbol definitions because it has made a lot of this reverse engineering work much, much easier.
Even just taking a quick glance over the code, it quickly becomes apparent that we need an modern and easily-obtainable assembler that supports several different kinds of macros or otherwise this project wouldn't be possible. I decided to target the source code rewrite to work with Macro Assembler {AS} because it supports a lot of those specific macro instructions previously mentioned and the syntax is very similar to what is in the original code so any rewrites are kept to a minimum.
Alan R. Baldwin's ASxxxx cross-assembler was also considered as it also supports the IRP
, IRPC
and REPT
macro instructions, but the amount of syntax changes needed in order for the code to build would be unfeasible.
Admittedly, working with Macro Assembler {AS} has been a bit of a challenge as it does some things differently from other assemblers that I've come across and the documentation is rather daunting. Unlike ASxxxx's manual, there's not many examples or concise instructions on how the assembler works. In fact, I feel I learned more from looking at Sonic 1 and 2 disassemblies targeting {AS} than the manual itself. Once I got the hang of the new syntax changes though, I started getting into the flow of things and was able to rewrite all of Sam Dicker's code in a week. It was a rough start but I did get used to how {AS} operates and I'm happy with the results so far.
I soon realized that because of the new syntax, I would have to rewrite more code than I initially intended. I tried my best to show all the changes to the code that I did with comments but I may have missed some minor edits here or there. My intention has always been to leave as much original code in as possible and change only what is necessary. Any major drastic changes will be pointed out in the comments. New comments by me will use two semi-colons (;;
), while original comments will only use one (;
).
Whenever possible, any changes to the code are marked by comments to the right that say ;;Fixme was:
followed by the original instructions.
IF $4000>>L_N2&M_N1 <> 0 ;;Fixme was: IFN 4000!>LN2!.MN1
Because we're not using VMS to build this, I made a new file called MAKE.ASM
, based off the original MAKE.COM
batch file. This file loads in all the required source files for {AS} to process and also has defines for enabling debug features.
I chose to change the original source filename extensions from *.SRC to *.ASM because 1) Notepad++ displays syntax highlighting with the *.ASM extension and 2) it makes it easier to identify the rewritten files from the original files.
When I first started rewriting the codebase, the first two macros that I commented out were PUSHORG
/PULLORG
, but now I have implemented them back into the code. Nearly all the source files use these two macros to define the start and stop addresses for that code section.
They were used to hold various ORG
addresses in an internal stack for the programmers as they worked on different sections of code. PUSHORG
is basically just a regular ORG
instruction but is "pushing" the last address off the stack. Conversely, PULLORG
is saving that current address to the stack for a later PUSHORG
.
Before rewriting the macros, I used a standard ORG
instruction for PUSHORG
. If a symbol is next to PULLORG
, then I added a new "<label> SET *
" instruction to mark the new address for that symbol:
;PUSHORG ROMSAVE
ORG ROMSAVE ;;Start code at last ROMSAV address
...
;PULLORG ROMSAVE
ROMSAVE SET * ;;Set current address to ROMSAV
When ORG ROMSAVE
is called again at the beginning of the next assembly file, it will use the new address we previously assigned to ROMSAV
, essentially beginning where we previously left off in the ROM.
The ROUTINE
macro basically handles multiple occurances of symbols. If two symbols with the same name are defined, then a new symbol with a "Z" in front is created and a JMP
instruction to the new symbol is inserted into the location of the old symbol. For example the routine GAMOVER
was first defined by Sam but at a later point in developement, the address for this symbol is used to immediately jump over to ZGAMOVER
(defined by R.J.).
* ROUTINE
* first occurance - creates symbol
* second occurance - types 'REPLACING' message
* first occurance - types 'DUP REPLACE' error message
ROUTINE MACRO N1
BLIST
IFNDEF N1
N1
MESSG " CREATING N1"
ELSE
IFNDEF ZN1
ZN1
MESSG " REPLACING N1"
ELSE
LOCAL
MESSG "DUP REPLACE N1"
ENDIF
.$$ SET *
ORG N1
JMP .$$
ORG .$$
ENDIF
MLIST
ENDM
Because of how Macroassembler {AS} handles macro arguments, an underscore has to be used between the "Z" and the routine label, so in this build ZGAMOVER
is now Z_GAMOVER
.
The problem with this macro is that it doesn't say when this symbol renaming occurs until actually building the code and since no complete listing file exists for the codebase, the only remaining evidence of this renaming occurring can be seen in the old EQU
and SET
files.
PAD
is another macro that gets used a lot to either create padding or reserve memory bytes and by "bookending" those bytes with two new labels: <label>SAV
and <label>LEN
. Unfortunately, this won't work with {AS} without having to change the label names to: <label>_SAV
and <label>_LEN
. While this underscore is acceptable for ROUTINE
since replacing routines doesn't happen too often, PAD
is used more frequently and will require a lot of rewriting to fix mismatching labels with the new underscore character. I chose to not use this macro when new label names are being defined because of this.
The TEXT
and PHRASE
macros are very important as they create the strings of text that are displayed on-screen throughout gameplay.
TEXT 4B,60
PHRASE RED,68,GAME,OVER
To save space, every single word is assigned a Phrase Number and saved in a chunk of ROM called PHRSAV
. Any duplicate words are then automatically eliminated as pre-defined words that are used over and over again just use one reference. The TEXT
macro assigns the screen position of the text while the PHRASE
macro assigns which color and font size to use, as well as creating the strings of text.
This macro was very difficult to troubleshoot and gave me a lot of headaches. In order to get this to work with {AS}, I have to take part of the PHRASE
macro code outside the macro itself and insert it at the end of the routine that initially called the macro. This has to be done everytime new words are defined. I think {AS} wasn't working earlier because the macro is using ORG
and starts messing up the other branches inside the previous routine that called the macro. This workaround is a slightly different way of doing it compared to what the devs did by having the macro do all the work, but this more manual workaround gets the job done regardless.
Here's what this new code looks like and how it works:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ROMSAVE SET * ;; Save the current address
ORG PHRSAV ;; Jump over to PHRSAV to save our pointers
FDB _GAME
FDB _OVER
PHRSAV SET * ;; Mark the new address for PHRSAV to add
;; more phrases later
ORG ROMSAVE ;; Back to our regularly scheduled programming...
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Thanks to the BSO's small symbol table size, several symbols appear in different files with slightly longer names, creating inconsistenties and assembly errors. For example, ROMSAVE
and ROMSAV
are used interchangably in the original code, but this rewrite uses ROMSAVE
exclusively. To keep edits down to a minimum and leave the original longer symbol names untouched, a new file called new_equates.ASM
was created that defines the longer symbol names and matches them up with their shorter counterparts.
SinIndex EQU SinInde
addscore EQU addscor
subpiece EQU subpiec
PiecePtr EQU PiecePt
PieceTbl EQU PieceTb
MAXBOMBS EQU MAXBOMB
MesgTime EQU MesgTim
ScoreAddr EQU ScoreAd
SiniSector EQU SiniSec
AddBombs EQU AddBomb
DCredits EQU DCredit
PlaIndex EQU PlaInde
PlyrAngl EQU PlyrAng
addpiece EQU addpiec
{AS} has some quirks with local labels so I had to redo them. For example, here's what local labels look like for the BSO assembler:
1$ lda lol
jmp 2$
2$ lda lmao
This is what this code would look like rewritten for {AS}:
.1S lda lol
jmp .2S
.2S lda lmao
Sometimes, SECTION/ENDSECTION
are used to make local sections of code, especially when there's lots of routines using local labels.
Every once in a while I have to change local labels into global ones in order for the code to build at all, but I try to avoid this as much as possible.
Note that not all local label changes have been marked with ;;Fixme was:
comments as it would be too many to add and can clutter up the code.
Thankfully, I found some documentation for another missing BSO assembler that explains some of the syntax and expressions used in the original Sinistar source code. Here are some important ones to point out:
UNARY: + Identity
- Negation
> High byte
< Low byte
!N Logical one's complement
BINARY: + Addition
- Subtraction
* Multiplication
/ Division. Any remainder is discarded.
!. Logical AND
!+ Logical OR
!X Logical Exclusive OR
Expressions will be evaluated according to the following operator
precedence, and from left to right when of equal precedence:
1) Unary +, unary -, !N, <, >
2) *, /, !., !+, !X
3) Binary +, binary -
Pseudo- Syntax Condition tested
op
.IF .IF logical expr true
.IF .IF expr expr <> 0
.IFE .IFE expr expr = 0
.IFN .IFN expr expr <> 0
.IFLT .IFLT expr expr < 0
.IFGT .IFGT expr expr > 0
.IFLE .IFLE expr expr <= 0
.IFGE .IFGE expr expr >= 0
.IFDEF .IFDEF sym sym is a defined symbol
.IFNDEF .IFNDEF sym sym is an undefined symbol
.IFB .IFB <string> string is blank
.IFNB .IFNB <string> string is not blank
.IFIDN .IFIDN <str1>,<str2> str1 and str2 are identical
character strings
.IFNIDN .IFNIDN <str1>,<str2> str1 and str2 are not
identical
These conditional pseudo-ops get used a lot so having this guide was extremely important for getting macros to work with Macroassembler {AS}; I'm really lucky to have stumbled across it.
Interestingly, there are a couple of expressions that don't appear here that do show up in the Sinistar and Joust codebases. Here's a snippet of code from Joust as an example:
FCB WAIT,!HCALL,!WCALL,MINUS-*,ZERO-*,PLUS-*,FLYVEL
!H
was used for separating the high byte of a word, while !W
is used for the lower byte of a word. The first one makes an appearance in Sinistar's codebase but !W
is a new one that I haven't encountered before.
RADIX 16
is declared very early on and decimal numbers are defined by using.
after the integer.
NITURRET EQU 8. ;* The number of warrior images
NIWORKER EQU 16. ;* The number of worker images
NIPLSHOT EQU 32. ;* The number of player shot images
NIWASHOT EQU 32. ;* The number of warrior shot images
NISBOMB EQU 3. ;* The number of sinibomb images
These periods have been removed and RADIX 10
is used instead when needed.
At first, I tried changing the RADIX 16
at the very beginning of the code but it created a lot of headaches. Using the RADIX 10
instructions also helps when browsing through the code as it makes it easier to distinguish the hex values from the decimal ones.
- Exclusive OR
!X
are now just!
. - Bit shift operators
!<
and!>
are now<<
and>>
. #!N4
is a value used a lot for fixing a DMA bug for the blitter graphic chip. This value has been replaced with#~$4
.- Binary AND
!.
are now just&
- Binary OR
!+
are now|
*
asterisks were used to denote comments at the start of a new line. These have now have semi-colons in front of them (;*
) to tell the assembler this is a comment.*
is now exclusively used as the current value of the program counter.
This list shows all the files that are needed to build the game (in the order they are first loaded into the assembler, as opposed to {AS} displaying when files are finished processing). A lot of these files have INCLUDE
instructions inside other files, creating nested references which can make things confusing pretty quickly. This map aims to make the code a little bit easier to navigate.
The very first files to be processed through the assembler are routines related to displaying the messages for diagnostic and in-game strings. It is based off of previous code from Joust (but modified to work with vertical monitors). Jack Haeger's pixel fonts also live here and are compressed with macros when assembled. A routine decompresses these fonts and stores them in static RAM ($D000).
- SAM/MESSAGE.ASM (Routines for text output and for compressing/decompressing the 5x7 and 3x5 pixel font tables)
- SAM/MESSEQU1.ASM (Equates for allocating system-critical stuff like RAM, CMOS settings, watchdog, vectors, etc.)
- SAM/MESSEQU.ASM (Message equates for various system/diagnostic strings)
- SAM/MESSEQU2.ASM (Williams Electronics codepage equates)
- SAM/PHRASE.ASM (Strings and vectors for various messages like "INITIAL TESTS INDICATE", "BOOKKEEPING TOTALS", etc.)
- SAM/MESSEQU1.ASM (Equates for allocating system-critical stuff like RAM, CMOS settings, watchdog, vectors, etc.)
- SAM/EQUATES.ASM
- SAM/START.ASM (Sets up 6809 direct page register and sets
RADIX
to 16)- SAM/MACROS.ASM (Macros for assembly counters, pseudo opcodes, RNGs, multitasking, sound calls, and copyright strings)
- WITT/DISPLAY.ASM (Message display macros)
- SAM/MACROS.ASM (Macros for assembly counters, pseudo opcodes, RNGs, multitasking, sound calls, and copyright strings)
- SAM/S1.ASM
- SAM/SAMEQUAT.ASM (Assembly counters, hardware constants, game constants)
- SAM/SAMOFFSE.ASM (Offsets for object/task workspaces, "characteristics descriptors", etc.)
- FALS/N1.ASM
- FALS/N1SYM.ASM (Noah's equates and offsets needed for Sam's module)
- WITT/R1.ASM
- WITT/SYMSAM.ASM (Rich's equates needed for Sam's module)
- SAM/START.ASM (Sets up 6809 direct page register and sets
- SAM/IMAGE.ASM (Nearly all of the sprites are found here;
ROMSAVE
starts after image data)
- SAM/SAMS.ASM
- SAM/S2.ASM
- SAM/SAMRAM.ASM (Ram allocation)
- SAM/GROUND.ASM (end of grounded intelligence lists)
- WITT/TEXT.ASM (Text macro converts strings to Williams codepage and positions on screen)
- SAM/PANEL.ASM (control panel switch vector table)
- SAM/INITALL.ASM (Initialization routines)
- SAM/EXEC.ASM (Executive loop)
- SAM/EXECJNK.ASM (miscellaneous exec stuff)
- SAM/TRASCOM.ASM (dynamic storage 'trash compacting' routines)
- SAM/NEWTUNE.ASM (Sound call routine)
- SAM/PLSHOOT.ASM (player shooting)
- SAM/PIXCHK.ASM (pixel collision check routine)
- SAM/BOUNCE.ASM (bounce routine)
- SAM/ADDSCOR.ASM (player score and sinibomb status display and change)
- SAM/ADDPIEC.ASM (add and subtract sinistar pieces)
- SAM/FRAGEXP.ASM (fragment explosion)
- SAM/SCANNER.ASM (scanner routines)
- SAM/GETOBJ.ASM (screen list routines)
- SAM/DRAWOBJ.ASM (display routines)
- SAM/SLEEP1.ASM (multitasking routines)
- SAM/FUNCTION.ASM (Math functions)
- SAM/TB13.ASM (Utility routines)
- SAM/SAMTABLE.ASM (tables for characteristics descriptors, sound effects, math functions, color palette, etc.)
- SAM/IRQ.ASM (Interrupt routines)
- SAM/S2.ASM
- WITT/RICHS.ASM
- WITT/R2.ASM
- WITT/SYMRICH.ASM (Rich's symbols)
- WITT/RAMRICH.ASM (Ram variables)
- WITT/INIRICH.ASM (Initialization routines for RICH)
- WITT/EMPTY.ASM ("EMPTY" or bombs display)
- WITT/ZAPRTS.ASM (Copyright checking RTS macro)
- WITT/ANISINI.ASM (Animate Sinistar)
- WITT/SPEAK.ASM (Speak macro)
- FALS/SC1.ASM (Speech Tunes)
- WITT/EMPTY.ASM ("EMPTY" or bombs display)
- WITT/DISP.ASM (Message display routines)
- WITT/DISPE.ASM (Message to player erasing)
- WITT/ERASE.ASM (Message erasing intelligence)
- WITT/DISPE.ASM (Message to player erasing)
- WITT/COLLISIO.ASM (Collision effects)
- SAM/COLLIDE.ASM (Collision macros)
- WITT/DEATH.ASM (Player death routine)
- WITT/SUBPART.ASM (Kill a part of the sinistar)
- WITT/COPYRIGH.ASM (EBCDIC copyright)
- WITT/DIFFICUL.ASM (Difficulty factor tables)
- WITT/KRSINI.ASM (Sinistar Killing routine)
- WITT/STBLIMP.ASM (Impulse engine speed table) [Gets patched over by ZSTBLIMP]
- WITT/LEAVESEC.ASM (Leaving sector vectors)
- WITT/LSSBOMB.ASM (Sinibomb leaving sector)
- WITT/LSWOCR.ASM (Worker with crystal leaving sector)
- WITT/ADDPART.ASM (Build up the sinistar)
- WITT/LSSINI.ASM (Sinistar leaving sector)
- WITT/TABLES.ASM (Distance/Velocity tables)
- WITT/STBLSBOM.ASM (Sinibombs)
- WITT/STBLSINI.ASM (Sinistar)
- WITT/STBLOSIN.ASM (New Sinistar orbital approach <<< Added by Noah >>>)
- WITT/STBLMINE.ASM (Warriors mining)
- WITT/STBLL0.ASM (Warriors leading)
- WITT/STBLW0.ASM (Warriors following)
- WITT/STBLW1.ASM (Warriors intercepting)
- WITT/STBLWORK.ASM (Workers circling player)
- WITT/STBLINT.ASM (Workers picking up crystals)
- WITT/STBLHEAV.ASM (Workers delivering crystals)
- WITT/STBLBOMB.ASM (Player on demo bombing run)
- WITT/WORKER.ASM
- WITT/ANIWORK.ASM (Animate worker)
- WITT/DISTANCE.ASM (Distance Computations)
- WITT/GETLVX.ASM (Velocity module for orbits)
- WITT/RETARGET.ASM (Reposition Sinistar to center offset)
- WITT/UPDDTC.ASM (Update Distance to Caller)
- WITT/UPDFLANG.ASM (Update Flight Angle)
- WITT/VELOCITY.ASM (Velocity computations)
- WITT/CHASE.ASM (Adjust a desired speed closer to the velocity of a moving target)
- WITT/LDYWCR.ASM (provides the object's caller's scanner workspace address)
- WITT/WARRIOR.ASM
- WITT/AIMWARR.ASM (Aiming to track moving target)
- WITT/ANIWARR.ASM (Animation)
- WITT/FOLLOW.ASM (Squadron leader targeting)
- WITT/SCREENCH.ASM (On/Off screen check)
- WITT/SHOOT.ASM (Warrior shooting routine)
- WITT/THINK.ASM (Animate/Intelligence check)
- WITT/WARRON.ASM (On Screen routine)
- WITT/WARROFF.ASM (Warrior off screen routine)
- WITT/WASHODDS.ASM (Shooting odds computations)
- WITT/ZWASHODD.ASM
- WITT/SINIBOMB.ASM
- WITT/SINI.ASM
- WITT/STUBS.ASM (To fake Noah's stuff)
- WITT/R2.ASM
- WITT/RICHS2.ASM
- WITT/BUTTON.ASM (Button handling with Easter Egg routine)
- FALS/NOAHS.ASM
- FALS/N2.ASM (Noah's current version release of rmb and src)
- FALS/N1RAM.ASM
- FALS/N1ALL.ASM (Vibration routines, Planetoid/Crystal logic, Calling Intelligence, Killing/Explosion subroutines, Difficulty adjustment code, Population tables)
- FALS/N3.ASM (Final "characteristics descriptors" for all game objects)
- FALS/N2.ASM (Noah's current version release of rmb and src)
- MICA/BOBS.ASM
- MICA/B1.ASM
- MICA/BOBEQUAT.ASM (Warrior/Player Explosion and High Score/Operator Message entry equates)
- MICA/BOBOFFSE.ASM
- MICA/B2.ASM
- MICA/BOBRAM.ASM
- MICA/ZPLXQUE.ASM (Player Explosion Task Queuer)
- MICA/PLXTSK.ASM (Player Explosion Task)
- MICA/ZWRXQUE.ASM (Warrior Exploding-Fragments Task Queuer)
- MICA/WRXTSK.ASM (Warrior Explosion Task)
- MICA/ZSNXQUE.ASM (Sinistar Explosion Task Queuer)
- MICA/SNXTSK.ASM (Sinistar Explosion Task)
- MICA/ZZATTRAC.ASM (High Score To Date/Marquee Pages Task)
- MICA/MARQUEE.ASM (Marquee Page By Ken Lantz and Mike Metz) [Not included unless MarqueeFix is defined]
- MICA/ATTMSGS.ASM (Attract Mode messages)
- MICA/STATUS.ASM (Status Page - Displayed at start of player turn)
- MICA/HSTDTE.ASM (High Score To Date Entry routine)
- MICA/HSTDIM.ASM (High Score Table of initials)
- MICA/ZGAMOVER.ASM (display game over in player window)
- MICA/ZZAMSINI.ASM (Attract Mode Demo)
- MICA/ZPNTSCRN.ASM (clears out the system, sets up the information tasks, restarts the system)
- MICA/B1.ASM
- WITT/AOE.ASM (Final patches for AOE '83 show)
- SAM/SAMFIXES.ASM
- SAM/FIXLSSIN.ASM (fixes live sinistar leaving sector)
- SAM/FIXDAMPD.ASM (fixes player bounce damping during the attract mode demo)
- SAM/FIXSMASH.ASM (fixes player getting smashed off the screen) [not used; replaced by FALS/LAST.ASM]
- SAM/FIXOPENT.ASM (fixes operator entry system initialization)
- SAM/FIXPLUNI.ASM (fixes player starting position)
- WITT/RICHFIXE.ASM
- WITT/FIXBUTTO.ASM (FIREB version editing correction)
- WITT/FIXINIRI.ASM (SINIB demo error and timing correction)
- WITT/FIXKRSIN.ASM (Dead man's warp correction)
- WITT/FIXRISBO.ASM (Value error correction) [for Sinibomb sprite]
- WITT/ZSTBLIMP.ASM (Impulse engine speed table tuned)
- WITT/ZSTBLBOM.ASM (Demo bombing run speed table tuned)
- MICA/BOBFIXES.ASM
- WITT/FIXSINI.ASM
- SAM/SAMFIXES.ASM
- SAM/DIAG.ASM
- SAM/T13.ASM (F000 test rom for 'sinistar' with auditing and adjustments)
- FALS/LAST.ASM (Final patches for "revision 3" rom set)
- WITT/debug_utilities.ASM (Old and new debug routines and cheats, as well as new mods to reduce difficulty)
- SAM/BARGRAPH.ASM (Slightly modified version of Debug Bar Graphs)
- WITT/RICH.EQU (Work file from Rich that has equates for Bar Graphs)
- SAM/BARGRAPH.ASM (Slightly modified version of Debug Bar Graphs)
- MICA/marquee_fix.ASM (This is a hack that restores the original MARQUEE title screen)
A lot of debug code is buried inside the original codebase so mods.ASM
has new defines to enable these again for those that are interested. Use DisableKenChk
if you are not building the last ROM (diagnostic ROM 11), otherwise use FakeChecksums
.
PROMS is on by DEFAULT!
Taken from WITT/RICHFIXE.ASM
During development, a routine in EXECJNK called "VRLOAD" was used for overload handling. If the program is unable to finish processing everything in the executive loop before drawing the next frame on the CRT screen, then the game would get overloaded and slow down would occur.
To immediately signal when a overload occurs, VRLOAD causes the screen to flash white for a frame. This is most noticable whenever the game starts up or transitions to a status screen. In the final game, NOPs are used to patch over the instructions that flash the screen white.
If PROMS is not defined, then the screen flashing returns.
It also disables KENCHK so that copyright protection doesn't trigger during debugging.
Note: This doesn't take affect until AOE.ASM is included, so use DisableKenChk
if the magic byte at address $A1B3 is still showing up as non-zero during attract mode/gameplay.
Moving this from RICHFIXE.ASM was kinda unnecessary as this define is usually left on all the time, but I figured it would be easier to enable/disable it here rather than having it separate from the other debug options.
The problem with PROMS is that it is defined in RICHFIXE.ASM, which is referenced in AOE.ASM. If AOE is not included in the build, then KenChk will still trigger. Enable this to force the copyright protection to stay off no matter what.
This can be useful for when the diagnostic rom is not included in the build.
Taken from SAM/T13.ASM
If you are including the diagnostic ROM 11 in the build, then use this for debugging. This is really important if you want to mess around with the code or work on mods. Also useful for enabling several different mods at once.
During power up, the ROM test uses a checksum table at $F34F to verify file integrity. To make debugging with mods much easier, enable this to zero out the checksum table and cheat the ROM test so that you can gain access to the "Game Adjustment" menu.
Zeroing out the checksums also should prevent the copyright protection from triggering. Look at address $A1B3 to ensure the byte is zero, otherwise the game will start acting weird.
Uncommenting this EQU can be useful for debugging and greatly decreases wait times by skipping the power up ROM/RAM Rug Test. It does not disable the ROM/RAM "Rug" test itself, as it is still accessible by pressing the service (aka "advance") button.
Recommended for invincible cheat
This debug define found in Sam's module allows the player to respawn forever, even if they run out of extra ships. This only changes two bytes in the code and doesn't mess up any symbol addresses. This was originally labeled as "DEBUG" but I renamed it to differentiate from the next two defines which were also called "DEBUG".
Enable this to never run out of lives. This is from Rich's module and while it takes up more space, it increases the player's number of ships upon every Turn initialization so the player never runs out.
This disables player deaths. Warrior shots don't hurt anymore (yay!), but if the player gets caught by the Sinistar, they'll get soft-locked (boo!). This was taken from Rich's module as well.
This new hack makes the player pass through the Sinistar and prevent getting soft-locked while NoDeath is enabled.
Uncomment "Witt" to force the Sinistar to spawn instantly and prevent the warriors from shooting at the player.
This new define enables a previously-unknown sprite edit of the tiny Planetoid image that was used to denote Rich's developmental build from the final ROM.
Several new mods have been added for Sinistar! To enable a mod, open up mods.ASM
and simply remove the semi-colon in front of the define for that mod. Then, save the file and build the game per the build instructions. Be sure to read the instructions next to the defines for further information.
Use "DisableTests" below to make mods possible in Sinistar. Several of the following mods can be combined together (see MOD COMBOS below).
Originally, I had the RAM and ROM tests in ROM 11 ($F09F - $F370) overwritten to fit "MarqueeFix" and "PauseMod" but this doesn't work on real hardware, as we were running into issues with the watchdog chip.
Any new mods are now relocated so that they overwrite the CRT Test Pattern, Color Bars and Switch tests in the diganostics ROM ($F4FB - $F928). To make this space available for adding mods, uncomment the "DisableTests" define.
Again, these mods can be combined with others, however if you are running into "ROM ERROR" messages on power up, then enable "FakeChecksums" to fix this.
To make mods possible for Sinistar, we use the space between addresses $F4FB - $F928 in diagnostic ROM 11. This is where the cross hatch test, color bar tests and switch tests are located. Enable this define to make the diagnostics skip these routines and give us $42C bytes of space to overwrite.
This is already enabled for both MarqueeFix and PauseMod.
To make it easier to identify which ROM set we're running, we'll borrow a trick from Eugene Jarvis and Larry DeMar in the Robotron Tie-Die ROMs and use the high score to denote a "version" number.
Normally, the first high score entry in the "Survivors Today" table is always set to 19045.
We'll change the zero here to ID the mod combo:
- 19145 = Pause Mod / MarqueeFix
- 19245 = Pause Mod / MarqueeFix / DifficultyMod
- 19345 = MarqueeFix / DifficultyMod
- 19445 = Pause Mod / MarqueeFix / DifficultyMod / SAMTAIL
- 19545 = MarqueeFix / DifficultyMod / SAMTAIL
- 19645 = MarqueeFix / SAMTAIL / ExtraShipFix (Closest to "Perfect" ROMs)
Important: 19645 requires a factory reset in order to copy the new default Extra Ship value to NVRAM.
Note: only enabling MarqueeFix doesn't change the high score entries.
19345 and 19545 are great for arcade operators who want to install these mods but prefer not to have players pause the game.
Disclaimer: PauseMod has the potential to cause screen burn-in if the "PAUSED" text is displayed for an extended period of time. I, SynaMax, assume no responsibility or liability if the PauseMod causes burn-in damage to your monitor.
Lastly, some really creative hacking was needed in order to fit SAMTAIL alongside these other mods. If SAMTAIL and MarqueeFix are combined together, then the sound test in the diagnostics ($FE6C) is overwritten and skipped. If SAMTAIL and PauseMod are combined, then the routine that sends a signal to the ROM board LED is overwritten ($F211).
This restores the awesome original "Marquee" title screen found in the prototype AMOA '82 build. Due to space constraints, this was not included in the final build.
To get this to work, I had to overwrite the cross hatch, color bar and switch tests in ROM 11 and then patched ROM 9 to make RJ's attract mode routines load the AMOA graphic.
"DisableTests" is already enabled for this mod. New Checksums for the ROM test are also enabled. Can be combined with "PauseMod" and/or "DifficultyMod" and/or "SAMTAIL" with valid checksums.
Changes ROMs: 9, 11
This reduces the difficulty of the game by modifying the enemy population values starting at $7ABE. You can watch my video for more detailed info on how this mod works and why I chose these new values: https://youtu.be/HnfcAudPPS4
Adds valid checksums for ROM 11.
Changes ROMs: 8, 11
Press the Player 1 button during gameplay to pause! Pressing it again resumes the game. This mod was inspired by the Joust Pause Mod found on Coinoplove.com and uses very similar code to achieve the same effect. The "PAUSED" text displayed on screen uses a routine inspired by Witt's code responsible for drawing the "EMPTY" text at the start of the game.
This mod can be enabled with MarqueeFix! "DisableTests" is already enabled for this mod. New Checksums for the ROM test are also enabled.
Changes ROMs: 4, 10, 11
Taken from SAM/TAIL.SRC, this mod restores a unused jet exhaust "tail" to the player ship!
This code was first discovered back in October 2023, but it wasn't until February 2024 that the unused source code was correctly implemented into the final game.
Changes ROMs: 4, 8, 9, 11
If you enable SAMTAIL by itself then you will need to turn on "FakeChecksums" and "DisableTests", or you will get checksum errors in the ROM test.
This restores the original "Additional Extra Ship Point Factor" to it's original value of 5,000 (per SAM/DEFAULT.SRC). This makes it much easier to score extra lives!
You'll need to do a factory reset or clear/delete your NVRAM in order for the new default value to be copied over.
Because this is just a one-byte edit, this can be combined with other mods like MarqueeFix and/or DifficultyMod.
This mod is kinda not really needed, since you can just change the value in the "Game Adjustments" menu to 5000 and then save.
No valid checksum yet for this mod, enable "FakeChecksums" to pass ROM test
Changes ROMs: 5
This one-byte mod makes it much quicker to edit the title screen's operator message, which can be accessed from the Game Adjustments service menu. The only caveat is that the operator message entry screen and high score entry screen use the same routines, so changing the value to make it go faster also affects the input for high score initials.
I'm assuming that RJ purposely patched this value to make editing slower because play-testers were messing up their high score initials with the shorter time.
No valid checksum yet for this mod, enable "FakeChecksums" to pass ROM test
Changes ROMs: 9
The Bargraph is really cool as it was used during development to monitor several variables during gameplay. This routine is not in the final game and can only be found in the original codebase. It works by drawing several different color bars over the player two section of the HUD/scanner area. Unfortunately, the code is a bit buggy and can cause the game to crash. I'm hoping that the bargraph becomes more stable in the future after some further debugging.
;* Define this symbol to include Graphic Diagnostics
This was originally called "DIAGNOSE" but I renamed it to BargraphEnable to better describe what this does. Defining this enables a debug "BARGRAPH" display that shows different parameters such as Play time in Minutes and Seconds, Warrior Aggression, Elapsed time since player death, number of enemies, etc.
The file "RICH.EQU" has the list of what the different color bars mean but it is inverted. Here is the correct guide for what each bar represents:
rmb 1 * F YELLOW (unused)
rmb 1 * E <SPECIAL EFFECT> BLACK (unused) (The Sinistar's glowing eye color)
GMWaInt rmb 1 * D The # of Intercepting warriors RED
GMWaTail rmb 1 * C The # of Guarding warriors DARK RED
GMWaMine rmb 1 * B The # of Mining warriors DARK PURPLE
GMWaAttack rmb 1 * A The # of Attacking warriors DARK TEAL
GMWaDrift rmb 1 * 9 The # of Drifting warriors BLUE
rmb 1 * 8 Effects BLACK (unused)
rmb 1 * 7 Special BLACK (unused)
GFLANG rmb 1 * 6 Flight angle of squadron leader. BLUE-GRAY
GVelocity rmb 0 * 6 Velocity BLUE-GRAY (unused)
GANANG rmb 1 * 5 Animation angle of squadron leader. GRAY
GDistance rmb 0 * 5 Distance GRAY (unused)
GDeathTime rmb 1 * 4 Time since Player death TAN-GRAY
GAggression rmb 1 * 3 Warrior aggression (high byte) SALMON PINK
GSeconds rmb 1 * 2 and seconds. CREAM
GMinutes rmb 1 * 1 Play time in minutes WHITE
BargraphEnable only works if DisableKenChk is on and that AOE.ASM and DIAG.ASM are not built. Use NOTEST instead of FakeChecksums to skip ROM test.
High score entry doesn't work but you can still insert a coin and hit the player 1 button to start playing again.
In the previous list, two variables are not enabled, "GVelocity" and "GDistance". Instead, "GFLANG" and "GANANG" for the warrior squadron leader are shown in blue-gray and gray colors respectively.
Uncomment this define to have the BARGRAPH routine display the Velocity and Distance parameters instead and disable the squadron leader color bars.
"EnableMods" and "DiagnosticTestFix" are now deprecated. Use "FakeChecksums" and "DisableTests" instead. Any modifications to the final version of the game requires us to either change the checksums in diagnostic ROM 11 or fake them.
Originally, the RAM and ROM tests in ROM 11 ($F09F - $F370) were overwritten to fit "MarqueeFix" and "PauseMod" but this doesn't work on real hardware, as we were running into issues with the watchdog.
Any new mods are now relocated so that they overwrite the "Cross Hatch", Color Bars and Switch tests in the diganostics ROM ($F4FB - $F928). To make this space available for adding mods, uncomment the "DisableTests" define.
These mods can be combined with others, however if you are running into "ROM ERROR" messages on power up, then enable "FakeChecksums" to fix this.
Turn this on if you want to enable mods like the Marquee Fix or Difficulty Mod. This disables the Rug test, just like NOTEST, but this also zeros out the ROMTBL checksum table, so that we don't trigger the copyright protection.
Only works if EnableMods is defined. Restores access to diagnostic tests for CMOS, Sound, Switches and Color bars by skipping the ROM/RAM tests. This is automatically enabled for MarqueeFix. This is needed for any mods that overwrite the RAM/ROM rug test area ($F09F-$F370) and/or before the CMOS test screen at $F404.
When this is enabled, the game will wipe away the screen and wait forever until the "advance" button (aka F2 in MAME) is pressed again. Keep pressing the advance button to go through the remaining diagnostic screens.