Post Reply 
Final Fantasy Mystic Quest - Some Random Code Digging
12-11-2017, 04:08 PM
Post: #1
Brick Final Fantasy Mystic Quest - Some Random Code Digging
Couldn't get as much done as I wanted, but I think it's a good point to stop for today when the emulator stops playing the game in the correct speed and crashes after leaving the title screen... yeah... big fun.

So, here are some notes so far. Maybe one can already use them. Oh, I used the file "Final Fantasy - Mystic Quest (U) (V1.0) [!].smc".

Quote:BG1 Tilemap seems like being always at $4000 in VRAM.
BG2 Tilemap seems like being always at $4800 in VRAM.
BG1 is used for the landscape in the first world map screen (in the intro).
BG2 is used for the clouds in the first world map screen.
BG1 is used for the whole map in the intro scene (the mountain side with the view on Focus Tower).
BG2 is used for the mountain that crumbles after the hero jumps off of it.
BG1 is used for the monster graphics in (the first) battle.
BG2 is used for the bg in battle.

These are just some more or less wild guessings after peeking into the code for about half an hour, so be warned that I might be totally wrong:

Quote:
$00835E - VRAM DMA (to $4400) for Battle Menus
$009998 - Set a number of registers to a certain double byte. Y= Register to begin with, A= number of double bytes(!) to do, max: $40, X= value (16-bit)
$01836C - Transfer of the first Sprite Palette
$0184B8 - VRAM DMA of the status bar
$0C8DD1 - DMA for VRAM Clearing at Game Startup
$0C9075 - VRAM DMA for the Crystals
$0C8FF4 - Transfering the Title Screen graphics during the Mode 7 part of the intro

So, yeah, still a long way to go. I haven't found (yet) what I expected, I thought they would have stored the tilemaps in WRAM and would simply transfer it to VRAM as is, but it seems like they somehow organized it a bit different (maybe they manually added the same high byte, or they splitted up high byte and low byte and add them before they transfer it to VRAM). Long story short, I'll have to give it another shot, and a more whole-hearted one than today.

Me on Twitter
Visit this user's website Find all posts by this user
Quote this message in a reply
12-11-2017, 06:24 PM
Post: #2
RE: Final Fantasy Mystic Quest - Some Random Code Digging
(12-11-2017 04:08 PM)lytron Wrote:  Couldn't get as much done as I wanted, but I think it's a good point to stop for today when the emulator stops playing the game in the correct speed and crashes after leaving the title screen... yeah... big fun.

So, here are some notes so far. Maybe one can already use them. Oh, I used the file "Final Fantasy - Mystic Quest (U) (V1.0) [!].smc".

Quote:BG1 Tilemap seems like being always at $4000 in VRAM.
BG2 Tilemap seems like being always at $4800 in VRAM.
BG1 is used for the landscape in the first world map screen (in the intro).
BG2 is used for the clouds in the first world map screen.
BG1 is used for the whole map in the intro scene (the mountain side with the view on Focus Tower).
BG2 is used for the mountain that crumbles after the hero jumps off of it.
BG1 is used for the monster graphics in (the first) battle.
BG2 is used for the bg in battle.

These are just some more or less wild guessings after peeking into the code for about half an hour, so be warned that I might be totally wrong:

Quote:
$00835E - VRAM DMA (to $4400) for Battle Menus
$009998 - Set a number of registers to a certain double byte. Y= Register to begin with, A= number of double bytes(!) to do, max: $40, X= value (16-bit)
$01836C - Transfer of the first Sprite Palette
$0184B8 - VRAM DMA of the status bar
$0C8DD1 - DMA for VRAM Clearing at Game Startup
$0C9075 - VRAM DMA for the Crystals
$0C8FF4 - Transfering the Title Screen graphics during the Mode 7 part of the intro

So, yeah, still a long way to go. I haven't found (yet) what I expected, I thought they would have stored the tilemaps in WRAM and would simply transfer it to VRAM as is, but it seems like they somehow organized it a bit different (maybe they manually added the same high byte, or they splitted up high byte and low byte and add them before they transfer it to VRAM). Long story short, I'll have to give it another shot, and a more whole-hearted one than today.

That's good stuff! I just hope the map data itself in the ROM isn't compressed because that'll screw me since I just cannot deal with compression.

[Image: jce3000gt_md.png]

[Image: jce3000gt.jpg]
Visit this user's website Find all posts by this user
Quote this message in a reply
12-12-2017, 04:21 AM (This post was last modified: 12-12-2017 01:40 PM by lytron.)
Post: #3
RE: Final Fantasy Mystic Quest - Some Random Code Digging
After trying around for about an hour (with all the usual stuff - trying to remove the config files, trying to copy the program to another place, desperately searching the registry for something), I found the way to make my snes9x + geiger debugger running the ROM properly again:

Whenever I log something or have a breakpoint set, the ROM runs perfectly fine. If not, the game starts lagging on the title screen, even more lagging in the naming screen and crashes afterwards.

Besides that, I found another bit of clues this morning:

Quote:The subroutine at $00/8DDF (or so, don't quote me on that, I do this from the top of my head right now) is the one which seems to be used for VRAM transfers. The most weird thing is that this part/line of the code does not get executed in the transition from the short world map view to the mountain map.

I hope to find the time and brain power this evening (i.e. around 1 pm Standard Texan Time) to actually look into the program flow and not just jumping around with CTRL + F and hoping to find it the easy way.

Aside from that:

Quote:This mathematical subroutine I pointed out ($00/9998 I think) seems to be involved in the "map decompression". It might be used to repeat the same tile several times. At least it is used in the buffer for BG3 tilemap, which is buffered at... $7E2000, I think. BG3 is used for the status menu and, I think, Textboxes.

So, this might be of interest if you are looking into text hacking. Is known how this is done, BTW, or is there, too, some new ground to break? Kinda? Sorta?

(12-11-2017 06:24 PM)JCE3000GT Wrote:  That's good stuff! I just hope the map data itself in the ROM isn't compressed because that'll screw me since I just cannot deal with compression.

Might be no problem, though, even if the original maps are compressed. Might be as easy as it was on Sim City:

The original maps are compressed, yet the compression subroutine had a command for "the next dozen bytes should be transfered as they are written". So, after it did not work out for me to get my map compressed properly, I did it the easy and ugly way and wrote with this "decompression command" the whole uncompressed into the ROM. Filled about half a bank, but it works. And thanks to some Excel Spreadsheet Formula trickery, I had not to write that all by hand.

So, may be it'll work that way. And since the graphics of FFMQ are not as elaborate as the ones of latter Squaresoft games, doing the (basic) map design in spreadsheets looks like a good idea.

First bunch:

New notes - I hope this counts for everything in the game, but up until now, I only checked the very beginning, of course:

Code:
01/84B8 VRAM DMA of Hero Sprite, goes to VRAM $6100-$67FF
7F/4000-4BFF Buffer of the Hero Sprite
01/8492 VRAM DMA for all other Sprites
7F/0000-2DFF Buffer for all other Sprites

01/836C or
01/836F CGRAM Updater for the Sprite-Palettes. If entered at $836C, whole Sprite-half of the CGRAM gets updated.
01/839E - Table for aforementioned subroutine

$7E/1A4C - Jump TAble Pointer for Subroutine at $01/FE6B
$01/FE7A - Jump Table for $01FE6B

If someone is interested and/or I can't fight the desire, I can explain that CGRAM-Subroutine.

Other than that: Yeah, looks like there is a map compression. At least one that builds the 16x16 tiles we recognize in-game out of the 8x8 graphical tiles (Is clear what I mean by this, or am I talking gibberish in public, again?). But, as I said, should be nothing to worry about.
The Program stores the decompressed map data for one BG (BG1?) into $7E/0800-FF and of the other (BG2?) in $900-FF, and then transfers it to VRAM with its own DMA-Pipeline-Subroutine, which I disassemble here:

Code:
$01/83CB A2 00 00    LDX #$0000              ; Reset Pipeline Entry Counter
$01/83CE BC 0B 1A    LDY $1A0B,x[$01:1A0B]   ; Load Number of bytes to do for this Pipeline Entry
$01/83D1 F0 2C       BEQ $2C    [$83FF]      ; If Number-of-Bytes-to-do is zero, this entry (and thus, all the rest of the pipeline) is empty and we can exit
$01/83D3 8C 05 43    STY $4305  [$01:4305]   ; Else, store in the DMA register for Number-of-Bytes-to-Do
$01/83D6 A0 01 18    LDY #$1801              ; DMA Settings / Destination ($18 = $2118 = VRAM)
$01/83D9 8C 00 43    STY $4300  [$01:4300]
$01/83DC BC 03 1A    LDY $1A03,x[$01:1A03]   ; Load Source Address
$01/83DF 8C 02 43    STY $4302  [$01:4302]
$01/83E2 A9 00       LDA #$00                ; Source must be on $00
$01/83E4 8D 04 43    STA $4304  [$01:4304]
$01/83E7 BC FB 19    LDY $19FB,x[$01:19FB]   ; Load and set destination in VRAM from Pipeline
$01/83EA 8C 16 21    STY $2116  [$01:2116]
$01/83ED AD FA 19    LDA $19FA  [$01:19FA]   ; VRAM Transfer settings - one for all Pipeline Entries
$01/83F0 8D 15 21    STA $2115  [$01:2115]
$01/83F3 A9 01       LDA #$01                ; Activate DMA
$01/83F5 8D 0B 42    STA $420B  [$01:420B]
$01/83F8 E8          INX                     ; Next Pipeline Entry
$01/83F9 E8          INX
$01/83FA E0 08 00    CPX #$0008              ; Check if already all four Pipeline Entries are done
$01/83FD D0 CF       BNE $CF    [$83CE]      ; If not, Loop and do the next
$01/83FF 60          RTS                     ; Else, Exit

I highly doubt that this subroutine is ever used for something else than the transfer of these decompressed map slices.
But, this way, we learned the purpose of some new WRAM addresses!

Code:
$7E19FA - VRAM transfer settings ($2115) for all current Pipeline entries
$7E19FB/C - Pipe Line Entry #1 - VRAM Destination
$7E19FD/E - Pipe Line Entry #2 - VRAM Destination
$7E19FF/A00 - Pipe Line Entry #3 - VRAM Destination
$7E1A01/2 - Pipe Line Entry #4 - VRAM Destination
$7E1A03/4 - Pipe Line Entry #1 - Source Address (on Bank $00)
$7E1A05/6 - Pipe Line Entry #2 - Source Address (on Bank $00)
$7E1A07/8 - Pipe Line Entry #3 - Source Address (on Bank $00)
$7E1A09/A - Pipe Line Entry #4 - Source Address (on Bank $00)
$7E1A0B/C - Pipe Line Entry #1 - Number of (Double?)-Bytes to transfer
$7E1A0D/E - Pipe Line Entry #2 - Number of (Double?)-Bytes to transfer
$7E1A0F/10 - Pipe Line Entry #3 - Number of (Double?)-Bytes to transfer
$7E1A11/2 - Pipe Line Entry #4 - Number of (Double?)-Bytes to transfer

Okay, now I'll take a look at this decompression stuff.

Second bunch and last bunch of today. These double-posts of mine get put together, which might make sense. Yet, no one sees that I kept my promise and did something on this evening. But this is my fate and I'll bear it...

I post here what I already commented on. It's somewhat the last part of it all, but since I literally reverse-engineer it, this makes sense. Already found out some of those assisting/buffering registers, guess I should write a short note about them tomorrow.

Code:
$01/FC8E 8D 3A 1A    STA $1A3A  [$01:1A3A]   A:1400 X:0000 Y:1400 P:envMxdiZc
$01/FC91 C2 20       REP #$20                A:1400 X:0000 Y:1400 P:envMxdiZc
$01/FC93 98          TYA                     A:1400 X:0000 Y:1400 P:envmxdiZc
$01/FC94 E2 20       SEP #$20                A:1400 X:0000 Y:1400 P:envmxdizc
$01/FC96 EB          XBA                     A:1400 X:0000 Y:1400 P:envMxdizc
$01/FC97 8D 02 42    STA $4202  [$01:4202]   A:0014 X:0000 Y:1400 P:envMxdizc
$01/FC9A AD 24 19    LDA $1924  [$01:1924]   A:0014 X:0000 Y:1400 P:envMxdizc
$01/FC9D 8D 03 42    STA $4203  [$01:4203]   A:0040 X:0000 Y:1400 P:envMxdizc
$01/FCA0 EB          XBA                     A:0040 X:0000 Y:1400 P:envMxdizc
$01/FCA1 C2 20       REP #$20                A:4000 X:0000 Y:1400 P:envMxdiZc
$01/FCA3 29 3F 00    AND #$003F              A:4000 X:0000 Y:1400 P:envmxdiZc
$01/FCA6 18          CLC                     A:0000 X:0000 Y:1400 P:envmxdiZc
$01/FCA7 6D 16 42    ADC $4216  [$01:4216]   A:0000 X:0000 Y:1400 P:envmxdiZc
$01/FCAA 18          CLC                     A:0500 X:0000 Y:1400 P:envmxdizc
$01/FCAB 6D 2F 1A    ADC $1A2F  [$01:1A2F]   A:0500 X:0000 Y:1400 P:envmxdizc
$01/FCAE AA          TAX                     A:0500 X:0000 Y:1400 P:envmxdizc
$01/FCAF A9 00 00    LDA #$0000              A:0500 X:0500 Y:1400 P:envmxdizc
$01/FCB2 E2 20       SEP #$20                A:0000 X:0500 Y:1400 P:envmxdiZc
$01/FCB4 BF 00 80 7F LDA $7F8000,x[$7F:8500] A:0000 X:0500 Y:1400 P:envMxdiZc
$01/FCB8 4D 3A 1A    EOR $1A3A  [$01:1A3A]   A:0074 X:0500 Y:1400 P:envMxdizc
$01/FCBB 10 02       BPL $02    [$FCBF]      A:0074 X:0500 Y:1400 P:envMxdizc
$01/FCBF C2 20       REP #$20                A:0074 X:0500 Y:1400 P:envMxdizc
$01/FCC1 29 7F 00    AND #$007F              A:0074 X:0500 Y:1400 P:envmxdizc
$01/FCC4 A8          TAY                     A:0074 X:0500 Y:1400 P:envmxdizc
$01/FCC5 0A          ASL A                   A:0074 X:0500 Y:0074 P:envmxdizc
$01/FCC6 0A          ASL A                   A:00E8 X:0500 Y:0074 P:envmxdizc
$01/FCC7 AA          TAX                     A:01D0 X:0500 Y:0074 P:envmxdizc
$01/FCC8 BF F4 CE 7F LDA $7FCEF4,x[$7F:D0C4] A:01D0 X:01D0 Y:0074 P:envmxdizc
$01/FCCC 8D 35 1A    STA $1A35  [$01:1A35]   A:CFCE X:01D0 Y:0074 P:eNvmxdizc
$01/FCCF BF F6 CE 7F LDA $7FCEF6,x[$7F:D0C6] A:CFCE X:01D0 Y:0074 P:eNvmxdizc
$01/FCD3 8D 37 1A    STA $1A37  [$01:1A37]   A:DFDE X:01D0 Y:0074 P:eNvmxdizc
$01/FCD6 E2 20       SEP #$20                A:DFDE X:01D0 Y:0074 P:eNvmxdizc
$01/FCD8 BB          TYX                     A:DFDE X:01D0 Y:0074 P:eNvMxdizc
$01/FCD9 BF F4 D0 7F LDA $7FD0F4,x[$7F:D168] A:DFDE X:0074 Y:0074 P:envMxdizc
$01/FCDD 8D 39 1A    STA $1A39  [$01:1A39]   A:DF00 X:0074 Y:0074 P:envMxdiZc
$01/FCE0 8D 3C 1A    STA $1A3C  [$01:1A3C]   A:DF00 X:0074 Y:0074 P:envMxdiZc
$01/FCE3 10 07       BPL $07    [$FCEC]      A:DF00 X:0074 Y:0074 P:envMxdiZc
code is missing here
$01/FCEC E2 10       SEP #$10                A:DF00 X:0074 Y:0074 P:envMxdiZc
$01/FCEE A2 00       LDX #$00                A:DF00 X:0074 Y:0074 P:envMXdiZc
$01/FCF0 9B          TXY                     A:DF00 X:0000 Y:0074 P:envMXdiZc
$01/FCF1 B9 35 1A    LDA $1A35,y[$01:1A35]   A:DF00 X:0000 Y:0000 P:envMXdiZc
$01/FCF4 9D 3D 1A    STA $1A3D,x   ; Set Low Byte for Tilemap entry
$01/FCF7 DA          PHX                     A:DFCE X:0000 Y:0000 P:eNvMXdizc
$01/FCF8 AA          TAX                     A:DFCE X:0000 Y:0000 P:eNvMXdizc
$01/FCF9 4E 3C 1A    LSR $1A3C     ; To make it short: Logic Shift Right $1A3C once...
$01/FCFC 6A          ROR A         ; ... if the Original LSB of $1A3C was set, A is #$40, else A is #$00
$01/FCFD 6A          ROR A         ; ... which is the Horizontal-Flip?-Flag for this tile
$01/FCFE 29 40       AND #$40
$01/FD00 EB          XBA           ; Buffer that in the hidden part of the 8-bit Accumulator
$01/FD01 AD 39 1A    LDA $1A39  [$01:1A39]   A:00DF X:00CE Y:0000 P:eNvMXdizC
$01/FD04 30 09       BMI $09       ; [$FD0F] Use the same palette for this tile if MSB was set
$01/FD06 BF 74 F2 7F LDA $7FF274,x ; Load Number-of-Palette-to-use-for-tile
$01/FD0A 0A          ASL A         ; Move it in the right position so it can be added to the high byte later
$01/FD0B 0A          ASL A
$01/FD0C 8D 3B 1A    STA $1A3B     ; Buffer value
$01/FD0F EB          XBA           ; Restore Horizontal-Flip-Flag in A
$01/FD10 FA          PLX                     A:0400 X:00CE Y:0000 P:envMXdiZc
$01/FD11 0D 34 1A    ORA $1A34  [$01:1A34]   A:0400 X:0000 Y:0000 P:envMXdiZc
$01/FD14 0D 3B 1A    ORA $1A3B     ; Add Number-of-Palette-to-use-for-tile to High Byte
$01/FD17 9D 3E 1A    STA $1A3E,x   ; Set High Byte for Tilemap entry
$01/FD1A E8          INX           ; Increment Store index for tilemap entry buffers twice
$01/FD1B E8          INX
$01/FD1C C8          INY           ; Increment Loop counter
$01/FD1D C0 04       CPY #$04
$01/FD1F D0 D0       BNE $D0       ; [$FCF1] Repeat until all 4 tilemap entries are done
$01/FD21 C2 10       REP #$10      ; X/Y = 16 bit
$01/FD23 60          RTS


$01/FA18 7A          PLY                     A:0404 X:0008 Y:0004 P:envMxdiZC
$01/FA19 C2 20       REP #$20      ; A = 16 bit
$01/FA1B AD 3D 1A    LDA $1A3D     ; Transfer decompressed tiles into the buffer
$01/FA1E 99 00 08    STA $0800,y
$01/FA21 AD 3F 1A    LDA $1A3F
$01/FA24 99 02 08    STA $0802,y
$01/FA27 AD 41 1A    LDA $1A41
$01/FA2A 99 80 08    STA $0880,y
$01/FA2D AD 43 1A    LDA $1A43
$01/FA30 99 82 08    STA $0882,y
$01/FA33 E2 20       SEP #$20      ; A = 8 bit
$01/FA35 C8          INY           ; Increment Store Index by 4
$01/FA36 C8          INY
$01/FA37 C8          INY
$01/FA38 C8          INY
$01/FA39 AD 31 1A    LDA $1A31  [$01:1A31]   A:04DF X:0008 Y:0004 P:envMxdizC
$01/FA3C 1A          INC A                   A:0400 X:0008 Y:0004 P:envMxdiZC
$01/FA3D CD 24 19    CMP $1924  [$01:1924]   A:0401 X:0008 Y:0004 P:envMxdizC
$01/FA40 90 04       BCC $04    [$FA46]      A:0401 X:0008 Y:0004 P:eNvMxdizc
code is missing here
$01/FA46 8D 31 1A    STA $1A31  [$01:1A31]   A:0401 X:0008 Y:0004 P:eNvMxdizc
$01/FA49 C0 44 00    CPY #$0044              A:0401 X:0008 Y:0004 P:eNvMxdizc
$01/FA4C D0 C0       BNE $C0    [$FA0E]      A:0401 X:0008 Y:0004 P:eNvMxdizc


$01/FA4E A9 80       LDA #$80       ; Set VRAM transfer settings (for $2115) to $80
$01/FA50 8D FA 19    STA $19FA
$01/FA53 C2 20       REP #$20                A:0480 X:0008 Y:0044 P:eNvMxdizC
$01/FA55 AD BD 19    LDA $19BD  [$01:19BD]   A:0480 X:0008 Y:0044 P:eNvmxdizC
$01/FA58 49 FF FF    EOR #$FFFF     ; Bitwise complement
$01/FA5B 29 0F 00    AND #$000F     ; Set the lowest nybble free
$01/FA5E 1A          INC A          ; + 1 * 4
$01/FA5F 0A          ASL A
$01/FA60 0A          ASL A
$01/FA61 8D 0B 1A    STA $1A0B  [$01:1A0B]   A:0040 X:0008 Y:0044 P:envmxdizc
$01/FA64 8D 0D 1A    STA $1A0D  [$01:1A0D]   A:0040 X:0008 Y:0044 P:envmxdizc
$01/FA67 A9 44 00    LDA #$0044              A:0040 X:0008 Y:0044 P:envmxdizc
$01/FA6A 38          SEC                     A:0044 X:0008 Y:0044 P:envmxdizc
$01/FA6B ED 0B 1A    SBC $1A0B  [$01:1A0B]   A:0044 X:0008 Y:0044 P:envmxdizC
$01/FA6E 8D 0F 1A    STA $1A0F  [$01:1A0F]   A:0004 X:0008 Y:0044 P:envmxdizC
$01/FA71 8D 11 1A    STA $1A11  [$01:1A11]   A:0004 X:0008 Y:0044 P:envmxdizC
$01/FA74 A9 00 08    LDA #$0800     ; Source Address of the Pipeline Entry #1: $00/0800
$01/FA77 8D 03 1A    STA $1A03
$01/FA7A 18          CLC            ; Source Address of Pipeline Entry #3: $00/0800 + Size of Entry #1
$01/FA7B 6D 0B 1A    ADC $1A0B
$01/FA7E 8D 07 1A    STA $1A07
$01/FA81 A9 80 08    LDA #$0880     ; Source Address of the Pipeline Entry #2: $00/0880
$01/FA84 8D 05 1A    STA $1A05
$01/FA87 18          CLC            ; Source Address of Pipeline Entry #4: $00/0880 + Size of Entry #2
$01/FA88 6D 0D 1A    ADC $1A0D
$01/FA8B 8D 09 1A    STA $1A09
$01/FA8E 20 24 FD    JSR $FD24      ; Calculate the offset of the VRAM destination

$01/FD24 E2 20       SEP #$20       ; A = 8 bit
$01/FD26 A2 00 00    LDX #$0000     ; Clear X
$01/FD29 AD BF 19    LDA $19BF      ; Calculate the offset of the current row in the tilemap...
$01/FD2C 8D 02 42    STA $4202      ; ... by taking the current row number and multiplicating it with #$40...
$01/FD2F A9 40       LDA #$40       ; (each tilemap row is $40 bytes long)
$01/FD31 8D 03 42    STA $4203
$01/FD34 AD BD 19    LDA $19BD      ; Load the number of the current tile in this tilemap row
$01/FD37 89 10       BIT #$10       ; Has the number of tiles in this row reached $10?
$01/FD39 F0 02       BEQ $02        ; [$FD3D] If not, go on...
missing code here: e8 e8 - INX INX  ; ... if it has, increment X by two
$01/FD3D 0A          ASL A          ; multiplicate by 2 (because two bytes per tile map entry)
$01/FD3E C2 20       REP #$20       ; A = 16-bit
$01/FD40 29 1E 00    AND #$001E     ; Remove if it surpassed $1E (and remove everything that still might be in the upper half of the Accumulator)
$01/FD43 18          CLC
$01/FD44 7D 4C FD    ADC $FD4C,x    ; If 19BD < #$10, add #$4000, else #$4400 (VRAM base for BG tilemap)
$01/FD47 18          CLC
$01/FD48 6D 16 42    ADC $4216      ; Add the result of current tilemap row * #$40
$01/FD4B 60          RTS

00 40 00 44

$01/FA91 8D FB 19    STA $19FB     ; VRAM Destination of Entry #1
$01/FA94 18          CLC           ; + 20 = Destination of Entry #2 (one tilemap row below Entry #1)
$01/FA95 69 20 00    ADC #$0020
$01/FA98 8D FD 19    STA $19FD
$01/FA9B 49 00 04    EOR #$0400    ; Change one bit (go either $400 bytes up or down)
$01/FA9E 29 C0 47    AND #$47C0    ; Make sure that bit change won't make the data go off-bounds in VRAM
$01/FAA1 8D FF 19    STA $19FF     ; VRAM Destination of Entry #3
$01/FAA4 18          CLC           ; + 20 = Destination of Entry #4 (one tilemap row below Entry #3)
$01/FAA5 69 20 00    ADC #$0020
$01/FAA8 8D 01 1A    STA $1A01
$01/FAAB E2 20       SEP #$20      ; 8-bit A, again
$01/FAAD 60          RTS

Me on Twitter
Visit this user's website Find all posts by this user
Quote this message in a reply
12-12-2017, 10:31 PM
Post: #4
RE: Final Fantasy Mystic Quest - Some Random Code Digging
Wow this is promising! I'd like to see how this will work in action. I'm going to be swamped the next couple weeks but in January I will have some freetime! I'd love to be able to see if editing maps is something feasible. :)

Nice work!

[Image: jce3000gt_md.png]

[Image: jce3000gt.jpg]
Visit this user's website Find all posts by this user
Quote this message in a reply
12-13-2017, 02:14 AM (This post was last modified: 12-13-2017 05:41 AM by lytron.)
Post: #5
RE: Final Fantasy Mystic Quest - Some Random Code Digging
Progress

   

(First Post in a long list of crammed-together double-posts, hah!)

Nothing is more fresh than the first cup of double-post of the day!

The screenshot is the first "proof" that I am on the right track, though it is no real hack - I set a breakpoint at $01/FCAF and then manually edited the content of the WRAM at $7F/8500. So, this proves that the decompressed map data (of some sort) is at $7F/8500 (for that intro stage, seems to be flexible and always around $7F/8000).
So, the stuff I disassembled yesterday isn't actually the map decompression, but the tile map composition based on the decompressed map data.
I think I found where the map data gets decompressed, too, and... thats weird.
They wrote a subroutine that writes its code itself, which is always a curious thing.
The transfer of data happens by means of the MVN command. They use it for small chunks of data (less then sixteen bytes). The MVN command works this way: You load values in A, X and Y. A contains the number of Bytes to do, X and Y contains the source and destination addresses. The MVN operation has two arguments, which is the source and destination BANK. These two arguments/bytes are the reason why this code has to be in RAM, since the program changes these two bytes as it needs.
Can't wait to dive deeper into this stuff!

BTW: When I tested the changed WRAM data to make that screenshot, the Map was shifted about ten tiles to the right, the hero moved too far to the right. Might be that I unintentionally triggered some special command through a typo, but hopefully not! >_<

Some other notes on the tile map composion:
Code:
$1924 - LENGTH OF A MAP ROW!?!?!? (i.e. horizontal size of a map?!?!)
$1A35 - Tile #1 Lowbyte
$1A36 - Tile #2 Lowbyte
$1A37 - Tile #3 Lowbyte
$1A38 - Tile #4 Lowbyte
$1A3A - EOR stuff for decompressed Map Data
$1A3B - Buffer for Palette bits, ready to be added to the Highbyte
$7FCEF4 - "Data Table for Tiles 1" - Tilemap Entry Lowbyte - see below
$7FD0F4 - "Data Table for Tiles 2" - Horizontal Flip/Keep Palette see below

The two "Data Table for Tiles" at $7F/CEF4 and $7F/D0F4 are quite interesting. Each entry of Table 1 is 4 bytes in length, Table 2 entries are one byte in size. Values of the first Table get set in $1A35-8 (see $01/FCC8), the data of the second Table gets stored in $1A39 and $1A3C.
The data of the first table gets transfered as-is to the buffer of the tilemap entries (this is the tile number). The data of the second table is a number of flags:
Code:
7654321
xd-c-b-a
x =  Relevant in $1A39 - Should the palette be changed for this tile?
d = Relevant in $1A3C - horizontal flip flag for Tile 4
c = Relevant in $1A3C - horizontal flip flag for Tile 3
b = Relevant in $1A3C - horizontal flip flag for Tile 2
a = Relevant in $1A3C - horizontal flip flag for Tile 1

Me on Twitter
Visit this user's website Find all posts by this user
Quote this message in a reply
12-13-2017, 12:25 PM
Post: #6
RE: Final Fantasy Mystic Quest - Some Random Code Digging
Okay, I think I got it:

The Compressed Data is build up out of:
First two Bytes - Number of Decompression Command Bytes
Decompression Command Bytes
Actual Data

So, the Low Nybble of the Command Byte tells the number of Bytes that should be transfered unchanged. If the High Nybble is set, there is some actual Decompression.

That means:
We have $28 (forty) free banks in the ROM, there you can put completely uncompressed maps, and all you have to do is put a bunch of $0F $0F $0F bytes in front of 'em.

Looks like this is going to work. But I guess, I have to do some testing by myself and do some proper tutorial on it.

Me on Twitter
Visit this user's website Find all posts by this user
Quote this message in a reply
12-13-2017, 01:54 PM
Post: #7
RE: Final Fantasy Mystic Quest - Some Random Code Digging
(12-13-2017 12:25 PM)lytron Wrote:  Okay, I think I got it:

The Compressed Data is build up out of:
First two Bytes - Number of Decompression Command Bytes
Decompression Command Bytes
Actual Data

So, the Low Nybble of the Command Byte tells the number of Bytes that should be transfered unchanged. If the High Nybble is set, there is some actual Decompression.

That means:
We have $28 (forty) free banks in the ROM, there you can put completely uncompressed maps, and all you have to do is put a bunch of $0F $0F $0F bytes in front of 'em.

Looks like this is going to work. But I guess, I have to do some testing by myself and do some proper tutorial on it.

Now we're talking. If we can get the game to read uncompressed maps then the actual editing process will much more manageable. Very nice work. Bouncy

[Image: jce3000gt_md.png]

[Image: jce3000gt.jpg]
Visit this user's website Find all posts by this user
Quote this message in a reply
12-13-2017, 03:55 PM
Post: #8
RE: Final Fantasy Mystic Quest - Some Random Code Digging
(12-13-2017 01:54 PM)JCE3000GT Wrote:  Now we're talking. If we can get the game to read uncompressed maps then the actual editing process will much more manageable. Very nice work. Bouncy

Yup, that was the plan as you know! Grin

I guess it might get complicated to move some events/sprites around, but generally I think I will be able to get that done. Somehow.

So, well, get your spreadsheets ready for some fantasy mapping.

Oh, by the way - does this project distract you from your FF6 hack that's in the work?

Me on Twitter
Visit this user's website Find all posts by this user
Quote this message in a reply
12-13-2017, 06:35 PM
Post: #9
RE: Final Fantasy Mystic Quest - Some Random Code Digging
(12-13-2017 03:55 PM)lytron Wrote:  
(12-13-2017 01:54 PM)JCE3000GT Wrote:  Now we're talking. If we can get the game to read uncompressed maps then the actual editing process will much more manageable. Very nice work. Bouncy

Yup, that was the plan as you know! Grin

I guess it might get complicated to move some events/sprites around, but generally I think I will be able to get that done. Somehow.

So, well, get your spreadsheets ready for some fantasy mapping.

I think for the sprites and events perhaps they may not be complicated if the game just uses a map index rather than pointers. I'm not sure if I found that but I can check on it later.

Quote:Oh, by the way - does this project distract you from your FF6 hack that's in the work?

Yes. Bouncy

[Image: jce3000gt_md.png]

[Image: jce3000gt.jpg]
Visit this user's website Find all posts by this user
Quote this message in a reply
12-15-2017, 01:44 PM
Post: #10
RE: Final Fantasy Mystic Quest - Some Random Code Digging
(12-13-2017 06:35 PM)JCE3000GT Wrote:  
Quote:Oh, by the way - does this project distract you from your FF6 hack that's in the work?

Yes. Bouncy

Sounds like you enjoy that more as you probably should~~~ Grin

~~~

I'm currently torn between actually disassembling and just fiddling around in the ROM and testing changed RAM values. After I did the latter for oh much too long, I just turned to the former, but here's something for you to play around, if you want:

Code:
Address in Hexeditor - Address in Program - Current Value - Content
0003B013 - $07/B013 - $00 - Tilemap of the World Map
0003B014 - $07/B014 - $00 - Tileset of the World Map
0003B015 - Might be the Map of of the Event Positions?

If you can do something nice, make a screenshot! ;)

Besides that, I disassembled the whole Tilemap Decompression, it's quite easy, nothing too complicated:

Code:
$0900/1 contains the address of the Compressed Tilemap Data (starting with its size in a double byte)
$0902   contains the Bank of the Compressed Tilemap Data
$0903/4 contains the address where to store
$0905   contains the bank where to store


$0B/8669 08          PHP                     ; Buffer Flags, Direct Page, Direct Bank on stack
$0B/866A 0B          PHD
$0B/866B 8B          PHB
$0B/866C F4 00 09    PEA $0900               ; Set Direct Page to $09xx
$0B/866F 2B          PLD
$0B/8670 C2 30       REP #$30                A:8008 X:0000 Y:4C00 P:envMxdizc
$0B/8672 A2 DE 86    LDX #$86DE              ; Build executable code at $0918 and $091E according to...
$0B/8675 A0 18 09    LDY #$0918              ; ... the code at $0B/86DE
$0B/8678 A9 0B 00    LDA #$000B
$0B/867B 54 0B 0B    MVN 0B 0B
$0B/867E A6 00       LDX $00                 ; Load the starting address of the compressed map data
$0B/8680 E8          INX                     ; Increment it by two (address of the first data byte)
$0B/8681 E8          INX
$0B/8682 8A          TXA
$0B/8683 18          CLC                     ; Add Byte Number of Decompression Command Bytes
$0B/8684 67 00       ADC [$00]
$0B/8686 85 06       STA $06                 ; Store as pointer to the Map Data (in $0906)
$0B/8688 E2 20       SEP #$20                ; A = 8 bit
$0B/868A A5 02       LDA $02    [$00:0902]   ; Load value from $0902
$0B/868C 85 1B       STA $1B    [$00:091B]   ; Set as source bank for the copy-from-ROM MVN Command
$0B/868E 48          PHA                     A:8308 X:8002 Y:0924 P:envMxdizc
$0B/868F AB          PLB                     A:8308 X:8002 Y:0924 P:envMxdizc
$0B/8690 A5 05       LDA $05    [$00:0905]   ; Load address where to store
$0B/8692 85 1A       STA $1A    [$00:091A]   ; Set as Store Bank for copy-from-R=M MVN command
$0B/8694 85 20       STA $20    [$00:0920]   ; Set as Store Bank for copy-from-RAM MVN command
$0B/8696 85 21       STA $21    [$00:0921]   ; Set as Load Bank for copy-from-RAM MVN command
$0B/8698 A4 03       LDY $03    [$00:0903]   ; Load address where to store as Store Index (as it was meant)
$0B/869A 64 0D       STZ $0D    [$00:090D]   ; !?!?!?!?!?

$0B/869C E2 20       SEP #$20                ; A = 8 bit
$0B/869E BD 00 00    LDA $0000,x[$08:8002]   ; Load Data Byte
$0B/86A1 F0 37       BEQ $37    [$86DA]      ; Exit if Data Byte is #$00
$0B/86A3 E8          INX                     ; Increment Load Index
$0B/86A4 C2 20       REP #$20                ; Buffer 16-bit A (i. e. Loaded Data Byte)
$0B/86A6 48          PHA
$0B/86A7 29 0F 00    AND #$000F              ; Check low nybble of data byte
$0B/86AA F0 0A       BEQ $0A    [$86B6]      ; Branch if low nybble is empty
$0B/86AC DA          PHX                     ; If not, buffer Load Index on stack
$0B/86AD A6 06       LDX $06    [$00:0906]   ; Load Pointer to Map Data as MVN Source Address
$0B/86AF 3A          DEC A                   ; Decrement number of bytes to do by one
$0B/86B0 20 18 09    JSR $0918  [$0B:0918]   ; Jump to self-written copy-from-ROM MVN command


$0B/0918 8B          PHB                     A:0000 X:832F Y:8000 P:envmxdiZc
$0B/0919 54 7F 08    MVN 08 7F               A:0000 X:832F Y:8000 P:envmxdiZc
$0B/091C AB          PLB                     A:FFFF X:8330 Y:8001 P:envmxdiZc
$0B/091D 60          RTS                     A:FFFF X:8330 Y:8001 P:envmxdizc


$0B/86B3 86 06       STX $06    [$00:0906]   ; Store Map Data Pointer back
$0B/86B5 FA          PLX                     ; Restore Load Index
$0B/86B6 68          PLA                     ; Restore Data Byte
$0B/86B7 29 F0 00    AND #$00F0              ; Check if upper nybble of Data Byte is empty
$0B/86BA F0 E0       BEQ $E0    [$869C]      ; If it is, loop and do the next Data Byte
$0B/86BC 4A          LSR A                   ; If not, move upper nybble into lower nybble
$0B/86BD 4A          LSR A
$0B/86BE 4A          LSR A
$0B/86BF 4A          LSR A
$0B/86C0 85 08       STA $08    [$00:0908]   ; Store Rest of Data Byte in $0908
$0B/86C2 BD 00 00    LDA $0000,x[$08:8003]   ; Load Next Data Byte
$0B/86C5 E8          INX                     ; Increment Load Index
$0B/86C6 29 FF 00    AND #$00FF              ; Remove accidentally loaded Data Byte after that
$0B/86C9 85 0A       STA $0A    [$00:090A]   ; Buffer Next Data Byte in $090A
$0B/86CB 98          TYA                     ; Transfer Store Index in A
$0B/86CC 18          CLC                     ; Subtract Next Data Byte (cuz it's the number of bytes to go backwards)
$0B/86CD E5 0A       SBC $0A
$0B/86CF DA          PHX                     ; Buffer Load Index on stack
$0B/86D0 AA          TAX                     ; Transfer Subtraction Result in X as Source address for MVN
$0B/86D1 A5 08       LDA $08    [$00:0908]   ; Load Original Data Byte in $0908 as Number of Bytes to do for MVN
$0B/86D3 1A          INC A                   ; Increment number of Bytes to do by one(!)
$0B/86D4 20 1E 09    JSR $091E  [$0B:091E]   ; Jump to self-written copy-from-RAM MVN command


$0B/091E 8B          PHB                     A:0010 X:8000 Y:8001 P:envmxdizC
$0B/091F 54 7F 7F    MVN 7F 7F               A:0010 X:8000 Y:8001 P:envmxdizC
$0B/0922 AB          PLB                     A:FFFF X:8011 Y:8012 P:envmxdizC
$0B/0923 60          RTS                     A:FFFF X:8011 Y:8012 P:envmxdizC


$0B/86D7 FA          PLX                     ; Restore Load Index
$0B/86D8 80 C2       BRA $C2    [$869C]      ; Loop and do next Data Byte
$0B/86DA AB          PLB                     ; Restore Flags, Direct Page, Direct Bank from stack
$0B/86DB 2B          PLD
$0B/86DC 28          PLP
$0B/86DD 6B          RTL

This is all part of a bigger subroutine ($01/914C to $01/9267) that starts when you leave a screen and ends after you remove the textbox that tells you what map you've entered.
When I've done that big subroutine, I think I know everything to tell you where the data is.

Tomorrow I think I'll work a lot on this, and then I'm gone until Tuesday.

Me on Twitter
Visit this user's website Find all posts by this user
Quote this message in a reply
12-16-2017, 12:22 PM
Post: #11
RE: Final Fantasy Mystic Quest - Some Random Code Digging
Created the most brainless hack ever:

If you go to 0000C431 in your ROM, you find the three bytes AD E8 0F (= LDA $0FE8), and you replace it with A9 xx EA (LDA #$xx, NOP), the game teleports you to map xx when you leave the first house in Foresta (sadly, it teleports you sometimes on barrier tiles). So far, I know:

Code:
00 - World Map
0C - Hill of Destiny
0D - Level Forest with Boulder Dude
0E - Level Forest without Boulder Dude
0F - Foresta
10 - Foresta House 1

... Can anyone give me a helping hand here to complete that list?

Me on Twitter
Visit this user's website Find all posts by this user
Quote this message in a reply
12-16-2017, 10:31 PM
Post: #12
RE: Final Fantasy Mystic Quest - Some Random Code Digging
I have the entire list somewhere in my project files. I do believe my MQ Multi Editor has the list too. Next time I go upstairs I'll get it for you. Grin

[Image: jce3000gt_md.png]

[Image: jce3000gt.jpg]
Visit this user's website Find all posts by this user
Quote this message in a reply
12-20-2017, 10:41 AM
Post: #13
RE: Final Fantasy Mystic Quest - Some Random Code Digging
Doors are weird. I have to check how they actually work, because... well, if I put the "exit tiles" somewhere else ($1E - Door, $77 town exit), they move the player seemingly randomly around. Putting the town exit somewhere else moved me somewhere in the focus tower (big fun if you're level one), sometimes doors threw me outta town on the world map and so on. I'll check it another day.

Collected knowledge for the tileset of Foresta so far (I guess, if I/someone else completed it, it can be posted in the other thread.

BTW: If you, JCE3000GT, already have a certain map to edit in mind, just tell, so I can focus my efforts.

Code:
$00 - Grass
$17 - Fence (of some sort - didn't noted more ~___~)
$1C - Grass (Shadow LEFT)
$1D - Animated Water (Shadow LEFT)
$1E - Door (closed)
$1F - Door (open)
$20 - Trunk [BOTTOM LEFT]
$21 - Trunk [BOTTOM RIGHT]
$3F - Grass (Shadow [UPPER LEFT])
$61 - Grass (not accessible)
$77 - Grass (Exit)

Some RAM notes:

Code:
$7E/192B - Facing Direction of the Hero?

0 = Up, 2 = Right, 4 = Down, 6 = Left

Code:
$7E/192D - X Coordinate of the Hero?
$7E/192E - Y Coordinate of the Hero?

Does not get updated if you jump.

Me on Twitter
Visit this user's website Find all posts by this user
Quote this message in a reply
12-21-2017, 12:34 PM
Post: #14
RE: Final Fantasy Mystic Quest - Some Random Code Digging
(12-20-2017 10:41 AM)lytron Wrote:  Doors are weird. I have to check how they actually work, because... well, if I put the "exit tiles" somewhere else ($1E - Door, $77 town exit), they move the player seemingly randomly around. Putting the town exit somewhere else moved me somewhere in the focus tower (big fun if you're level one), sometimes doors threw me outta town on the world map and so on. I'll check it another day.

Collected knowledge for the tileset of Foresta so far (I guess, if I/someone else completed it, it can be posted in the other thread.

BTW: If you, JCE3000GT, already have a certain map to edit in mind, just tell, so I can focus my efforts.

Code:
$00 - Grass
$17 - Fence (of some sort - didn't noted more ~___~)
$1C - Grass (Shadow LEFT)
$1D - Animated Water (Shadow LEFT)
$1E - Door (closed)
$1F - Door (open)
$20 - Trunk [BOTTOM LEFT]
$21 - Trunk [BOTTOM RIGHT]
$3F - Grass (Shadow [UPPER LEFT])
$61 - Grass (not accessible)
$77 - Grass (Exit)

Some RAM notes:

Code:
$7E/192B - Facing Direction of the Hero?

0 = Up, 2 = Right, 4 = Down, 6 = Left

Code:
$7E/192D - X Coordinate of the Hero?
$7E/192E - Y Coordinate of the Hero?

Does not get updated if you jump.

Thanks for your patience while I look for the location list. As it turns out all I have is treasure chest locations not a full map location index. Though it wouldn't be hard to do, it'll just take time. I might do that after the holidays. Grin

Map exits might actually have something to do with events on each map similar to what the treasure chest and enemy locations are. Just an idea? Maybe try something simple like a temple map? The first temple is a pretty simple map.

[Image: jce3000gt_md.png]

[Image: jce3000gt.jpg]
Visit this user's website Find all posts by this user
Quote this message in a reply
12-21-2017, 04:35 PM
Post: #15
RE: Final Fantasy Mystic Quest - Some Random Code Digging
(12-21-2017 12:34 PM)JCE3000GT Wrote:  Thanks for your patience while I look for the location list. As it turns out all I have is treasure chest locations not a full map location index. Though it wouldn't be hard to do, it'll just take time. I might do that after the holidays. Grin

Every piece of information and help is appreciated!
Maybe even that might help me!

(12-21-2017 12:34 PM)JCE3000GT Wrote:  Map exits might actually have something to do with events on each map similar to what the treasure chest and enemy locations are. Just an idea? Maybe try something simple like a temple map? The first temple is a pretty simple map.

I'm gonna look for that map.
I'm just struggling with this exit thing.
I just figured out why two houses in Foresta use one way of exit and the third uses another one: The third house has two exits, so, at least theoretically, the program does not know which exit the player will take. The one-exit-houses use a way to exit where they buffer the return address (Map Number, X-Coordinate, Y-Coordinate). All in all, this is weird, weird, weird.

Me on Twitter
Visit this user's website Find all posts by this user
Quote this message in a reply
12-21-2017, 10:09 PM
Post: #16
RE: Final Fantasy Mystic Quest - Some Random Code Digging
(12-21-2017 04:35 PM)lytron Wrote:  
(12-21-2017 12:34 PM)JCE3000GT Wrote:  Thanks for your patience while I look for the location list. As it turns out all I have is treasure chest locations not a full map location index. Though it wouldn't be hard to do, it'll just take time. I might do that after the holidays. Grin

Every piece of information and help is appreciated!
Maybe even that might help me!

(12-21-2017 12:34 PM)JCE3000GT Wrote:  Map exits might actually have something to do with events on each map similar to what the treasure chest and enemy locations are. Just an idea? Maybe try something simple like a temple map? The first temple is a pretty simple map.

I'm gonna look for that map.
I'm just struggling with this exit thing.
I just figured out why two houses in Foresta use one way of exit and the third uses another one: The third house has two exits, so, at least theoretically, the program does not know which exit the player will take. The one-exit-houses use a way to exit where they buffer the return address (Map Number, X-Coordinate, Y-Coordinate). All in all, this is weird, weird, weird.

Sure thing. I'll try and send that list over soon. It's getting busy tuning around visiting all the family for the holidays. Haha.

[Image: jce3000gt_md.png]

[Image: jce3000gt.jpg]
Visit this user's website Find all posts by this user
Quote this message in a reply
12-27-2017, 01:46 AM
Post: #17
RE: Final Fantasy Mystic Quest - Some Random Code Digging
It seems like whenever I think I finally made decent progress and cracked at least the most basic construction of the game's functions, the game instantly throws me off its back in the dirt. Generally I don't try to proclaim that the game is a horrible, senseless mess that follows no logic because the programmers had no overview and threw a new function in whenever they happened to realize that they needed one, because always when I shout things like this around, someone comes 'round the corner and explains everything and easily makes me look like a dumbass.

So, I try to report:

I found the map for Bone Dungeon 1F (it's map no. $13), switched it with the empty Foresta map I made, and... there is a completely broken yet fully shaped map when I enter the Bone Dungeon. So, I can start from scratch again, because it looks too me like they wrote completely different decompression subroutine or compression format for that dungeon. This is really annoying, because, y'know, I thought I had this. I don't like to be thrown in the mud.

Me on Twitter
Visit this user's website Find all posts by this user
Quote this message in a reply
12-29-2017, 09:35 AM
Post: #18
RE: Final Fantasy Mystic Quest - Some Random Code Digging
(12-27-2017 01:46 AM)lytron Wrote:  It seems like whenever I think I finally made decent progress and cracked at least the most basic construction of the game's functions, the game instantly throws me off its back in the dirt. Generally I don't try to proclaim that the game is a horrible, senseless mess that follows no logic because the programmers had no overview and threw a new function in whenever they happened to realize that they needed one, because always when I shout things like this around, someone comes 'round the corner and explains everything and easily makes me look like a dumbass.

So, I try to report:

I found the map for Bone Dungeon 1F (it's map no. $13), switched it with the empty Foresta map I made, and... there is a completely broken yet fully shaped map when I enter the Bone Dungeon. So, I can start from scratch again, because it looks too me like they wrote completely different decompression subroutine or compression format for that dungeon. This is really annoying, because, y'know, I thought I had this. I don't like to be thrown in the mud.

Wow, dude, that sucks. LAME!

I always secretly had an opinion that this was poorly coded as was FF4. It wasn't until FF5/RS2/SD2 that Square got their shit together with coding their games then perfecting it with FF6/RS3/CT/SD3.

[Image: jce3000gt_md.png]

[Image: jce3000gt.jpg]
Visit this user's website Find all posts by this user
Quote this message in a reply
12-30-2017, 09:34 AM
Post: #19
RE: Final Fantasy Mystic Quest - Some Random Code Digging
(12-29-2017 09:35 AM)JCE3000GT Wrote:  I always secretly had an opinion that this was poorly coded as was FF4. It wasn't until FF5/RS2/SD2 that Square got their shit together with coding their games then perfecting it with FF6/RS3/CT/SD3.

Uhm... well... I cannot speak for most of these games, but all Square games I know are basically on different levels of shitty programming. I just looked into SD2 the other day and first thing I noticed is: They could've saved a lot space, why did they program it so poorly? I mean, it speaks for itself if I found this at first look. Besides that isn't FF6 far from being well coded or well structured either, AFAIK.

Me on Twitter
Visit this user's website Find all posts by this user
Quote this message in a reply
Post Reply 


Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Mystic Quest Reborn LITE JCE3000GT 13 558 12-11-2017 11:32 AM
Last Post: JCE3000GT
Wink Final Fantasy VI (secret) project JCE3000GT 30 8,190 12-08-2017 11:06 AM
Last Post: JCE3000GT
  Mystic Quest HardType 2.0 Cure Bug Tantalus 11 1,962 12-29-2016 01:12 PM
Last Post: drag0nwind
  Mystic Quest Rebalanced Fennor 4 1,159 11-05-2016 12:48 AM
Last Post: Lotex
  Mystic Quest: Silence Status Effect Fennor 6 1,246 09-22-2016 05:32 PM
Last Post: JCE3000GT
  Mystic Quest ROM map Fennor 3 854 09-07-2016 04:55 PM
Last Post: JCE3000GT
  Mystic Quest Reborn LITE is available as a reproduction! JCE3000GT 37 7,804 07-23-2016 12:14 PM
Last Post: JCE3000GT
  final fantasy mystic quest save editor problem Clouds67 1 1,399 10-16-2015 12:44 PM
Last Post: JCE3000GT
Wink Final Fantasy V Xpert (Difficulty Installing) drag0nwind 4 2,572 06-25-2015 09:34 PM
Last Post: JCE3000GT
  QUERY: Final Fantasy V EasyType andwan00 1 1,473 06-24-2015 02:39 PM
Last Post: JCE3000GT
  [REQ] Final Fantasy III US EasyType andwan00 3 2,306 06-19-2015 10:37 AM
Last Post: JCE3000GT
  [Beta Test] Mystic Quest Reborn LITE JCE3000GT 18 1,886 11-04-2014 02:12 PM
Last Post: Lotex

Forum Jump:


User(s) browsing this thread: 1 Guest(s)