Author Topic: Chillyfeez's Mods, hacks, research notes, etc.  (Read 17621 times)

avalanche

  • Mom Bomb
  • *
  • Posts: 122
    • View Profile
Re: Chillyfeez's Mods, hacks, research notes, etc.
« Reply #90 on: February 27, 2015, 09:28:16 AM »
That looks to be the case.  Are values above 14 bits valid in the place you inserted those damages?

chillyfeez

  • FF4 Hacker
  • *
  • Posts: 1,285
  • Gender: Male
  • Go ahead, ask me about Angel Feathers!
    • View Profile
Re: Chillyfeez's Mods, hacks, research notes, etc.
« Reply #91 on: February 27, 2015, 11:26:33 AM »
Sorry, which places I inserted those damages?
Are you referring to the problems related to the picture I posted?

avalanche

  • Mom Bomb
  • *
  • Posts: 122
    • View Profile
Re: Chillyfeez's Mods, hacks, research notes, etc.
« Reply #92 on: February 27, 2015, 11:35:18 AM »
Yep.  As you mentioned earlier, 16383 is going to be the largest number valid in many parts of code because of the flag bits.  So if you forced damage numbers like 54321 pretty late in the pipeline, it might work okay, but earlier parts might misbehave because of those flags.  I'm sure it wouldn't be the only problem though, so this is a minor thing.

The 321K damage is pretty rad though   : )

chillyfeez

  • FF4 Hacker
  • *
  • Posts: 1,285
  • Gender: Male
  • Go ahead, ask me about Angel Feathers!
    • View Profile
Re: Chillyfeez's Mods, hacks, research notes, etc.
« Reply #93 on: February 27, 2015, 03:05:49 PM »
Oh, I see what you're saying.
No, it's entirely about how things are being counted per monster.
See, the 20 digits that are being displayed here are set up all in a row. Each one has four values - x-pos, y-pos (which changes several times for the bouncy effect), actual displayed digit pointer (equal to the digit's value plus 70), and "31" (I have no idea what this one does). The reason things aren't displaying properly has everything to do with the fact that it's only assuming four digits per monster when it assigns the x and y positions to each digit.

avalanche

  • Mom Bomb
  • *
  • Posts: 122
    • View Profile
Re: Chillyfeez's Mods, hacks, research notes, etc.
« Reply #94 on: February 27, 2015, 03:45:46 PM »
Excellent, those 4-byte records are the hardware sprite format.  FYI the 4th byte format is
Code: [Select]
vhoopppc
  v: vertical flip
  h: horizontal flip
  oo: priority
  ppp: palette
  c: 9th bit of sprite index (aka character)

Another thing is that there are only so many sprites available for the digits, but I don't know how many that is.  Is the most that can be displayed at once 8 monsters * 5 digits, or are there some spells that need all 13 actors * 5?


chillyfeez

  • FF4 Hacker
  • *
  • Posts: 1,285
  • Gender: Male
  • Go ahead, ask me about Angel Feathers!
    • View Profile
Re: Chillyfeez's Mods, hacks, research notes, etc.
« Reply #95 on: February 27, 2015, 09:09:11 PM »
Excellent, those 4-byte records are the hardware sprite format.  FYI the 4th byte format is
Code: [Select]
vhoopppc
  v: vertical flip
  h: horizontal flip
  oo: priority
  ppp: palette
  c: 9th bit of sprite index (aka character)
"Priority" means, essentially, layer, I presume... Whether it appears over or under existing sprites?
And what's character?

Quote
Another thing is that there are only so many sprites available for the digits, but I don't know how many that is.  Is the most that can be displayed at once 8 monsters * 5 digits, or are there some spells that need all 13 actors * 5?
AFAIK, 8*5 would be the most. Ffiv doesn't have a merton-style spell that hits all monsters and all party members.
The area of RAM the sprites are loaded from certainly has enough space to accommodate 40 digits, so here's hoping that won't be a problem for the hardware to display...

chillyfeez

  • FF4 Hacker
  • *
  • Posts: 1,285
  • Gender: Male
  • Go ahead, ask me about Angel Feathers!
    • View Profile
Re: Chillyfeez's Mods, hacks, research notes, etc.
« Reply #96 on: February 27, 2015, 11:18:53 PM »
Ha-ha! brilliant!

Turns out I was doing too much. I didn't need to change three bytes. I only need to change one byte!



I'm getting very close to making this thing a reality!

chillyfeez

  • FF4 Hacker
  • *
  • Posts: 1,285
  • Gender: Male
  • Go ahead, ask me about Angel Feathers!
    • View Profile
Re: Chillyfeez's Mods, hacks, research notes, etc.
« Reply #97 on: February 28, 2015, 10:09:50 AM »
Ah, the ROLler you are talking about is 02:852B which oddly enough is the same division routine I mentioned from bank 3, but for some reason coded slightly differently.  In any case, it divides and produces an integer division in $2A and remainder/modulo in $2C.  The former is used as the next digit, while the latter is used for calculating the next digit on the way down.  Interestingly that does indeed work for 5 digits.

I would bet that the routine at 02:86BF is probably used for any decimal conversion for display, at least in battle, including the party battle window HPs, and perhaps the monster HP in a Peep result, which actually needs 5 digits.

I tried setting the damage to 12345 and while this routine did calculate 5 digits properly, only 2345 displayed in bouncy numbers, thus whatever 3 changed bytes you mentioned must be needed to setup the bouncy sprites.  You're already past this part, but I was curious how they performed the decimal conversion, so I popped in to take a look.

Hmm, even though I've activated display of the 10000ths place digit, it's still not showing up in bouncy numbers, so the routine at 2852B must be throwing out the remainder after four digits instead of storing it in the place that was already set aside for a 5th digit. Silly.
So I'll have to zero in on the place where that digit exists and tell the code to use it instead of disposing of it...

avalanche

  • Mom Bomb
  • *
  • Posts: 122
    • View Profile
Re: Chillyfeez's Mods, hacks, research notes, etc.
« Reply #98 on: February 28, 2015, 12:16:51 PM »
Yes, priority is like the Z index, and is the order of sprites but also between sprites and bg layers too. It's nontrivial though when comparing bg's and sprites.

Character is what the SNES docs call it. It is the index into the sprite graphics loaded elsewhere in video memory. Sprite index makes better sense to me though.

As for your latest post, I came across some relevant 4-assuming code where it takes the 5, then ignores the first, before it gets to the sprite code you found. I am not home to post exactly where right now though. But I should be able to do that tonight or tomorrow if you are still on the problem.  But the low level decimal conversion itself keeps all 5 for sure. It's somewhere else that discards it.
« Last Edit: February 28, 2015, 12:24:06 PM by avalanche »

chillyfeez

  • FF4 Hacker
  • *
  • Posts: 1,285
  • Gender: Male
  • Go ahead, ask me about Angel Feathers!
    • View Profile
Re: Chillyfeez's Mods, hacks, research notes, etc.
« Reply #99 on: February 28, 2015, 02:04:40 PM »
I actually got it working, but it did require a bit of custom code, since I still don't fully grasp how the conversion is working. I can alter that routine so that it acknowledges values above 9999, but it still stores one digit above 9 in the 1000s place, so to work around this I wrote a 0x13 byte routine that basically says:
If [digit] is >9, then store 1 in the next digit up, subtract 10 from [digit] and store.
I was hoping I could do it all without any custom code (which still might be possible), but this works flawlessly, so I am satisfied with it.
If you want to look into making that routine account for the 5th digit, though, I would still be interested in seeing that happen.

The only step left is to "turn off" the 9999 damage limit(s) and this will be a working hack!

avalanche

  • Mom Bomb
  • *
  • Posts: 122
    • View Profile
Re: Chillyfeez's Mods, hacks, research notes, etc.
« Reply #100 on: February 28, 2015, 09:51:12 PM »
Cool, glad you got it!

Can I ask where it was that you modified, or where it had the larger-than-9 digit?  I'm pretty sure that 02:852B (division) and 02:86BF (generic binary-to-decimal conversion) are okay.  The latter should put 5 good digits into $180C-$1810.  Code at 02:8716, however, discards the first digit dropping it to 4.  But I'm not sure where the code is that calls the decimal conversion and ultimately finds its way to the sprite setup. 

chillyfeez

  • FF4 Hacker
  • *
  • Posts: 1,285
  • Gender: Male
  • Go ahead, ask me about Angel Feathers!
    • View Profile
Re: Chillyfeez's Mods, hacks, research notes, etc.
« Reply #101 on: February 28, 2015, 10:57:34 PM »
Yeah, I've been keeping notes on a notepad file as I go, and was intending on posting it all once I had the patch up and running, but I can put up what I've got so far... Except I'm already in bed for the night, so I will do tomorrow morning when I get up.

chillyfeez

  • FF4 Hacker
  • *
  • Posts: 1,285
  • Gender: Male
  • Go ahead, ask me about Angel Feathers!
    • View Profile
Re: Chillyfeez's Mods, hacks, research notes, etc.
« Reply #102 on: March 01, 2015, 09:46:19 AM »
OK, let me try to explain everything I've done so far...

So, the place in RAM where the digits are stored immediately before they're loaded for visual processing is 00:0340. As previously mentioned, it's four bytes per digit: x,y,(digit+70),(vhoopppc).
It should be noted that the game does, by default, assign five digits per target, even though five digits are normally never used.

Now, byte 2 of those entries (the digit) is loaded into the table at 0340 from a table at 7E:DBE6. This table also assigns five digits per target, but the uppermost digit is never loaded into 340. Instead, the game loads 1000s, 100s, 10s, 1s and the 10000s of the next entry (which is always FF, or blank) into the entry for each target.

So, the first fix was to change
Code: [Select]
$02/E5AA BD E6 DB    LDA $DBE6,x[$7E:DC19]which is the opcode responsible for loading each displayed digit, so that it reads
Code: [Select]
$02/E5AA BD E5 DB    LDA $DBE5,x[$7E:DC18]
So now the game is accounting for the correct five digits for each target. As a result, the damage digits display one sprite to the right from where they normally would, but I personally find that completely inoffensive. It can probably be shifted, but I say why bother? It looks fine.

So now we're at the point where the problem at hand is the fact that nothing is being loaded into the 10000s place digit. You can cheat the damage up to 16383, but only "6383" will show up. This has to do with the decimal conversion process, and more specifically what the game is doing (or not doing) with the last remainder.

The conversion routine loads the digits into 180C-180F, and they are loaded from there into the table at DBE6. As far as I can see, the 10000s place digit is never loaded into 180B.
So I spent a while watching a live disassembly of the conversion routine. I still don't get what is happening or how it happens. My understanding of the ROL opcode is that it essentially works like ASL, except that it can be performed on two bytes at once... and sometimes if you ROL 00 00, you get 01 00, and I have no idea where that bit comes from.
anyway... from what I can see, the storing of digits into 180C-180F is pretty hardcoded. the game doesn't do a STA $180C,x op that is performed four times as X increases. it's STA $180C, STA $180D, STA $180E and STA $180F. What I did notice was, right before the jump into this subroutine, the game does this:
Code: [Select]
$02/86C1 A2 10 27    LDX #$2710
Well, 0x270F is equal to 9999, so it occurred to me that this op might be setting the upper limit of what numbers are considered in the decimal conversion process.
So since we want the game to accept damage as high as 0x3FFF, I changed this op to:
Code: [Select]
$02/86C1 A2 00 40    LDX #$4000
I then cheated 0x3000 damage into A4 and watched what happened...
0x3000 is equal to 12288.
The output I got on screen was "[random incorrect sprite]288"
So I looked at what was in the table at DBE6...
Bear in mind that the format for digits is (actual digit + 70), so correct would be 71 72 72 78 78
What I had was FF 7C 72 78 78
Well, A + 2 = C, which means what the game was doing was now accounting for the value over 9999, but instead of separating that 7C into two usable digits, it was just going with it.
So I found the op that stores 7C into DBE7:
Code: [Select]
$02/CA35 99 E7 DB    STA $DBE7,y[$7E:DBED]
$02/CA38 C8          INY                  ;(I needed this one-byte op to, because I was writing a JSL)

And I changed it to:
Code: [Select]
$02/CA35 22 E0 EF 12 JSL $12EFE0[$12:EFE0]
Then wrote the subroutine:
Code: [Select]
$12/EFE0 C9 7A       CMP #$7A             ;compare the digit about to be stored into the table with 7A
$12/EFE2 90 0A       BCC $0A    [$EFEE]   ;if it is lower than 7A, skip to the end of this routine (and proceed as normal)
$12/EFE4 48          PHA                  ;if it is 7A or higher (which will only happen with the digit in the 1000s place, then stack it
$12/EFE5 A9 71       LDA #$71             
$12/EFE7 99 E6 DB    STA $DBE6,y[$7E:DBED];load 71 into the 10000s place
$12/EFEA 68          PLA                  ;pull the digit back off the stack
$12/EFEB 38          SEC                 
$12/EFEC E9 0A       SBC #$0A             ;subtract 0A
$12/EFEE 99 E7 DB    STA $DBE7,y[$7E:DBEE];then proceed as normal
$12/EFF1 C8          INY                  ;(this is a replacement of that INY we cannibalized at 02/CA38
$12/EFF2 6B          RTL                 

And there you have it!
Five digits now display properly... as long as you cheat in damage over 9999. I still haven't gotten to the point of turning off those limits. For the most part, this will just be a matter of finding them (there are several, different ones for damage routines of different commands) and changing them from 270F to 3FFF.
The Multi-Target damage routines may require a little figuring out, because I think the game does something weird where if the total calculated damage is over 9999, the first target gets 9999 and the rest of the damage is distributed among the remaining targets... or something like that.
Oh well, we'll see.

I'm off work today, but I have some chores to do, so I'm not positive I'll be able to get a lot of work in on this.
Here's hoping.

avalanche

  • Mom Bomb
  • *
  • Posts: 122
    • View Profile
Re: Chillyfeez's Mods, hacks, research notes, etc.
« Reply #103 on: March 01, 2015, 10:40:28 AM »
Well, I still think the division and decimal conversion routines are okay.  The decimal conversion writes 5 digits to $180C,180D,180E,180F and 1810.  180B is not related.  I also don't think DBE5 is part of it, so I suppose that could result in reading a bogus value.

The reason that the 10K digit is missing is because they discard it.  Excerpt:
Code: [Select]
02:CA08  20 BF 86    JSR $86BF                 decimal conversion routine
02:CA0B  20 16 87    JSR $8716                 discard first digit, blank out leading zeros, set X to first digit to display
First it calls the decimal conversion, so 180C-1810 have all 5 correct digits.  But the next routine called shifts all the digits over, discarding the 10K digit, then does some other things like writing an FF over leading zeros (so they don't show), and leaves X pointing to the index of the first digit to show.

That second routine is the problem, and it called in multiple places, so we may not be able to totally change it without breaking other things. 

Here's what I tried, just two bytes changed so far: 
Code: [Select]
FROM  02:CA0B  20 16 87    JSR $8716
TO    02:CA0B  20 25 87    JSR $8725

FROM  02:CA3A  E0 04 00    CPX #$0004
TO    02:CA3A  E0 05 00    CPX #$0005
The first change skips over the digit-discarding part but performs the rest of that subroutine.  And the second causes it to copy 5 digits to the DBE7 area.  You're right and it's cool that the game otherwise allowed for 5 digits.  Attached is an example running with those changes.

Unfortunately, there is one part not perfect about this.  Above I mentioned that the routine leaves X pointing to the first index to show. Well with this hack, if you do a single digit worth of damage it will have a leading zero like "06".  If we change it to fix that, then some of the callers of that routine will get messed up because they assume it discards the leading digit.  I would hope that's fixable by tweaking the various callers, but I have not tried that yet.  Hehe it also says "Miss!0" or similar the next time because they don't clear everything properly.
« Last Edit: March 01, 2015, 10:52:49 AM by avalanche »

chillyfeez

  • FF4 Hacker
  • *
  • Posts: 1,285
  • Gender: Male
  • Go ahead, ask me about Angel Feathers!
    • View Profile
Re: Chillyfeez's Mods, hacks, research notes, etc.
« Reply #104 on: March 01, 2015, 11:20:27 AM »
That 5 in the ones place also looks like it's bouncing a bit oddly.
From what it looks like, you're drawing your digits from DBE7-DBEB.
If you use DBE6-DBEA instead, I think it will follow the wave pattern of the upper four digits more closely.
It it possible that might also solve the "miss!0" issue, since "miss!" is loaded into DBE7-DBEA?
... On second thought, it might not affect the bounce at all, but it should fix "miss!0"

So far, I still prefer the result of my method, but you may be on to something here.