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

Author Topic: FF1 MMC5 Disassembly Updates  (Read 76732 times)

Jiggers

  • Sr. Member
  • ****
  • Posts: 254
    • View Profile
FF1 MMC5 Disassembly Updates
« on: January 04, 2019, 05:36:47 am »
Hi! This is a project I've been working on for... I think 2 years now? It upgrades Final Fantasy 1 to use the MMC5 mapper... then goes crazy with what I hope are improvements to the game. It's based of Disch's FF1 Disassembly. He did a bunch of things to help get me started with it. I've done my best to credit a few other people as well.

https://github.com/JiggeryPonkery/FF1-MMC5 - Here is the newest versions maybe.

Everything below this line is kinda old and not updated.



Here is a zip file with the entire project.
https://drive.google.com/open?id=1G699Vc47Qr5he4zcBEi2JPTdc0a9h14n

Updated 15/01/2019

(I don't know what other emulators will work besides Mesen by the way...)

This is far from finished, but I've hit a wall and need help again. Before I get into that... I should apologize for how long this is. Wow. Sorry!

General Changes
  • Bridge scene is now a title screen!
  • Re-did the opening text printing effects. Now prints one letter at a time. With sprites!
  • Options menu: (all settings saved with your game)
  • Choose Low, Normal, or High encounter rate
  • Choose Low, Normal, or High gold gain
  • Choose Low, Normal, or High exp gain
  • Turn on/off menu sound effects
  • Turn on/off auto-targeting
  • Battle message speed (respond rate) now changed here.
  • Menu screen has been re-arranged to fit Options menu and Save option, as well as longer character names.
  • Save anywhere in the overworld from the main menu.
  • Character Status screen re-arranged.
  • Weapon and Armour screen name boxes slightly altered.
  • Magic screen widened, now displays character name (if it didn't before).
  • Character Status screen re-arranged.
  • Characters can have 7 letter names.
  • Spells can have 7 letter names, and some spells have updated names to take advantage of that.
  • Character class and sprite are seperate. Select either (back and forth!) in character generation by pressing up/down for sprite, and left/right for class.
  • Exiting character generation by pressing B returns you to the title screen.
  • No more dialogue box SFX; faster dialogue box opening and closing.
  • Faster screen transitions between maps and opening the menu.
  • Shop screens have been re-arranged.
  • Shops have updated dialogue strings.
  • Item shops now let you buy between 1-99 items at a time. There are some hidden benefits to only buying 1-2 at a time.
  • Heals, pures, softs, tents, cabins, and houses now show up first in the item screen, in that order.
  • Weird purple/blue pixels in the Bridge scene were fixed by fixing attribute data.
  • Weapons and armour is no longer automatically sorted, because there was a bug and removing the sorting code was the easiest fix.
  • Hold B Button to sprint in towns, castles, and dungeons, but not the overworld! Theoretically hold the B Button to slow down the airship for precision landing.
  • I probably forgot something. Lots of behind the scenes fixes were done all over!
  • There are three save slots to use. Saving on the overworld and the inn will access the same menu. Loading from the Continue option on the title screen will... load.

Battle Changes
  • The entire screen has been re-done to show 7 letter character names.
  • Magic menu has been widened for 7 letter spell names.
  • Status ailments are now depicted by an icon.
  • Black Belt and Master hand sprites now change palettes depending on the sprite used.
  • There is a Hide option that allows a character to be targeted less and evade more (-40 to enemy hit chance) when targeted...
  • Attacking from hiding boosts hit rate and crit rate by x2 for everyone.
  • Attacking from hiding boosts strength by 1.5x and crit rate by x3 for thieves.
  • Thieves and Ninjas have a chance to steal gold equal to their damage dealt when landing a critical hit.
  • Thieves and Ninjas also will try to hide when the party is surprised, if not afflicted by anything other than poison.
  • Black Belts and Masters have a chance to stun an enemy when landing a critical hit.
  • Red Mages and Wizards have a chance to slow an enemy when landing a critical hit.
  • Black Mages and Wizards have a chance to confuse an enemy when landing a critical hit.
  • White Mages and Wizards have a chance of boosting their own strength when landing a critical hit.
  • Lotta bugs fixed. TMPR and SABR spells should now work. Enemies should stay asleep. Many little changes like that.
  • Magic sprites move 2 pixels to the left every 2 frames, woosh!
  • Turn order is now somewhat calculated by Luck and 1/4 of enemy's morale.
  • Poison now takes 1/8th a character's total HP per turn, and will message between turns with the damage amount.
  • Regenerative enemies now regenerate about 1/10th their total HP per turn, and will message when they do so, but not show the amount.

Audio Changes
  • MMC5's extra square channels can now be used. MMC5 audio fully integrated with original code.
  • Updated the Prelude to include a melody based off Ailsean's "Final Ecstacy" OCRemix.
  • Replaced the Marsh Cave music with my own composition. (Please credit me if you use it? Original song data still there to use too.)
  • Menu SFX now use noise channel. Turning off menu SFX will shake the screen when an error occurs.
  • Updates to the music driver:
  • Added a bass octave.
  • Replaced an unused Note Length/Tempo LUT with an option for 115 bpm.
  • New sequencer options:
  • F0 = Alternative loop (a "go back to X then skip the second time" kind of loop, allowing a song to play something twice, then skip to a variation)
  • F1 = GOTO .word
  • F2 = RETURN
  • F3 = Octave Switch - F3 01 to lower, F3 02 to raise.
  • F4 = Silencer. F4 will turn it off and on for the channel. Halves volume byte.
  • F5 = Duty Select - F5 01, 02, 03 - 12.5%, 25%, 50% duty.
  • Map music persists in the main menu, but quieter;
  • Entering the menu triggers DPCM data that halves the triangle channel's volume and triggers a Silencer for the square waves.
  • Poison and damage tiles now use noise channel.
  • Common treasure chests no longer interrupt dungeon music.
  • Healing in the menu no longer resets music... I think? Been a while since I tested that.
  • The Prelude is no longer reset between the intro story, title, options, and character generation screens.
  • Inns play the old menu music. Clinics play the Castle music. The B+Select map plays the old menu music too.
  • Not a Change: Battle SFX still uses square 2. For now.
  • Battle and Prologue (minigame) music use the MMC5 square for channel 2, so SFX don't interrupt the music.
  • Pressing B + Select in a town now opens a sound test screen, to play any song in the game. Zhp!

ASM Changes
  • Updated standard and DTE tables included in the Atlas folder, along with example script.
  • Bank A is fully documented and ready for strings to be edited by hand or with Atlas, or any other tool for converting text to hex codes.
  • Bank Z ($0F, but not fixed bank) now contains bits of battle code, most of the title screen code, options menu code, and sound test screen code.
  • Bank 10 ($10) now holds dialogue data.
  • In Bank E, the ability to edit armour equip locations (head, body, hands, shield) is documented to be super easy.
  • In Bank C, enemy stats, weapon stats, armour stats, all documented and ready for editing.
  • Almost everything in Bank E is documented, except for the new shop strings.
  • Bank A item prices data is fully documented and ready for editing.
  • Bank D music data is more or less fully documented and ready for editing. (With thanks to Gil Galad for their music driver disassembly for the data and layout!)
  • Bank B Enemy names and Battle messages are now fully customizable without pointer errors.
  • Bank B Level-up data is shown in binary, with a helpful spreadsheet-like format. All 12 classes and levels identified. All 6 promoted classes can now level up with different stats from their pre-promotion classes!
  • Lots of new variables, and some RAM data has been shifted around to make more room for experimenting. See Variables and Constants for more info. LOTS has been shifted around for saving in 3 slots.
  • Anywhere I changed something, I did my best to document it with a "JIGS" and some sort of explanation. Not everything in Bank Z is documented well.
  • Edit nes.cfg and build.bat to add more banks. Remember to take out $4000 of 0s for each new bank from filler.dat before compiling.

Changes I'd Like To Make
  • Make sure Chaos's death doesn't erase parts of the battle screen that shouldn't be.
  • Complete documentation of the Dialogue Data like I've done for items and menu strings.
  • Choosing menu colour in the options screen.
  • Complete documentation of all other data: overworld battle things, magic, npc triggers...
  • Completely re-write everything to generally be more flexible and less confusing maybe in 20 years

Known Bugs
  • Options menu cursor speed is wonky. Need to clean up the code there.

Maybe Bugs
  • I don't think I fixed the XFER bug. I over-complicated the whole elemental weakness/resistance thing in my head and now I don't know if it works or not.
  • Poison now uses the noise channel... so should damage tiles. I don't know what will happen with both in play.
  • Due to the widening of the magic screen, if a character only has one spell, you can't move the cursor to see how many max casts are possible.
  • I hand-typed the hex codes for updated spell names... some might be off.

Why?
I've had a lot of fun tinkering with ASM doing this project. FF1 is a simple, classic game that's surprisingly easy to tweak and full of incomprehensible coding choices that make it frustrating to impliment those fun tweaks. Originally I was going to use FF1 as a base for a whole other RPG world--but, you know, fitting a whole cat person sprite into 16x16 pixels is hard when you have no idea what you're doing.

So I abandoned my original goal and focused on doing little quality of life upgrades. I see a lot of people wanting to get into hacking by doing pure hex editing or using FFHackster, and I want to provide an alternative, to give people a deeper understanding of how the game really works. The switch to MMC5 allows for experimentation that simply wasn't possible in the crammed MMC3 format. I want other people to experience this! My code can be as hopelessly messy as it takes to get my ideas down before I have the skills to trim it down and speed it up. Your code can be that, too! Using this project as a base for your own ideas, you too can learn Assembly and put together all those "wouldn't it be nice if FF1 had..." ideas!


And again... many thanks to Disch, Gil Galad, Lenophis, anomie, and everyone else whose helped out by trailblazing this silly game's code and data jungles and providing little (and huge) improvements!
« Last Edit: March 09, 2019, 01:16:01 am by Jiggers »
I know exactly what I'm doing. I just don't know what effect it's going to have.

Bregalad

  • Hero Member
  • *****
  • Posts: 2641
    • View Profile
Re: FF1 MMC5 Updates
« Reply #1 on: January 04, 2019, 05:47:40 am »
Nice ! At first I tought this would be yet another shitty uninteresting mapper hack, but no you really planned to use the MMC5 so this is great. Perhaps a better name than "FF1 MMC5" would make up for the concept a little bit better. Keep up the good work !!

EDIT: Also please PLEASE use a patch, not a ROM ! This is very important !

Jiggers

  • Sr. Member
  • ****
  • Posts: 254
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #2 on: January 04, 2019, 03:49:34 pm »
WHOOPS. Forgot about that. Deleted the rom from the zip file now. Thanks for the reminder!

I'm not good with names. But since it is an "upgrade" from Disch's disassembly, I guess throwing that word in there would help? Its not really meant to be a patch, just the source code and the tools needed to piece it together. Is that still legal...?
I know exactly what I'm doing. I just don't know what effect it's going to have.

Mari42

  • Jr. Member
  • **
  • Posts: 84
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #3 on: January 04, 2019, 04:49:08 pm »
This is a fantastic way to make alot of improvements even better. I'm looking forward on this one despite the fact that this is for beta (I believe, if its unfinished). So does the ATB. That is WAY better of what it should've been for all future FF games. Im saying this, because im a fan of FF. So, this massive improvement does very well done.  :thumbsup:

Orochi Kusanagi

  • Jr. Member
  • **
  • Posts: 83
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #4 on: January 04, 2019, 05:15:36 pm »
This is some amazing work!

A.D.R.I.A.N

  • Full Member
  • ***
  • Posts: 132
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #5 on: January 04, 2019, 08:39:34 pm »
Guess my idea of a gil-stealing Thief finally became reality. Truly, well done!
"I hate when mods don't let you ask for help."

Jiggers

  • Sr. Member
  • ****
  • Posts: 254
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #6 on: January 06, 2019, 12:36:10 am »
Aw, thanks!

I did some more work on the hiding stuff. As far as I can tell, all hiding bugs are FIXED! The stat boosts are now in effect. I mean, I think they are. I haven't actually super tested it yet...

I tracked down the "everyone uses character 4's items" bug to this area:

Code: [Select]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  BattleDrawLoadSubSrcPtr  [$FC00 :: 0x3FC10]
;;
;;  input:       XA = 16-bit pointer to the start of a pointer table
;;
;;  output:  btldraw_subsrc
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

BattleDrawLoadSubSrcPtr:
    STA $97             ; high byte of pointer table
   
    JSR DrawBattle_IncSrcPtr
    LDA ($90), Y        ; get the desired index
   
    ASL A               ; multiply by 2 (2 bytes per pointer)
    PHP                 ; backup the carry
    STA $96             ; use as low byte
   
    TXA                 ; get X (low byte of pointer table)
    CLC
    ADC $96             ; add with low byte of index
    STA $96             ; use as final low byte
   
    LDA #$00            ; add the carry from the X addition
    ADC $97
    PLP                 ; also add the carry from the above *2
    ADC #$00
    STA $97             ; use as final high byte
   
    LDY #$00            ; get the pointer, store in btldraw_subsrc
    LDA ($96), Y
    STA btldraw_subsrc
    INY
    LDA ($96), Y
    STA btldraw_subsrc+1
   
    RTS

I'll need to go over this a bunch more to see just what's causing it, but once it gets out of here it starts drawing up the text for the "Small @Knife" my black mage has...

I also got distracted and made magic sprites move towards enemies! So that was a fun 5 minutes where nothing went wrong.

There was a bug I forgot about where you could choose a blank spot under Hide and Flee and crash the game. That's been fixed.

For testing purposes, the random roll when doing a critical hit to see if you do the special attack has been removed--every time you do a critical hit, it should do the special attack. If it doesn't, then something's broken. Note that fighters are OP and have no special attacks (unless you go enable the Cleric thing in Bank Z, which should let them mow down undead and were creatures...)

Um... at the moment stealing gold crashes the game. I'm sure it has to do with undrawing battle blocks. I only changed a $02 to a $03...? I'll try to fix it tomorrow. This now works. All special attack messaging should draw properly!

I also fixed up the battle message and enemy name LUTs to be editable. Was going to expand the level up data for 12 classes, but there's not enough room in Bank B for that. Will look into moving that data safely to another bank.

.zip file in main post is updated with changes!
« Last Edit: January 06, 2019, 05:55:50 pm by Jiggers »
I know exactly what I'm doing. I just don't know what effect it's going to have.

Vanya

  • Hero Member
  • *****
  • Posts: 1489
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #7 on: January 07, 2019, 05:52:49 am »
This is pretty awesome.
It could be a very good basis for a more complete battle system overhaul to bring it up to par with FF3.

Jiggers

  • Sr. Member
  • ****
  • Posts: 254
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #8 on: January 09, 2019, 03:24:15 am »
Updated the Enemy Regeneration routine and Player poison routine! Players take 1/8 max HP in damage from poison, making it actually scary in battle. 8 turns to cure it or dead!

Enemies... Enemies do this. I am not sure if it works, but if it does, I think it should regenerate a little under 1/10th their max HP per turn. So... WarMech real scary. Anything much lower than that and common enemies are push-overs. (It's still better than 2 HP per turn.)

Code: [Select]
LDY #ENROMSTAT_HPMAX
    LDA (@rom), Y
    STA math_basedamage
    STA btl_mathbuf+2
    INY
    LDA (@rom), Y
    STA math_basedamage+1
    STA btl_mathbuf+3
   
    LSR math_basedamage+1   ; divide by 2
    ROR math_basedamage
    LSR math_basedamage+1   ; divide by 2
    ROR math_basedamage
   
    LDA math_basedamage
    STA tmp
    LDA math_basedamage+1
    STA tmp+1               ; tmp is now 25% max HP
   
    LSR math_basedamage+1   ; divide by 2 again
    ROR math_basedamage     ; math_basedamage is now 12.5% max HP
       
    LDA math_basedamage+1   
    CLC
    ADC tmp+1
    STA math_basedamage+1
    LDA math_basedamage
    CLC
    ADC tmp                 ; math_basedamage is now 37.5% max HP?
    STA math_basedamage
   
    LSR math_basedamage+1   ; divide by 2 again
    ROR math_basedamage     ; math_basedamage is now
    LSR math_basedamage+1   ; divide by 2 again
    ROR math_basedamage     ; math_basedamage is now 9.??% ? 

Both poison and regeneration will now message between turns.

I also fixed a bug where poison would be displayed by the stone icon out of battle, because for some reason they thought it best to shift poison from $04 to $03??? Rather than worry about why they did that, I just added a few more bytes to my code that draws the proper icon.

Currently working on buying more than 1 item at a time.

Question: Using the MMC5's multiplication registers, how would you multiply a 24-bit number by an 8-bit number? I'm completely stumped. I would prefer it if it could do it on the fly, so to say. I have room for a stupidly large LUT, so that's an option, but people would have to change the LUT if they change an item price... And you can't buy more than 21 houses without going over the 16-bit limit for how the game handles buying. Hell the price for 99 houses won't even display correctly in the main menu...

I guess since no item is over 16-bits to start with, I only have to multiply so that the result FILLS 3 bytes... Still no idea how to do that.
I know exactly what I'm doing. I just don't know what effect it's going to have.

Bregalad

  • Hero Member
  • *****
  • Posts: 2641
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #9 on: January 09, 2019, 08:26:29 am »
Question: Using the MMC5's multiplication registers, how would you multiply a 24-bit number by an 8-bit number? I'm completely stumped. I would prefer it if it could do it on the fly, so to say.
You do it like you multiply a 3-digit number by a single-digit number in real life. This requires 3 multiplications and 3 additions.

Jiggers

  • Sr. Member
  • ****
  • Posts: 254
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #10 on: January 09, 2019, 10:58:33 pm »
I need a bit more help. I spent all day on this. I just don't understand the logic... What am I missing?

Code: [Select]
BuyLotsPrice:
    LDA #0
    STA MMC5_tmp+6 ; clear this first
    LDA shop_curitem
    JSR LoadPrice ; gets the price of the item you're trying to buy
    ; tmp, tmp+1, and tmp+2 now carry the price...
    ; MMC5_tmp carries the amount
    ; when using MultiplyXA
    ; A = lower 8 bits (automatically saved to MMC5_multiplyA)
    ; X = higher 8 bits (automatically saved to MMC5_multiplyX)
    LDX MMC5_tmp        ; quantity
    LDA tmp             ; low byte of price
    JSR MultiplyXA
    STA MMC5_tmp+2      ; low byte of combined price
    STX MMC5_tmp+3
   
    LDX MMC5_tmp        ; quantity
    LDA tmp+1           ; middle byte of price
    JSR MultiplyXA
    STA MMC5_tmp+4      ; middle byte of combined price
    STX MMC5_tmp+5
   
    LDA MMC5_tmp+4       
    CLC
    ADC MMC5_tmp+3
    STA MMC5_tmp+4
   
    LDA MMC5_tmp+5
    ;CLC                ; do I need this?
    ADC MMC5_tmp+4
    STA MMC5_tmp+5
   
    LDA MMC5_tmp+6      ; saving carry from last addition
    ADC #0
    STA MMC5_tmp+6
   
    RTS

Code: [Select]
            high mid  low
99 x 3000 = $04, $88, $28
98 x 3000 = $04, $7C, $70
^ my tests...

https://imgur.com/a/RUS2lad - I arranged the things so I can see what's going on with the numbers in memory. Should I be using the high bits of the second multiply for the high byte of the combined price? That would work to make those two tests work, but then at 93 houses, it comes to: $04, $41, $D8 -- except then the high bits from the last multiply are $03...

I just really confused... I'm not a math person. I don't know the steps. I lucked into getting this close by trying stupid things until it got close with a few difficult patterns.
I know exactly what I'm doing. I just don't know what effect it's going to have.

Disch

  • Hero Member
  • *****
  • Posts: 2725
  • NES Junkie
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #11 on: January 09, 2019, 11:48:04 pm »
Rather than debug your code I just wrote my own routine to do it.  I commented and drew a little diagram to show how it works so hopefully you can follow what it's doing.  Note it is completely untested:

Code: [Select]
; SUPPORT ROUTINE
; This routine may or may not be necessary depending on how MultiplyXA works.
;   The important bit here is that C needs to be
;   unchanged by the call.  The PHP/PLP here assure that.  If MultiplyXA preseves
;   C then this routine is not needed and MultiplyXA can be called directly
MultiplyXA_Safe:
    PHP
    JSR MultiplyXA
    PLP
    RTS
   
; The actual multiplication routine
;
;   Goal:  $AABBCC * $EE   (24 bit value * 8 bit value)
;   Visualization:
;
;       AA BB CC
; x           EE
; --------------
;          BD A8   (EE * CC = BDA8)
;       AD DA ..   (EE * BB = ADDA)     (dots are effectively zeros)
; +  9E 0C .. ..   (EE * AA = 9E0C)     (note that all addition must include carry)
; --------------
;    9E BA 97 A8   <-  End result, $AABBCC * $EE = $9EBA97A8

Multiply_24x8:
    @in_24  =   ; low byte of 24-bit value (assume +1 and +2 are med/high bytes)
    @in_8   =   ; low byte of 8-bit value
    @out_32 =   ; output (32-bit value)
    @temp   =   ; some area of temp ram (only 1 byte needed for this code)
   
    CLC                     ; start with C clear
   
    ; low byte (EE * CC)
    LDA @in_8
    LDX @in_24
    JSR MultiplyXA_Safe
    STA @out_32             ; no addition needed for low byte
    STX @temp               ; addition needed for high byte, stuff it for later
   
    ; middle byte (EE * BB)
    LDA @in_8
    LDX @in_24+1
    JSR MultiplyXA_Safe
    ADC $temp               ; add with previous high byte
    STA $out_32+1
    STX $temp               ; for future addition
   
    ; high byte (EE * AA)
    LDA @in_8
    LDX @in_24+2
    JSR MultiplyXA_Safe
    ADC @temp
    STA @out_32+2
   
    ; high byte currently in X.  It does not need full addition, but we do need to add to it
    ;  any carry from the previous addition
    BCC :+
       INX
    :
    STX @out_32+3
   
    ; Done!
    RTS



EDIT:

I should also mention I'm assuming MultiplyXA outputs high byte in X and low byte in A -- since that's the most logical/useful way for that function to work.

EDIT 2:

Typo in code, had a STA instead of a STX
« Last Edit: January 10, 2019, 03:23:10 am by Disch »

Jiggers

  • Sr. Member
  • ****
  • Posts: 254
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #12 on: January 10, 2019, 11:16:21 pm »
Oooohh my gosh. It works. Thank you. I still don't get HOW it works... but it does! I actually thought I could trim it down a bit, because the base item price is only ever going to be 2 bytes--so, 2 bytes into 3 bytes. But it only works with all 4 bytes? THEN I thought I could save space by having it output to tmp AND shop_curprice, but somehow doing two STAs in a row was corrupting the second one. So just had to do LDA tmp, STA shop_curprice for all the parts...

I'm close to updating the main file again with all this stuff. Its looking really good. But then I had a thought: I can trim down the hiding code even MORE if I don't have to deal with the IB/OB stats being loaded different during magical and physical attacks.

Code: [Select]
  @Hide:
  LDA CurrentCharacter ; ($00, $01, $02, $03)
  JSR PrepHide
  LDA #01           ; toggle hiding byte
  STA (tmp+12), Y   ; trouble spot
  RTS 
 
PrepHide:
    ASL A
    TAX
    LDA HideTable, X         
    STA tmp+12           ; these two bytes of tmp are either not used in battle
    LDA HideTable+1, X
    STA tmp+13           ; or not used during a player's turn. So they should be safe to tamper with?
    RTS   
   
HideTable:
  .WORD Character1Hidden ; $5D1F
  .WORD Character2Hidden ; $5D3F
  .WORD Character3Hidden ; $5D5F
  .WORD Character4Hidden ; $5D7F

So I'm debugging this and its working fine. PrepHide loads tmp+12 and tmp+13 with $5D and $xF. But that "STA (tmp+12), Y"... its saving a little bit past there. Screenshot to explain better... Red box: where its saving to. Blue box: Where it should be saving to.

https://imgur.com/a/Dkxeeua

I'll keep fiddling with it...

Edit: I got it. I forgot to set Y.  :P Like a total idiot.
« Last Edit: January 11, 2019, 02:40:51 pm by Jiggers »
I know exactly what I'm doing. I just don't know what effect it's going to have.

Disch

  • Hero Member
  • *****
  • Posts: 2725
  • NES Junkie
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #13 on: January 11, 2019, 12:01:47 am »
I still don't get HOW it works

The code?  Or the mathematical concept?

The mathematical concept is the same as what is used in standard multiplication:

123 * 5 = (100 * 5) + (20 * 5) + (3 * 5)


Which can be determined with some basic algebra:

Code: [Select]
123 * 5                   (original)
(100 + 20 + 3) * 5        (separate digits)
5*100 + 5*20 + 5*3        (distribute the 5)


I'm effectively doing the exact same thing, only rather that separating digits, I'm separating bytes:

Code: [Select]
$112233 * $44                      (original)
($110000 + $2200 + $33) * $44      (separate bytes)
$44*$110000 + $44*$2200 + $44*$33  (distribute)

Jiggers

  • Sr. Member
  • ****
  • Posts: 254
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #14 on: January 12, 2019, 05:27:27 am »
The math concept, I think, is where I get lost. I'd need step by step, line diagram drawings showing every single change, with an explanation of why and how. Probably with Elmo and Big Bird. I had someone try explaining how to multiply without a calculator and after a while I just went "But that CAN'T work with a NES! The numbers aren't connected at all! 256 times 2 doesn't make 512, it makes 256+256!"

After staring a bit, I think I can sense how it works. The distribute line makes the most sense. That's how I handled math in school. Break larger numbers down into easier ones, then re-build the final number. Kind of what I was trying to do--which was correct except for where to add in the high bits?

Anyway, just glad that's all over! Time for another update!



* Added sequence data to restore default Duty settings to all original songs, since my new Marsh Cave song changes it but there was nothing to change it back for other songs.
* Battle and Prologue music's Square 2 channel is now played by the MMC5's SQ2 channel so its not interrupted by SFX.
* Re-wrote Hiding code to be even more space-efficient!
* Wrote some un-space-efficient code to allow buying 1-99 items in Item shops only.
* Re-organized Character Stat data storage. Now have 24 continuous free bytes for each character.
* Re-organized my new MMC5 variables to share space where possible.
* Did a few more spots of data cleanup. Enemy stats now ready for direct editing thanks to the FFbytes docs by Dienyddiwr Da - http://www.romhacking.net/documents/81/

To-Do:
* Figure out how ChaosDeath erases the battle background, because the background is now smaller and it will erase the boxes...?
* Go through the zero-page RAM wossits to find any unused spots and see if I can shift things around to put more audio channel stuff there instead of in MMC5 RAM. Might not be worth the effort.
* Use 24 leftover ch_stat bytes to index spells. 3 spells, 8 levels, 24 bytes!
* Combine ch_class and ch_sprite into high/low bytes. 1 more byte to use.
* ch_exptonext probably doesn't have to be saved. If it can be calculated and saved, it can be calculated and printed each time the status screen is looked at. 2 more bytes saved.
* ch_hidden doesn't need to be in the 64 bytes per character. 4 bytes saved in total!
* Character level can be used to index max MP. Current MP can be squeezed into 4 bytes possibly. First byte high: level 1. First byte low: level 2, and so on.
* This would free up 256 bytes for more game_flags (chests, npcs, events?). Possibly makes room to save more than 1 game at a time??



Question: Is it normal for an MMC5 rom's save file to be 64kb (using Mesen)? First $400 bytes is the "unsram" stuff, which I figured was UNSaved RAM. Second $400 bytes is a copy; the saved RAM. Then $1200 bytes of other stuff (I see its map data) and then like $8000 of 0s. So uh. Do I even need to be making space to make more save game slots??

Even the original game's save file is 8kb...

I suppose I could make a "Save and quit" feature that over-writes the map data, and be more vigilant about the original variables while moving them over to the work RAM in $5C00--freeing up another $400 for save data. Makes 2 save games and a third save file that gets clobbered on load and clobbers map data when saving and shutting down...?
I know exactly what I'm doing. I just don't know what effect it's going to have.

Disch

  • Hero Member
  • *****
  • Posts: 2725
  • NES Junkie
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #15 on: January 12, 2019, 02:32:34 pm »
Even the original game's save file is 8kb

There's a single RAM chip and the entire thing gets saved.  So the whole 8K chunk is saved -- but the game doesn't actually USE all of it for saved data.  Most of it is just used for additional workspace RAM and doesn't NEED to be saved, even though it still is.

Quote
Is it normal for an MMC5 rom's save file to be 64kb (using Mesen)?

Yes, that's normal.  Determining how much SRAM an MMC5 game has is difficult/unreliable, so the easiest way for an emu is to assume it's just using the most possible (which for the MMC5 is 64K) and just save all of it.

Realistically, I think the typical setup is to only have one of the SRAM chips battery backed, so it would probably make more sense to only save 32K --- but saving 64K is easier and safer for the emulator.  If you're worried about which SRAM would actually get saved on a real cartridge, that's a slightly trickier question that I don't immediately have the answer to.  I *think* it's the 2nd chip (so the second block of 32K, not the first) that has the battery on most carts.  But don't quote me on that.

Quote
Do I even need to be making space to make more save game slots??

Probably.  Whatever RAM you're using for save data can't be used by anything else in the game ever -- it has to exclusively hold the save data (unless you want the save data to get clobbered for some reason).  And FF uses most of the RAM for things like map data and whatnot.

Quote
I suppose I could make a "Save and quit" feature that over-writes the map data,

If you do that, the save data will be clobbered as soon as you resume the game and map data overwrites your save game.  I wouldn't recommend it.  And what happens when someone tries to resume a game that wasn't saved this way, and you just end up "resuming" a trash game that gets built out of arbitrary map data that happened to be in memory at the time?

Quote
moving them over to the work RAM in $5C00

It'd probably be a lot easier to just swap to a different RAM page and put your saved games there.  Remember, even without ExRAM MMC5 gives you a full 64K to work with.  You just have to swap to it.

Quote
a third save file that gets clobbered on load and clobbers map data when saving and shutting down...?

You can try that if you want, but personally I don't think that's a very good idea.

Jiggers

  • Sr. Member
  • ****
  • Posts: 254
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #16 on: January 12, 2019, 04:30:40 pm »
It'd probably be a lot easier to just swap to a different RAM page and put your saved games there.  Remember, even without ExRAM MMC5 gives you a full 64K to work with.  You just have to swap to it.

O...oh. Well... I think I'll just do that, then.

Was a nice thought experiment to cram magic and MP into 28 bytes anyway though. XD
I know exactly what I'm doing. I just don't know what effect it's going to have.

Bregalad

  • Hero Member
  • *****
  • Posts: 2641
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #17 on: January 12, 2019, 04:54:21 pm »
The math concept, I think, is where I get lost.
Did you learn how to do multiplications by hand in columns back you when at primary scool ? I learnt that but I don't know if it's still taught to kids... hopefully it is. When multiplying two numbers on the 6502 which lacks a multiply instruction, it's exactly the same technique, except you use "1" and "0" digits instead of the regular "0-9" digits (this makes single-bit multiplication extremely simple as it becomes a simple AND operation), and use binary addition instread of regular addition.

When you're lucky enough to have a MMC5 that can do a 8x8->16 multiply in a couple of cycles you do it using bytes istead of "0-9" digits, still the same technique. Inidivual digits (that is, bytes) within the large numbers have to be multiplied each with eachother, and then shifted and added using the good old primary scool technique.

Jiggers

  • Sr. Member
  • ****
  • Posts: 254
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #18 on: January 15, 2019, 02:08:06 am »
Well, uh... I was only really in school for a few months. We were given a math book a grade above ours and given calculators. Most of it was about shapes and doing weird puzzle things like... "8(12+4)(17-12)" and so on... just really long strings of those, is what I remember. So I never had to do multiplication or division the hard way. Trying to get my GED someday is going to suck probably. Eh.

Only a small update today...

Added in a new way to calculate who goes first in battle. Takes the player's luck stat, adds it with a random number between 1 and 50; takes the enemy's morale, divides it twice, adds it with a number between 1 and 50. If there are two identical numbers, it favours the second in line from the initial LUT of enemies 1-9, players 1-4. Not sure yet if it this is going to be fair later on. Or if its fair now.

Fixed a minor bug I caused that was turning everyone's weapons into their own palettes. It was only supposed to do that for fists! Then I thought all unarmed attacks should have fists. Then I changed my mind.

I figured out how to swap RAM, but I have to do more poking to see how to swap things over. I had it swap before a battle transition and it basically put me in battle with everyone's stats being 0s. All fighters, no names, no health... hah.


Some new bugs popped up now... White Mage's critical strength boost mucks up their sprite. Casting magic on someone puts them IN hiding now... fun things.
Fixed those, but Garland gives 1 point of experience with EXP Gain on HIGH? Fixed that, too. Guess ya gotta start with the low byte when multiplying with ASL and ROL.

Also made yet another thief boost: they will now try to hide during their turn when the party is surprised. Too much? Is it enough that the critical hit chance of weapons is fixed, that they can earn gold when doing a critical hit, and that their stats are boosted while attacking from hiding? I guess I can stop un-nerfing them now?  :P

Question: How show INT work? I know Anomie did something, but then FF Restored did it a different way... which do people prefer? Keeping in mind I have no idea how to copy their work exactly...
« Last Edit: January 15, 2019, 05:02:41 pm by Jiggers »
I know exactly what I'm doing. I just don't know what effect it's going to have.

Vanya

  • Hero Member
  • *****
  • Posts: 1489
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #19 on: January 15, 2019, 08:18:43 pm »
Short of actually adding a Steal command, I think the Thief is good without the auto-hide on surprise attacks. Maybe, if you could have them try to auto-hide when they are critical it might work better as a final un-nerf.

I think the INT patch by Anomie and the one used in FF Restored is like pretty much the same, no? Or at least very similar. Either one is fine.

As for the turn order, I think what would make sense is if it was mainly based on the AGI stat. With the LCK stat adding to the random number. This would make predicting turn order for your party more reliable.