News: 11 March 2016 - Forum Rules
Current Moderators - DarkSol, KingMike, MathOnNapkins, Azkadellia, Danke

Author Topic: bad coding in roms  (Read 34774 times)

Zoinkity

  • Hero Member
  • *****
  • Posts: 557
    • View Profile
Re: bad coding in roms
« Reply #20 on: July 13, 2012, 07:03:25 pm »
Oh, completely forgot.  Animal Forest explicitly initializes somewhere around 0x250 bytes of data after the legal screen.  That's about 400 opcodes sucked down to do what can be done in about 20 opcodes--smaller if you're willing to take a hit on the compression factor by using nonredundant code.

assassin

  • Full Member
  • ***
  • Posts: 140
    • View Profile
    • My Barren Webpage
Re: bad coding in roms
« Reply #21 on: November 15, 2012, 06:30:33 pm »
from FF3us (also in FF6j, at C3/A348), including my comments:

Code: [Select]
C3/9B59: 20 2A 9C     JSR $9C2A      (Clear our list of eligible equipment by writing
                                      nine FFs to it)
C3/9B5C: 20 41 9C     JSR $9C41      (Setup equippability word)
C3/9B5F: A9 20        LDA #$20
C3/9B61: 85 29        STA $29        (set text color to white)
C3/9B63: A5 4B        LDA $4B        (which of four Equipment slots we're looking at)
C3/9B65: C9 02        CMP #$02
C3/9B67: F0 49        BEQ $9BB2      (branch if this is a Helmet slot)
C3/9B69: C9 03        CMP #$03
C3/9B6B: F0 02        BEQ $9B6F      (branch if this is an Armor slot)
C3/9B6D: 80 03        BRA $9B72      (otherwise, it's a hand slot, so list
                                      weapons and shields)
C3/9B6F: 4C EE 9B     JMP $9BEE      (Armor)
                                     (cripes, that's a lot of branch instructions.
                                      we can replace the three with "BNE $9B72 /
                                      JMP $9BEE / NOP / NOP" OR "NOP / NOP / BEQ $9BEE
                                      / NOP / NOP / NOP".  hell, just "BEQ $9BE9"
                                      would've worked to start, because that's where
                                      Function C3/9BEE would've begun without these 5
                                      extra bytes.  ay yay yay.)

so Square made one 2-byte branch into three branches totalling 7 bytes. :P

they do a LOT of dumb crap in Bank C3, most of which wasn't discovered by me (Lenophis, Novalia Spirit, and Imzogelmo have encountered their share).  it's our consensus that the programmers who coded Banks C3, C1, C0, etc. were dumber than those who coded C2 (the battle engine bank).  also, one commenter suspects that some of the C3 code was auto-generated somehow.

Ryusui

  • Hero Member
  • *****
  • Posts: 4989
  • It's the greatest day.
    • View Profile
    • Tumblr
Re: bad coding in roms
« Reply #22 on: November 15, 2012, 06:49:48 pm »
they do a LOT of dumb crap in Bank C3, most of which wasn't discovered by me (Lenophis, Novalia Spirit, and Imzogelmo have encountered their share).  it's our consensus that the programmers who coded Banks C3, C1, C0, etc. were dumber than those who coded C2 (the battle engine bank).  also, one commenter suspects that some of the C3 code was auto-generated somehow.

Maybe it was written in C/C++ or another language, and then compiled - badly.
In the event of a firestorm, the salad bar will remain open.

LostTemplar

  • Hero Member
  • *****
  • Posts: 906
    • View Profile
    • au-ro-ra.net
Re: bad coding in roms
« Reply #23 on: November 16, 2012, 06:24:10 am »
From the few looks I took at FF6's code I can only tell that it's pretty much a mess.

But I've seen multiple games where there apparently was at least some form of automization, especially macros. It's not that they didn't have computers with compilers back then, so I'd guess if they could program for the SNES they could at least write some tool that generates code in some manner. Even if it sucked.

Furthermore, it seems to be often the case that different banks are coded by different people. In one game I worked on it was so obvious it hurt. The battle was programmed in such a different way from the rest of the game. That's kind of interesting, though.

Not entirely related, but some time ago I looked at a game that had some JSRs in it to addresses that only contained an RTS. I suspect that this was either some form of debug routine that was taken out, or that there was some feature that was removed. Or maybe it was just overlooked, who knows.

tryphon

  • Hero Member
  • *****
  • Posts: 722
    • View Profile
Re: bad coding in roms
« Reply #24 on: November 16, 2012, 05:16:27 pm »
I'm diving into the code of Phantasy Star Generations 2 (ps2) and I've noticed a couple of things strange, such as a call to a subroutine, which, as usual, stores its return values in v0 and v1, but registers v0 and v1 are overwritten before being stored anywhere.

I can delete the call without any consequence...

It's all the more strange that I suspect the original program to have been written in C/C++.

BRPXQZME

  • Hero Member
  • *****
  • Posts: 4572
  • じー
    • View Profile
    • The BRPXQZME Network
Re: bad coding in roms
« Reply #25 on: November 16, 2012, 07:18:26 pm »
Not all compilers optimize (though this is getting much rarer than it was 20 years ago). And not all compilers that optimize do it well! :laugh:

Cruft left over from debug code can also leave puzzling artifacts, particularly if the developer was not that assembly-minded (or just didn’t care... I mean, sometimes it’s really just a few instructions on a processor that does millions a second and doesn’t mess up caching or anything).

In that case for PSG2, it’s possible that the return value wasn’t the point of that particular call to the function. It isn’t unusual to call a function that returns something when all you wanted was the function’s effect. But again, it could just be partially-dummied debug code. Only way to tell is to look and see what it does.
we are in a horrible and deadly danger

Carnivol

  • Jr. Member
  • **
  • Posts: 90
  • Consider it a privilege!
    • View Profile
Re: bad coding in roms
« Reply #26 on: November 18, 2012, 10:44:42 am »
(only serious flaw I know of is that the music freezes in the good ending credits, though I don't know if that happens on real hardware or just in emulation)

Know this was an old thread gettin' bumped, but I can tell you that the ending credits music locks up on hardware too. (Was that ever fixed by anyone? I only played the game like a decade ++ ago, whilst looking for games I wanted to see happen in English/Norwegian ...)

Pyriel

  • Jr. Member
  • **
  • Posts: 23
    • View Profile
Re: bad coding in roms
« Reply #27 on: November 18, 2012, 11:31:39 am »
Yeah, nobody usually cares about the return value from memset, but NOPing the call probably wouldn't be a good idea.

Suikoden II on the PSX is just loaded down with debug code.  The game is done in hundreds of modules that load at fixed addresses, and the modules will call various functions from the main executable via JALR register jumps.  I guess they solved the issue of dealing with common code via a ton of extern function pointers or something.  Regardless, every time one of these calls is done, you see:
Code: [Select]
la $trace_reg, ModuleTrace
sw $call_reg, $trace_reg
Since it uses these functions pretty regularly, there's probably about half a KB or more of wasted instructions in a lot of the modules.  These instructions are pretty trivial, so it hardly matters, and every time it happens I have 3 more op codes I can add without taking anything away.  I can take back more if I change all the JALRs to straight JALs.  All the debug prints they left in are slightly less trivial.

One really weird thing they did was having two sets of code for battles.  One runs during the first round of a fight, and the second set runs during the second round onward.  It's not that there's an "if" statement or something.  They actually overlay the code from FST.BIN with code from SEC.BIN while the battle animations run.  About 90% of the code is identical, so I guess they were worried a couple of overloaded or extra functions would overflow the 200 or so KB they allocated to hold the code.

KingMike

  • Forum Moderator
  • Hero Member
  • *****
  • Posts: 6575
  • *sigh* A changed avatar. Big deal.
    • View Profile
Re: bad coding in roms
« Reply #28 on: November 18, 2012, 11:32:22 am »
Never verified if it (Jelly Boy 2 music crash) happened on hardware, just that it wasn't caused by the translation patch.
"My watch says 30 chickens" Google, 2018

Zoinkity

  • Hero Member
  • *****
  • Posts: 557
    • View Profile
Re: bad coding in roms
« Reply #29 on: November 19, 2012, 03:26:18 pm »
Perfect Dark: the ROM space allocated for the first three (and largest) compressed files in the game happen to be sized for decompressed copies of this data.  In other words, there was no reason whatsoever to compress it.

GoldenEye and Perfect Dark also have multiple copies of zlib embedded, complete with all its registers.  GE only has two; the first is used only at boot before the second is decompressed, so you can at least understand to some degree how this could happen.  PD has at least three however, and I suspect a fourth, the only difference being what fileloader called the data they're decompressing, and the only difference in the fileloaders being one is effectively a macro for the other. 
Both games are rigged to test for at three different kinds of headers, except each of these tests use the same samples for the header test.  An enterprising individual can feed it Rare's other games' samples so they can open each other's data--or zlib headers for that matter.

Oh, and GE happens to have a complete 64DD I/O handler built in for no reason whatsoever.  That complements all the debug info it collects and discards rather nicely.

LostTemplar

  • Hero Member
  • *****
  • Posts: 906
    • View Profile
    • au-ro-ra.net
Re: bad coding in roms
« Reply #30 on: November 19, 2012, 04:12:49 pm »
I'm working on this weirdly programmed SNES game right now. Not sure if it can even be called bad, but it is certainly weird. It turns the NMI off and waits manually for vblank each frame to do its drawing; it NEVER uses 8-bit mode, only 16-bit; it uses long addressing (24-bit) way too often; it does this very simple variation of an LZ compression where it writes directly to VRAM and reads it back from VRAM for back references, etc.

Zoinkity

  • Hero Member
  • *****
  • Posts: 557
    • View Profile
Re: bad coding in roms
« Reply #31 on: November 21, 2012, 08:19:27 pm »
The official RNC decompression routine provided for N64 throws all the programming style out the window.  It uses only system variables, plays funny tricks with a 'false' stack, manually jumps and links instead of using the hardware provided method, and has to disable exceptions because if anything happened in the middle of this horrible winding spaghetti (such as playing audio, or video, or handling another thread, etc.) it would crash.

It was enough of a problem that Acclaim rewrote the thing with some rather tart comments about the original inserted for good measure.

Personally I don't see why anyone bothered with such a bizare compression scheme anyway when zlib was a smaller library, faster, didn't require licensing, and compressed faster and better.

Bond697

  • Full Member
  • ***
  • Posts: 249
    • View Profile
    • The Final fantasy 4 Reference Book
Re: bad coding in roms
« Reply #32 on: November 26, 2012, 09:28:39 am »
pokemon white 2 does some funny things in its breeding code.  to create an egg, they:

-create a full wild pokemon for the sole purpose of creating a free 220 byte block and a pointer to it(they have a memory allocation system that could easily do this)
-create a 34-element u32 array where they arrange a bunch of features that the egg will have(inherited ivs, inherited moves species, et al)(there's a good amount of extraneous data in this)
-use the previous pointer as a start in creating a second full wild pokemon
-after making the second full pokemon, write all the values from the egg data array into the correct spots, the  set some values for the egg, and finally set the marker that makes it an egg

in the end they generate 3 pids, 18 ivs, and loads of other extraneous values.  it's really kind of a mess.

e: almost forgot the best part.

breeding in bw2 uses its own special inline rng.  it uses a special seed they create when the game boots.  however, due to a programming mistake, every time you restart the game the first egg you breed will be identical aside from the species and pid. 


the way it works is when you start a new game, on loading into the world for the first time, the game creates a seed and saves it to your save file.  each time you restart a new seed is made and copied into the right spot for breeding.  after that, the old seed is read in front the save and written in.  then the old seed is written in a second time when the entire daycare block is copied into place.
« Last Edit: November 26, 2012, 10:05:29 am by Bond697 »

BRPXQZME

  • Hero Member
  • *****
  • Posts: 4572
  • じー
    • View Profile
    • The BRPXQZME Network
Re: bad coding in roms
« Reply #33 on: November 26, 2012, 04:49:38 pm »
e: almost forgot the best part.

...
amg

well, I guess it still takes care of what they wanted it to accomplish, but still

wow
we are in a horrible and deadly danger

Zoinkity

  • Hero Member
  • *****
  • Posts: 557
    • View Profile
Re: bad coding in roms
« Reply #34 on: November 26, 2012, 09:13:55 pm »
Funny thing about the N64: register R0 is always 0.  It can never change.
Turns out some games <cough>Forsaken64</cough> seem to think that's a great place to dump error codes.

800029B8, 800068D8, 80006A6C, 80007410, 800080C4, 80008150, 80008788, 800087F0, 80009D0C, 80009D44, 80009DC0, 80009E60, 80009F58, 8000A02C, 8000A118, 8000BBA8:
ADDIU   V0,R0,FFFF
SW   V0,0000 (R0)

Would be slightly less idiotic if they didn't test for error codes after each return, or if some of these routines weren't dedicated to testing for this error code.

BRPXQZME

  • Hero Member
  • *****
  • Posts: 4572
  • じー
    • View Profile
    • The BRPXQZME Network
Re: bad coding in roms
« Reply #35 on: November 26, 2012, 11:29:31 pm »
I don’t see anything being dumped into R0 in that code....
we are in a horrible and deadly danger

LostTemplar

  • Hero Member
  • *****
  • Posts: 906
    • View Profile
    • au-ro-ra.net
Re: bad coding in roms
« Reply #36 on: November 27, 2012, 04:18:50 am »
My MIPS assembly is a bit rusty, but that's indirect addressing, isn't it? Meaning it would be

v0 <- 0xffff
address r0+0000=000000000 <- v0

I don't know what the N64 has at address 0, but it really doesn't seem like r0 itself.

Revenant

  • Full Member
  • ***
  • Posts: 203
    • View Profile
Re: bad coding in roms
« Reply #37 on: November 27, 2012, 05:03:32 am »
edit: i shouldn't try to remember forgotten college courses while sleep deprived
« Last Edit: November 27, 2012, 07:09:55 am by Revenant »

BRPXQZME

  • Hero Member
  • *****
  • Posts: 4572
  • じー
    • View Profile
    • The BRPXQZME Network
Re: bad coding in roms
« Reply #38 on: November 27, 2012, 06:48:59 am »
My MIPS assembly is a bit rusty, but that's indirect addressing, isn't it? Meaning it would be

v0 <- 0xffff
address r0+0000=000000000 <- v0

I don't know what the N64 has at address 0, but it really doesn't seem like r0 itself.
Close. In MIPS, immediate values for arithmetic are sign-extended 16-bit numbers, so (as posted) the code does

v0 := -1
M[0] := v0
we are in a horrible and deadly danger

Pyriel

  • Jr. Member
  • **
  • Posts: 23
    • View Profile
Re: bad coding in roms
« Reply #39 on: November 27, 2012, 08:32:32 am »
...if some of these routines weren't dedicated to testing for this error code.

What does this mean? After they store at 0(R0), they load it back sometime later to test it?  From your description of the oddity, it sounds like a few instructions later you're seeing them explicitly stick 1 on V0 and then test that against R0.