don't click here

ASM Spinball disassembly

Discussion in 'Engineering & Reverse Engineering' started by Andlabs, Oct 1, 2010.

  1. Andlabs

    Andlabs

    「いっきまーす」 Wiki Sysop
    2,175
    1
    0
    Writing my own MD/Genesis sound driver :D
    Yeah nothing much to say here, just got bored and left it sitting until now (lol commit #200). Enjoy!
     
  2. Ravenfreak

    Ravenfreak

    2 Edgy 4 U Tech Member
    3,155
    239
    43
    O'Fallon Mo
    Hacking Sonic Drift
    Even if it's small, I downloaded it since I've been wanting to hack Sonic Spinball, but all I could do was hack the ASCII letters used for the messages that scroll in the HUD using a Hex editor. :v: (That and I got bored looking at hex values for a long time and trying to figure out what did what, and even after switching a few bytes around I never noticed a difference. Well once I did edit Lava Powerhouse's music, but meh.) I jotted down a few notes in the past, this is what I found. (I dunno if this will help, but it may help someone. Not much is here btw.)
    Code (Text):
    1. $BE340-$BFCAF ACII Text- Unlike other Sonic games, messages on the HUD,credits, and options text are all in ASCII text and thus is easier to edit.
    2. $B7B2E-Lava Powerhouse (I'm not too sure on this one, I edited a bit and the music did change slightly. But it's been about a year since I tested it. :\)
     
  3. Andlabs

    Andlabs

    「いっきまーす」 Wiki Sysop
    2,175
    1
    0
    Writing my own MD/Genesis sound driver :D
    If you want to edit the music, this and this will help you (though in the disassembly I put up, the music locations are somewhat different... but they're close).
     
  4. GenesisFan64

    GenesisFan64

    The bright side of the dark side. Member
    108
    0
    16
    The sound data locations from this topic are actually wrong... (The Z80 driver is ok)

    it should be:
    Patch: $0AA0B0 - $0AB4AB
    Modulator: $0AB4AB - $0AB502
    Sequences: $0AB502 - $0B39DD
    Samples: $0B39DD - $0BDD2E

    Here's the correct data: (BIN and ASM files)
    Download
     
  5. evilhamwizard

    evilhamwizard

    Researcher
    1,393
    468
    63
    While we're on the topic of music (but not exactly related to the dissasembly of the game), just wanted to let you know that the port of the game to mobile phone seems to be using the original MIDI files for some the sound/music (OR NOT FFFFFFFFFFFFFFFFF). And since the game was ported from the original C source code, they left a lot of other files from the original game in here as well.

    Of course, you'll want to find the port for yourself, but it shouldn't be hard to find. :P
     
  6. Wafer

    Wafer

    Find me on Twitter instead Member
    255
    75
    28
    Apologies if this is necro-ing, but here's that disassembly again, only in .asm format and fixed up to build in asm68k. Thanks to Clownacy and Neo for pointing me in the right direction getting the PC-relative instructions working, and to Andlabs for providing the original .idb. I've sent a PR against the SR repo.

    Here's some more info from the readme:

     
  7. MEGAGEN

    MEGAGEN

    Level 3
    20
    0
    0
    England
    Optimizing Sonic Franchise
    Hello.

    Would be truly amazing to see Sonic Spinball running 60FPS instead of 30.

    That would be brilliant, maybe one day.

    Brilliant work on the disassembly.
     
  8. Scrambled Eggman

    Scrambled Eggman

    Worm Bagged Member
    14
    27
    13
    Picking at Sonic Spinball Disassembly
    @Wafer: I'm starting to have a poke around the disassembly and the game to begin documenting anything of interest that I can find. As there's no real home for Sonic Spinball hacking on this site yet (genuine shock).

    Are there any ground rules you have for making edits to the asm? i.e. comments/label changes. I'm branching for now locally for my own purposes, but stuff like naming conventions, comment styling etc. would be good to know... assuming you even feel you need to even take charge on that anyway. :P
     
  9. Wafer

    Wafer

    Find me on Twitter instead Member
    255
    75
    28
    I guess this thread IS the real home? :)
    The overwhelming majority of the disassembly work was by Andlabs, I just copy-pasted it out of IDA, included the align macro and a modified build script from Sonic 1, and fixed the addressing issues with some semi-automated Python brute-force. So for my sake, you should feel free to leave your mark in comments and labels. Clownacy literally commented his approval on my PR only hours before you posted, so you can hold off until a maintainer pulls it, or make PRs against me and I'll happily upstream them for you.

    The only insight I can really offer on the actual code is that ReadJoypads is only where the pads are read in the title screen. During actual gameplay the pads mainly get read in loc_D3D9E, maybe a few other places but I'm not sure what they're for.
     
  10. Scrambled Eggman

    Scrambled Eggman

    Worm Bagged Member
    14
    27
    13
    Picking at Sonic Spinball Disassembly
    Alright fair. I'll see about pushing to my own branch in your repo and we can go from there.

    I've found the player input mask gets dumped to $FF0005 at pretty much all times except for the main menu and intro cutscene. Curiously the attract mode in Toxic Caves continues to poll to this address however.

    So far I've determined where the cheat codes are stored, and where abouts in the code they are processed (labelled appropriately in the updated asm on the repo). Due to the nature of it being compiled C, for whatever reason the Level Select code uses a global location ($FF5750) for counting the number of successful entries into the cheat code, yet the credits cheat code seems to track the count via an address register (Which seems to always point to $FFEDD0 during the options menu). I should be able to follow this code backwards ultimately and learn how the options menu is managed, as well as the main menu as it should be polling input to determine which level to start when the level select byte is flagged as active.

    I'm currently in the process of dissecting the player class struct, which I have confirmed to be 76 bytes... based on that there is an array of 4 instances due to supporting 4 players (and just working out the spacing between 2 common attributes). Once I am able to determine the root offset of this array, it should be possible to track down any calling code that modifies or reads the player data which will be a useful step forward. Curiously it appears to not only keep player-specific data, but also data relevant to only the active player, such as coordinates, velocity etc... things that you would not expect to need to be instantiated.

    Anyway I will start pushing to the git from now and pop occasional digests here if I discover anything that needs shouting about. :)
     
  11. Scrambled Eggman

    Scrambled Eggman

    Worm Bagged Member
    14
    27
    13
    Picking at Sonic Spinball Disassembly
    Since I don't currently have permissions to submit to the git yet, I'll pop here what I have so far. I do have ASM notes regarding the level select, but that'll need to go into the git repo.

    EDIT: Corrected player array root address, should be 5758 not 7758.
    Player Data Struct

    I've been able to dissect a decent amount of the player struct so far. Not quite everything, that I have found, makes complete sense yet; but hopefully these initial findings might encourage some more investigation from others too.

    I've also found what appears to be a text data buffer for the HUD messages. Here's a some of the data I've poked out of it so far. It's worth noting that there seems to be multiple buffers that can be used (as you can see some of the other strings in the memory editor in the gif below). Only certain messages seem to make use of the additional buffers from what I can tell so far.

    Text Buffer #1 Attributes (tinkered with so far)
    Code (Text):
    1. $FF55AF - Message Colour : $00 - Invisible, $01 - Flat Green, $02 - Flat Red, $03 - Flat Cyan, $04 - Flat Yellow, $05 - Rainbow,  $06 - Red/Yellow Gradient, $07 - Green Yellow Gradient.
    2. ;Values above $07 tend to create weird and wonderful colour combinations, including black text and partially filled versions of these colours; and even colour combos not seen in game normally.
    3. $FF55B3 - Message Animation Mode : $01 - Flashing, $02 - Palette Cycling, $03 - Static. Anything not $03 will cause the timer to count down
    4. $FF55B8 - word - Countdown for hud text animations. Once it reaches 0, the text buffer always resets to colour setting $04 and plays a vertical "uncover" animation.  
    [​IMG]

    I specifically called this out as a buffer, as I'm pretty sure this is used temporarily to generate the text glyphs that are actually sent to the VDP. The proof of this is that this buffer is also used for the Options screen. Whenever you change an options, the last option that you change always appears in the buffer in the memory viewer. If you change the control config, it usually shows the bottom bit of text (as it will have been processed last). It appears that it uses all the same parameters too (Note that the colour below is $06 which is the gradient red/yellow) so theoretically you could change the colour styling of the options menu by tinkering with this buffer, and potentially animate things.

    This buffer seems to be polled in-game, but in the options menu it seems to be event-driven as to when it is read in and the glyphs rendered.

    [​IMG]
     
  12. Wafer

    Wafer

    Find me on Twitter instead Member
    255
    75
    28
    Nice find! By coincidence, I found myself building a very similar system only last week for my current project. With non-baked text that can move or animate, keeping it in a buffer and then changing the parameters as you play it back out to the VDP seems much faster than rendering it all again.

    If some hypothetical future hacker was going to try and optimize the engine, they'd probably go ahead and bake the strings into something closer to the VDP format at the build stage, IIRC Sonic Team did it this way for eg. zone title cards.
     
  13. Scrambled Eggman

    Scrambled Eggman

    Worm Bagged Member
    14
    27
    13
    Picking at Sonic Spinball Disassembly
    Yeah this seems quite plausible, although it depends on how the data is submitted. In-game the buffer polls the text for data such as the timer and animation mode; as well as updated text that comes in from events such as Bagged-Worms etc. One to follow up for sure.

    Also I can confirm my suspicions for the options menu text by messing around with patch codes in Gens. The interesting thing however is that the colour code affects ALL the text on screen even though the buffer seemingly appears to only deal with the modified text. This leads me to believe that all of the text rendered using this method either uses only a single shared memory location for text attributes, or all of the text gets refreshed with the buffer data (seems unlikely based on the text that is seen in the buffer).

    [​IMG]
     
  14. kazblox

    kazblox

    Member
    178
    27
    28
    Diassemblies and decompilations.
    Ghidra shows that this is a combination of assembly and C. The game was likely built with an early version of Sierra C; NOT the one on the Sega Channel disc from Hidden Palace, for sure.
     
  15. kazblox

    kazblox

    Member
    178
    27
    28
    Diassemblies and decompilations.
    I solved the memory/address/IO access problem. Sonic Spinball used structs for a variety of accesses, like every sane C program. However, the only known version of Sierra C that I have likes to optimally avoid clashing the first scratch register, d0, with the return register.... which is also d0.

    With my version of Sierra C, this decompilation of function $D6796 is exactly equivalent to the original, but the recompiled function d0 has strictly reserved for returns. Thus, scratch register use is strictly allocated to d1 and d2 and the recompiled function does not match. The original function allocates the return register to d0 while also allocating scratch register use to d0 and d1. Therefore, I still need an early version of Sierra C...
     
  16. CrazyTerabyte

    CrazyTerabyte

    Member
    9
    0
    1
    I just wanted to mention a little known fact… Sonic Spinball was ported to J2ME and was available to Java-capable phones. Thus, a decompilation of the J2ME Spinball game may help with the 16-bit disassembly. Or may help in producing an equivalent high-level code (e.g. in C) for the game logic.

    I couldn't find any mention of the J2ME version on the wiki, and there aren't many threads here for J2ME games (this one about Sonic 1 Java is relevant). Thus, I'm commenting here just to raise awareness, and as a hint to anyone who wants to decompile/disassemble Sonic Spinball any further.
     
    • Informative Informative x 1
    • List
  17. Scrambled Eggman

    Scrambled Eggman

    Worm Bagged Member
    14
    27
    13
    Picking at Sonic Spinball Disassembly
    I've able to come back to this in the past month or so and wish to share some progress (I didn't get to look at for very long after my original postings because a lot happened shortly after, including COVID-19/Quarantine!).

    In this short time have been able to make significant progress in my understanding of the code structure and behaviour of a lot of the systems. There is a heck of a long way to go still, but I hope that sharing some quick demos of small hacks, to demonstrate actual understanding of the code, may serve as a sign of life for anyone else who may be quietly picking away at the disassembly in isolation to come forward.

    Tools/Documentation
    Spinball has no pages or structures for sharing and documenting findings. Nor which tools should be used, and how best to share data from said tools. I'd be tempted to spin up a separate thread to discuss this properly, as I would like to be able to share knowledge in a way that fits within the preferred ways of working around here. This is especially relevant as I've been using Ghidra to do the majority of the exploration of the code, as I don't have access to IDA Pro (which the current ASM and submitted disassembly data was generated using)

    I forked the spindisasm git to my own private gitlab, but I would like to look to tidy it up so it's suitable for pulling back to the main spindisasm repo on github.
    It's located here: https://gitlab.com/Eggman891/spinballdisassembly
    I'd feel best refining it before making it public or submitting a pull request, since I've not reviewed the readme or licenses, nor what peoples' preferred tools or documentation methods are. So please DM me or reply here if you wish to help me out with that.

    Hacks

    Sound Test
    Further to my tinkering from a few years ago, I've been able to shim in a Sound Test option that sits in place of the Music option using a cheeky branch on the Options loop. I believe I have enough info to add an additional row to this screen, however I've not fully understood the bridge between the OSD message queue system, and the options screen. I believe it simply tweaks the offset where it is rendered in the VDP, then blits over the previous option. I accidentally corrupted this at one point and had it offsetting by -8px every time I decremented the sound test counter!


    Video of the Sound Test working,. Left/Right to change back, C button to play bank.

    Hacks to optimise frame rate
    To search for where Sonic Spinball's performance issues are, I located the update loops that process the animated game objects, and the sprite rendering instances. For these demo I reduced the number from 256 to 16 (however 32 also gives similar performance).

    In doing so, the game is able to run significantly faster . In The Machine, the game can almost consistently hit 60fps, and in Showdown (Level 4) it is significantly faster and can sometimes touch 60fps, such as when in space, or at the flippers at the left/right edges of the level. The remaining major performance losses are likely related to the collision detection with triggers and tiles, as the frame drops (which are now much more noticeable) occur in busy areas with lots of chutes or bumpers.

    Objects that are not visible, but that would normally be collided with, remain functional despite not rendering correctly. This appears to demonstrate that collision and physical object behaviour is decoupled form the sprite rendering behaviour.


    Demo of optimisations on The Machine


    Demo of optimisations on Showdown


    Longplay video to show the performance comparisons.
    The Machine timestamped @ 19:02.
    Showdown timestamped @ 29:53


    Timestamped links for the longplay video

    youtube.com/watch?v=4cOvlRwmlKk&t=1793s
    youtube.com/watch?v=4cOvlRwmlKk&t=1142s
     
  18. Overlord

    Overlord

    Now playable in Smash Bros Ultimate Moderator
    19,440
    1,063
    93
    Long-term happiness
    Any chance of sharing the Sound Test ROM?
     
  19. Scrambled Eggman

    Scrambled Eggman

    Worm Bagged Member
    14
    27
    13
    Picking at Sonic Spinball Disassembly
    Here you go. I'd maybe look into making the options screen easier to maintain later down the line - perhaps by supporting scrolling of menu items - so we can have multiple tweakers available for customising gameplay, when there are more features to juggle.

    Instructions
    * Left/Right to toggle banks
    * C-button to play the current bank

    Advisories:
    * Checksum is incorrect (I've not looked into how to fix this up yet, but afaik most emulators don't seem to care)
    * The "Sound Test" option is shimmed on top of the Music toggle. So switching sound bank will also trigger a toggle of the music setting. This only affects when you leave and re-enter the options menu however (and the sound test skips the global flag for the music setting anyway)
    EDIT: Additional note
    * It will always stop all sounds before playing the next. There's no distinction between music or SFX. The GEMS driver seemed a bit sensitive when throwing music at it without stopping the previous one. You might even notice that some music plays differently depending on what you play beforehand (7E/7F even more so since it's corrupted hellscape)

    EDIT2: Little tidbit, for fun. The sonic sprite in the options menu is a fully functioning animated game object, complete with state machine.

    upload_2024-10-21_0-12-49.png
     

    Attached Files:

    Last edited: Oct 21, 2024
    • Informative Informative x 2
    • Like Like x 1
    • List
  20. Ravenfreak

    Ravenfreak

    2 Edgy 4 U Tech Member
    3,155
    239
    43
    O'Fallon Mo
    Hacking Sonic Drift
    There's a checksum fixer tool that was released in 2003 that can fix the checksum btw. It's on Romhacking.net, just google "Genesis Checksum fixer" and you'll find it. I ran your hack through the tool and it worked flawlessly. I can't wait to hear the glitched music. xD I look forward to seeing what you do with Spinball!