M68k Bodging (Who gave this cat a keyboard?)

Post about your games or other projects here!
Post Reply
User avatar
VAdaPEGA
Fox Pal
Posts: 29
Joined: Tue Oct 17, 2023 10:23 pm
Pronouns:

any

Flags:

:flag_asexual:

M68k Bodging (Who gave this cat a keyboard?)

Post by VAdaPEGA »

Ey, so you know the term "programmer art"? The kind of art usually to explain a concept or as placeholder that sometimes ends up in the final as is anyway?

Welcome to "artist code" where things don't line up but somehow it all still works???



(also will be posting explanations of intricate dumb things here some time from past and current works so I don't have to spam Discord servers with it)

User avatar
VAdaPEGA
Fox Pal
Posts: 29
Joined: Tue Oct 17, 2023 10:23 pm
Pronouns:

any

Flags:

:flag_asexual:

Re: M68k Bodging (Who gave this cat a keyboard?)

Post by VAdaPEGA »

So here's an effect anyone can do at home (click to see animation):

GIF 10-08-2023 23-07-16.gif

Don't fade the bright colours and swap sprites, easy.

gatohighlight.PNG
gatohighlight.PNG (11.33 KiB) Viewed 21930 times
User avatar
Jess
Site Owner
Posts: 294
Joined: Sun Oct 15, 2023 8:48 pm
Name: Jess
Title: Game Developer
Pronouns:

She/Her

Flags:

:flag_trans: :flag_demisexual: :flag_pansexual:

Status: on the "internet"

Re: M68k Bodging (Who gave this cat a keyboard?)

Post by Jess »

I still really like that fadeout effect, it's quite nice

We are Roxy, Mika, Ashe, and Willow. We own the place. Website Discord
ImageImageImageImageImageImage

User avatar
VAdaPEGA
Fox Pal
Posts: 29
Joined: Tue Oct 17, 2023 10:23 pm
Pronouns:

any

Flags:

:flag_asexual:

Re: M68k Bodging (Who gave this cat a keyboard?)

Post by VAdaPEGA »

nomorejumplag.gif
nomorejumplag.gif (64.59 KiB) Viewed 21781 times

In the original game, there is 1 frame of movement lag every time you jump.
This isn't because jumping is a heavy task, but because it skips over the rest of the player's code on a successful jump via a "addq.l #4,sp" (add to stack pointer, essencially forgetting the return point).
I decided to change the line to a "move.l #SpeedToPos,(sp)" so that it applies momentum the same frame, removing the stutter.

(More accurately, it should've been #ObjectFall to apply gravity, but I'm keeping it this way. Enjoy the extra jump height~)

User avatar
VAdaPEGA
Fox Pal
Posts: 29
Joined: Tue Oct 17, 2023 10:23 pm
Pronouns:

any

Flags:

:flag_asexual:

Re: M68k Bodging (Who gave this cat a keyboard?)

Post by VAdaPEGA »

So one thing I had happen to me was this funny little happenstance:

2023-12-07_loveinvalidDPLC.gif
2023-12-07_loveinvalidDPLC.gif (1.87 MiB) Viewed 21718 times

As you can see... everything went horribly wrong... and it wasn't entirely my fault!

Two things happened :

  • I grabbed the DPLC (Dynamic Pattern load Cues) code directly from S3K for convenience without reviewing it properly... turns out it doesn't account for blank frames, so it ends up loading 256 cues of garbage data, resulting in a explosion of garble... which then resumes flawlessly afterwards (you can still somewhat see the text going "classic Tomy" in the gif)
  • The default animation routine for the trilogy only allow for 32 frames max due to the following format:
    • FVH# ####
      F : Flag
      V : Vertical flip
      H : Horizontal flip
      # : Frame number
  • When it reached sprite frame 32, it wrapped back to 0.

My fix? Made an alternate routine for longer animations and checked for frame 0 in the DPLC code.

User avatar
VAdaPEGA
Fox Pal
Posts: 29
Joined: Tue Oct 17, 2023 10:23 pm
Pronouns:

any

Flags:

:flag_asexual:

Re: M68k Bodging (Who gave this cat a keyboard?)

Post by VAdaPEGA »

So I was bored one day and decided to look into S&K's Lock-on feature and looked into how KtEiS2 communicates with S2
Here's how it all works:

  • When a game smaller than 2MiB is locked on to S&K, it gets mirrored to the upper 2MiB of the address space
  • S&K, after checking for the SEGA string in the header, looks for a set of serial codes, S3 and a few revisions of S2
  • If S2 is detected, $A130F1 is set to 1, enabling the UPMEM of S&K to be visible, where the KtEiS2 code resides at the upper 3MiB
  • S&K then jumps to the UPMEM where it initializes the game and runs code from there, only using S2 when assets are required

However, during that initialization part, the game does something interesting: It jumps directly to the S2 ROM to load the Sound Driver

So I had the following idea:

  • With a game bigger than 2MiB, only the upper 2MiB are visible to S&K, meaning one can add a fake header so the game detects it as S2
  • When it jumps to the Sound Driver load code, it will instead execute any arbitrary code I chose to, meaning I can essencially do what KtEiS2 does but on S&K.

Guess what, it works

2024-01-23.gif
2024-01-23.gif (5.93 MiB) Viewed 11066 times

It just comes with one problem :
Since $A130F1 is also used for switching to SRAM, it can potentially make the exploit not function at all, but this depends on how the cartridge developer does SRAM (unfortunately there's no good way to test this since no good modern cartridges with SRAM support exist that work with S&K)
My plan is to have this as an extra when Gatoslip is attached and naturally, an RPG benefits from a save feature, meaning this can potentially be a problem.

There is a different exploit found by Hachelle-Bee that instead exploits how S3&K loads S3's SEGA screen:
instead of it just decompressing the art to RAM, one can simply have it continuously write to RAM until it reaches the Stack, where one can add a jump to the arbitrary code they want to execute.
This is a less elegant solution and costs some extra space for the compressed part but is in theory more compatible since $A130F1 isn't messed with at all.

User avatar
VAdaPEGA
Fox Pal
Posts: 29
Joined: Tue Oct 17, 2023 10:23 pm
Pronouns:

any

Flags:

:flag_asexual:

Re: M68k Bodging (Who gave this cat a keyboard?)

Post by VAdaPEGA »

hmm.gif
hmm.gif (79.77 KiB) Viewed 9634 times

Now, I'm absolutely stupid when it comes to menu stuff but one thing I've managed to get right is the cursor moving to a new position smoothly.
The gif is from S1Mousealog but it's a simplified copy from Gatoslip's battle menu with an added second X position parameter.

Ovals2.png

Here's the silly pre-calculated set of positions. Each row has 3 values with 2 bytes each (6 bytes per row, 30 bytes in total)

Ovals1.png

And here is that wacky 68k code, the commented part at the top would've defaulted the position to the bottom left corner of the screen, which isn't necessary for this case.

First we load the position table at address register a1.
We'll want to offset this table to the correct position of the menu, so we fetch the value of the internal vertical option (which is a number between 0 and 2) and store it on data register d2.
Since the instruction messes with the condition code register (CCR), we won't have to add a compare or test instruction, we can have a conditional branch right after (this happens a lot on the 68k for optimal code). In this case we use it to check if we're on position 0 on the menu and only branch to a later part of the code if it's not 0.
If the position is 0, then we use the internal horizontal option instead, overwritting what was previously on d2. On top of that, we add 3*6 to the position so we start at the 3rd row on the table.

Now theoretically (and this is the case in Gatoslip's version of the code!) I could've just used one value to represent the current menu position rather than 2 for horizontal and vertical positions... honestly I don't got any excuse for why I did it this way, like I'd said, I'm stupid with menu stuff.

Next we have an unreasonable ammount of instructions just to multiply d2 by 6, but as it turns out, the M68k's multiplication and division instructions are super costly so we want to avoid those.

We now add d2 to a1, which'll offset the address to the correct row of position values from the table, from there we wastefully move the values to data registers d0 through d5 (we could've avoided using so many data registers by fetching them later in the code when necessary and maybe even do a simple loop with another table to make the code smaller, didn't think of that at the time x.x)

We then have what's essentially the following code three times in a row for each axis :
MenuPosition = MenuPosition + (NewMenuPosition - MenuPosition / 4)
if "MenuPosition>>2" happens to be 0, then it'll snap to the final position.

.... dang it I should've made a post about the mouse peripheral instead, this tangent is stupid.

User avatar
VAdaPEGA
Fox Pal
Posts: 29
Joined: Tue Oct 17, 2023 10:23 pm
Pronouns:

any

Flags:

:flag_asexual:

Re: M68k Bodging (Who gave this cat a keyboard?)

Post by VAdaPEGA »

https://chitter.xyz/@VAdaPEGA/112264114876971292
So as it turns out, the entirity of the sound driver is loaded in Z80 RAM, which makes it almost trivial to add custom songs to S&K while locked on to a different game.

coolimage.PNG

It's a little silly but essentially, we have to write the offset within the Z80 address space and ROM bank of the Music to Z80 RAM... and that's it, it already supported this from the get go due to the need to read music from S3's cartridge for S3&K and generally because of how little the Z80 can see at a time (only 0x8000 / 32KBytes without switching)

Imagine a box of cookies and two hungry kids, one can just devour everything at once but the other can only nibble one cookie at a time and will take some time to take another.
M68k can read the whole ROM as it pleases, Z80 is picky and needs bank switching.

Sound effects won't be possible without rewriting the Sound Driver since there's no bank switching involved for those, so I won't bother (KtEiS2 didn't bother either, Knuckles's land and wall snap are silent), but in theory one could add or replace them if a full copy of S&K's sfx were to exist within Gatoslip's ROM.

Post Reply