(Topic ID: 261103)

Stern Galaxy code disassembly

By slochar

15 days ago

Topic Stats

  • 67 posts
  • 13 Pinsiders participating
  • Latest reply 8 hours ago by Passave
  • Topic is favorited by 20 Pinsiders


Linked Games

  • Galaxy Stern Electronics, 1980

Topic Gallery

There have been 30 images uploaded to this topic. (View topic image gallery).

switch c7r2 ball start (resized).png
switch - raw ball start (resized).png
switch credit button (resized).png
slam-and-tilt (resized).png
switch c0r567 (resized).png
function 51 clear variables (resized).png
function56 add to score q (resized).png
function 4f score directly (resized).png
L1100-switch matrix vector table (resized).png
function 26 switch dispatch (resized).png
reset3final (resized).png
reset2 (resized).png
reset1 (resized).png
blank-stern-lamp-flag-grid-lamps13 (resized).png
fastreact (resized).png

There are 67 posts in this topic. You are on page 2 of 2.
#51 3 days ago
function 4f score directly (resized).png
#52 3 days ago

Here is the heart of all scoring. A score byte consists of a power of 10 in the upper nibble, and a count in the lower of nibble for the # of times to repeat that power of ten. So if you want to add 5000 points, the score byte would be #$35. 10^3=10*10*10=1000, *5=5000 to be added.

Then for each and every score addition, all 3 replay levels are first checked to see if you surpassed them, and then a flag is set for each level, then any levels you haven't already gotten is collected via a clever activation of a virtual switch. The routines pointed to by the virtual switch activation increment an audit for the replay level, and then award a replay. The flags are $3f, $3e, and $3d, for replay levels 1, 2, and 3. Conveniently, the flag bit for each is the same as the activation bit (row).

On the memory map, you can add $0010-0012 PLAYER SCORE RAM, and note that the flags $3d-$3f are for replay levels, and that flag $3c is a score (playfield validation) flag. Also, the first thing that happens in the routine is another virtual switch in column 7 row 0 is activated, this function is to keep track of shoot again/add a balls and turn them off/update them on first score.

Tomorrow, the other score function in the game is explored - the concept of delayed scoring in score queues.

#53 2 days ago

Here is the enqueue score routine. Uses the same score byte format as score immediate, but adds up into a queue for eventual unpacking by the dispatch function (Which really should be called the main loop, as that's pretty much what it is).

New memory locations are the score queues themselves, $0067-006C SCORE QUEUES 1-10-100-1K-10K-100K.

Interesting that there is '1s' queue - this is actually nice as it makes /10 rom programming a lot easier. You can just shift all score bytes' lower nibble down one to make it a /10 rom (well, a basic one.... you still have to massage the match and replay levels. Or, if you need a spare byte, modify the code to never react to the 1's queue and you have a byte back.

Because the score queue listing is so short, the second pic is function $51, clear variables. Just a simple loop to initialize the player score scratch area, the lamps, the flags, and the blink areas. Very similar to function $24, clear play flags, which does the exact same thing except doesn't touch the player score scratch area.

Tomorrow we'll look at a couple of switch functions, which would be the focus of what rom modders would be looking into for gameplay changes.

function56 add to score q (resized).pngfunction 51 clear variables (resized).png
#54 1 day ago
switch c0r567 (resized).pngslam-and-tilt (resized).pngswitch credit button (resized).png
#55 1 day ago

First three switches in the switch matrix (although they are in reverse row order... just the way they did it).

The slam switch is the most straightforward - the function is reboot, and it's so short it doesn't even have an actual pigs routine, it just jumps straight to the 6800 reset vector. Any background sound, etc. playing is handled by the reset, so you don't even have to worry about clearing that first. You'd think they'd have had an audit for slam tilts, but nope, not even that.

Next up is the regular tilts - also pretty straightforward. Kill the flippers, check and set a couple flags, turn on the tilt lamp. You can see here that Stern was slightly unfair to the player, in that they take away any extra balls you have waiting when you tilt! Boo!!

(It's not marked on the code snippet, but likely flag $55 is an extra ball waiting flag, it is on other stern games to indicate you have more than one extra ball, the actual count is a memory location. The flag tells the ball/player advance routines to not do so and decrement the counter instead).

Here's a mod opportunity: remove the two lines lampbvalueoff $55 (to keep the extra ball waiting flag) and lampbvalueoff $28 (to preserve any extra ball you have ready).

A note on making mods: If you're not going to disassemble the entire codebase and whack it into shape to ensure you can reassemble it anywhere in memory (i.e. relocatable) - you must replace any lines you remove with innocuous commands that are the same exact size. PIGS does not include a 'NOP' (No Operation) command. You could repeat the lampbvalueon $33 line twice to replace it, or swap the next 2 lines with them, play_primary_sound XXXX, return - or add in commands that don't actually do anything. Stern themselves used to use enable_solenoid_0f $00 for this function - solenoid $0f does not decode to a real solenoid on the driver board, so it's used effectively as a 2 byte NOP. (Stern uses it when there is more than one solenoid to fire in a row to separate them - because the solenoid routine in a pigs script will wait for the solenoid timer to be free before it will add the next one.)

Next is the longish-credit button routine, which is relatively straightforward as well:

Check for credits. If none, return
You have credits. If it's game over, start a new game.
You have credits. It's not game over. Check if on ball one. If not, start a new game.
You have credits. It's not game over. You're on ball one. Check if # of players=4. If not, add a player, otherwise return.

Starting a new game initializes several values, sets up player 1's initial playfield state (in lamps and flags), then saves this template in all 4 players' save locations (even if you are only playing a 1 player game). This saves rom space to do this since you don't have to have logic when you add a player to determine which player to then set up (you'd have to save the current player anyway, so just do it up front before any scoring or state change happens).

The last part of the function uses a virtual action column to actually launch the ball and reset drop banks, or do anything that needs to be done ball-to-ball. We'll look at that routine tomorrow.

Here's a preview of the code, you can see it's not real 6800 code - all switch routines, real, timed, or virtual always start in PIGS automatically with the multiprocessing flag set. If you want to write a routine in 6800, you have to have 'ila' (in-line assembly) as the first command or it just won't work. You can also see that disassembling a pigs game is very much a manual process.

switch - raw ball start (resized).png
#56 1 day ago

Do you ever use DASMx to try and flush out most of the pure assembler code?

#57 1 day ago
Quoted from Quench:

Do you ever use DASMx to try and flush out most of the pure assembler code?

Nope, too interspersed with the PIGS code. I know you can setup templates, etc. to handle most of this, but like I said way back at the beginning, this is just the way I do it.... I've contemplated modifying DASM source to spit out the macros directly, but the debugging cycle would be too long for me.

Doing it completely manually helps me in another way too as I've semi-memorized all the opcodes for PIGS and can just look at the raw rom dump and sometimes understand what's going on without even disassembling it.

#58 1 day ago
Quoted from slochar:

Nope, too interspersed with the PIGS code.

Hmm, I see.
Besides the "game personality" code, do you find there can be a lot of system code comments that's fairly easily copy'n'pasted between games when you're documenting them?

#59 1 day ago
Quoted from Quench:

Hmm, I see.
Besides the "game personality" code, do you find there can be a lot of system code comments that's fairly easily copy'n'pasted between games when you're documenting them?

Yes, how do you think I've been zooming along on this

I think the system code is about 1100 bytes or so, so they're going to be extremely similar between games (if not exactly the same, other than the branch locations) - I do wish Stern had continued to copy bally and have an OS system rom that didn't change for a couple games, if they'd had that, I'd probably be done with the all games already.....

#60 1 day ago

I been trying to follow along, But got hung up on post #4 with the changes and more particular with the L00 thing, Wouldnt you have to change this back at some point to be per code?...Anyway this Princess is struggling to keep the dream alive, Where would the understanding begin in your opinion, Assembly or the PIGS?

#61 1 day ago

Love this stuff, way before my time but find it fascinating!! Wish I was around in the days of assembler and roms you get a real understanding of the hardware and how it all works not like today where device drivers hide it all away

#62 1 day ago
Quoted from Passave:

I been trying to follow along, But got hung up on post #4 with the changes and more particular with the L00 thing, Wouldnt you have to change this back at some point to be per code?...Anyway this Princess is struggling to keep the dream alive, Where would the understanding begin in your opinion, Assembly or the PIGS?

6800 assembler lets you do a jump to a routine that's located in an index register (in this case X) - so jmp 0,x (and jsr 0.x) just means to JUMP to the address located in X. You can also do a jump to an offset from X, so if X is set to #$1000 and you do a jump 2,x it will actually jump to $1002.

The correction of L00,x is to correct when we changed all the branching instructions from absolute values (i.e. bra $1234) to a value that the assembler can relocate if needed (bra L1234) - when we reassemble the reconstituted source code, it will become bra $1234 again, assuming that all the code reassembles in the correct place. This is also why I change absolute values to branches, because you can look at the assembler output and make sure all the bits end up back in the same place based on the label (L1234).

You need to understand 6800 first before trying to understand PIGS.... it's a building process. I only knew a smattering of 6502 assembly back in the 80s but I learned pretty quickly the differences between 6502 and 6800 (the 6502 was created as a direct competitor to the 6800, and it does some things better.... but it does some things worse. I like the 6809 for overall efficiency and wish that a 6809 could drop into a stern board and work..... it's so much more powerful.)

For instance, if you wanted to write an mpu200 game from scratch, you could only know the PIGS command ILA to return to assembly, and happily write your entire game in 6800 if you wanted. Then it would be closer to an mpu100 or bally game. The power of pigs comes with being able to do functions specific to pinball programming with one command - show_hstd instead of jsr LHSTDROUTINE is the difference.

The learning curve can be steep as there's not really a "hello world" type of thing on a pinball (well, flashing the LED would be it, I guess). As point of fact some of the first things I did was add elaborate attract modes to games like Hot Hand and Trident, because the results were visible immediately.

#63 1 day ago

This is going to get ugly, But I do understand the linear of what you are saying, and gives me direction...Thanks.

#64 18 hours ago

It might be worth as you expose more PIGS command functions that you add them to your first post as a list so there's a central quick reference?
Maybe also the use of RAM locations as you determine what they're for.

#65 14 hours ago
switch c7r2 ball start (resized).png
#66 14 hours ago

Here's the ball start routine. It's actually the end of the outhole routine, but at this point, it's been launched by the virtual switch entry point instead of as the end of the outhole.

The logic flow:

Restore the currently up player, make sure the correct info is on the displays. Increase the ball count audit.

Setup the bonus ladder correctly. No carryover on Galaxy (another mod-portunity?).

The routine at L546D handles some flags for the progressive spotting feature of the inlanes, based on the achieved bonus x. We'll not look at that yet.

Test to see if you're on the last ball - if so, show the HSTD. (You can see Stern using the solenoid 0f here, as a delay... they have an actual delay function that they never seem to use!)

Now, clear and setup some lamp values to ensure the ball is ready to go in the correct state. You can write in the flags here on the lamp/flag spreadsheet as ?unknown, during ball launch for decoding later.

A note about the 'loadb $b4' line - this line doesn't make any sense, B is set to $61 at this point (from the previous line) and then it gets reset to $7d in the next line (or if not there, it gets reset to either $51 or $3c....)

I think this line is a leftover programmer fudge factor, either the $b4 is a checksum correction, which doesn't affect anything in the program, or there was some other code underlying this section that got changed for some reason and this is what they stuck/left in there to make up the space. Either way, in a full on disassembly/reassembly, this is a line I'd comment out because it's not needed and saves 2 bytes.

After resetting the 4 bank drop targets, the flags for the drop targets are checked and the solenoids activated for each. As each is dropped, the switch routines for each drop will run, but because the flags are already set, no scoring will take place. Here's some more use of enable_solenoid_0f as delays, for the drops to drop in a stately fashion. The delay of $1e could be shortened considerably and would be a mod I'd consider making but it falls under the "just because it's cool" category to see the drops zoom down quickly.

For subroutines that I don't know what they do yet, I just put ?? so that I can search later on once I know what they do to fill it in - I'll put a speculative guess based on the surrounding code like I've done here with the drop bank.

Tomorrow, more of the switch matrix routines.

#67 8 hours ago

There is is...That code patch I bet, was that free game warp hole Special, Triggered by dropping targets in order...Why it was removed I would imagine, it would stay on for the whole ball, and a good player could basically achieve unlimited games and play that machine all afternoon, with 1 quarter. (Wink)

Promoted items from the Pinside Marketplace
$ 7.00
From: $ 14.00
Third Coast Pinball
Machine - For Sale
Massillon, OH
Machine - Wanted
Cortland, NY
From: $ 140.00
Machine - Wanted
Utica, MI
From: $ 45.00
There are 67 posts in this topic. You are on page 2 of 2.

Hey there! Got a moment?

Great to see you're enjoying Pinside! Did you know Pinside is able to run thanks to donations from our visitors? Please donate to Pinside, support the site and get anext to your username to show for it! Donate to Pinside