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

Author Topic: Dragon Warrior 1, 2 & 3 Hacking Discussion  (Read 37675 times)

Chicken Knife

  • Sr. Member
  • ****
  • Posts: 283
    • View Profile
Re: General NES Hacking Questions
« Reply #100 on: July 08, 2019, 09:32:06 pm »
Yeah, given that the first 96 posts in this thread are all about Dragon Warrior 1 and 2 (mostly about 2), it might be worth changing the thread title to reflect that :P.
How revoltingly...sensible of a suggestion. There we are.

PS: Don't be surprised when I change the subject further to Dragon Warrior 1, 2 & 3  ;)

abw

  • Sr. Member
  • ****
  • Posts: 282
    • View Profile
Re: General NES Hacking Questions
« Reply #101 on: July 09, 2019, 08:46:19 pm »
How revoltingly...sensible of a suggestion. There we are.
I try to come up with one of those every now and then. :laugh:

PS: Don't be surprised when I change the subject further to Dragon Warrior 1, 2 & 3  ;)
I await the day! :thumbsup:

Chicken Knife

  • Sr. Member
  • ****
  • Posts: 283
    • View Profile
Re: Dragon Warrior 1, 2 & 3 Hacking Discussion
« Reply #102 on: August 24, 2019, 12:11:24 pm »
@abw

Ok, the day has arrived that I'm seriously trying to get extraction and insertion rolling. I would have loved to have gotten further than step 1 on my own. :P

The first challenge I'm facing is the fact no one seems to have posted the start and end addresses of the dialogue pointers for DW3 like was done for the first two games. It's easy enough to see the actual storage of the dialogue based on loading the posted table file into a hex editor but I'm not having much success in my attempts to trace back to the block of pointers based on my formerly useful methods. I have a feeling you're going to tell me that debugging is the best way to determine them and... I need to get better at that. Also, I'd imagine this would have to be broken up into a part 1 and part 2 based on the previous extractions? I think that had to do with the final strings being a different length but I'm not 100 percent clear.

**EDIT I just want to clarify, I'm not waiting for you to find the pointer table for me. I'm going to continue to be poking and prodding.
« Last Edit: August 24, 2019, 03:25:28 pm by Chicken Knife »

abw

  • Sr. Member
  • ****
  • Posts: 282
    • View Profile
Re: Dragon Warrior 1, 2 & 3 Hacking Discussion
« Reply #103 on: August 24, 2019, 06:09:02 pm »
The first challenge I'm facing is the fact no one seems to have posted the start and end addresses of the dialogue pointers for DW3 like was done for the first two games. It's easy enough to see the actual storage of the dialogue based on loading the posted table file into a hex editor but I'm not having much success in my attempts to trace back to the block of pointers based on my formerly useful methods. I have a feeling you're going to tell me that debugging is the best way to determine them and... I need to get better at that. Also, I'd imagine this would have to be broken up into a part 1 and part 2 based on the previous extractions? I think that had to do with the final strings being a different length but I'm not 100 percent clear.
Debugging is always a way, but there's nothing wrong with trying an educated guess or two first. You already know from the first two games that they only store a pointer to the first string in a block of 16 strings, so maybe DW3 does the same. If you take the start of the text you can read easily at 0x40010, count ahead 16 strings to 0x40190, convert those to RAM addresses $8000 and $8180, and then search the ROM for 00808081, you should get a hit at 0x28080. Et voilà!

DW3's text is approximately twice the size of DW2's, and it's not compressed, so it sprawls over 6 banks and not every bank ends with a full 16 strings, so you'll need to split the extraction into several parts, but other than being a bit dull and repetitive, it shouldn't pose any problems.

Hmm, the Text section of the DW3 ROM map on the wiki does look woefully inadequate... let's see if we can pump it up a little ;).

Chicken Knife

  • Sr. Member
  • ****
  • Posts: 283
    • View Profile
Re: Dragon Warrior 1, 2 & 3 Hacking Discussion
« Reply #104 on: August 24, 2019, 07:00:11 pm »
Debugging is always a way, but there's nothing wrong with trying an educated guess or two first. You already know from the first two games that they only store a pointer to the first string in a block of 16 strings, so maybe DW3 does the same. If you take the start of the text you can read easily at 0x40010, count ahead 16 strings to 0x40190, convert those to RAM addresses $8000 and $8180, and then search the ROM for 00808081, you should get a hit at 0x28080. Et voilà!

DW3's text is approximately twice the size of DW2's, and it's not compressed, so it sprawls over 6 banks and not every bank ends with a full 16 strings, so you'll need to split the extraction into several parts, but other than being a bit dull and repetitive, it shouldn't pose any problems.

Hmm, the Text section of the DW3 ROM map on the wiki does look woefully inadequate... let's see if we can pump it up a little ;).
The problem with my attempts to search for the pointer was getting way too many hits. Combining two addresses being pointed to and then searching is one hell of a great idea. This is what I pay you for! :laugh:

Doing some updates to the ROM information sounds like a good idea. I'll make sure to do that.

As far as counting the strings manually at the ends of rom banks and setting up separate sections for each, that sounds doable!

One more thing I'm foggy on though. I'd say that our script increased in size somewhere between 5-10 percent. Seeing the massive chunk of blank space after the existing text made this seem like not much of a problem. But how big of a problem would it be if the text creeps into another rom bank?

Also, to your comment of DW2 and DW3's text size being roughly equivalent, that's actually shocking to hear. DW3 not only has more towns but has a day / night cycle that would seem to almost double the text. The translating / writing process definitely *felt* like it took 3x as long.

Choppasmith

  • Full Member
  • ***
  • Posts: 130
    • View Profile
Re: Dragon Warrior 1, 2 & 3 Hacking Discussion
« Reply #105 on: August 26, 2019, 01:52:05 pm »
Speaking of translating and inserting, I'm ready to start inserting my changes and testing DQ2.

Abw, I downloaded abcde v4 and saw your setup and tables for all the various things (seriously WOW). Unless I missed something, when extracting, the atlas.txt didn't add the table changes (easy to add myself) or the JMP commands for jumping to various parts of the ROM (a little trickier). Was abcde SUPPOSED to add those? (I did sort of Frankenstein my whole atlas.txt adding the other parts from the new version (credits, menus, etc) to my original which was just the script plus item and monster names). I'm wondering if I missed something somewhere and should just rip from scratch, or if I just have to add those JMP commands. Thanks.

abw

  • Sr. Member
  • ****
  • Posts: 282
    • View Profile
Re: Dragon Warrior 1, 2 & 3 Hacking Discussion
« Reply #106 on: September 01, 2019, 01:42:57 pm »
Combining two addresses being pointed to and then searching is one hell of a great idea. This is what I pay you for! :laugh:
*cha-ching* :P.

Doing some updates to the ROM information sounds like a good idea. I'll make sure to do that.
That was actually a (very) roundabout way of hinting that I had just fleshed out the text section a little bit. Definitely add anything I missed, though!

I'd say that our script increased in size somewhere between 5-10 percent. Seeing the massive chunk of blank space after the existing text made this seem like not much of a problem. But how big of a problem would it be if the text creeps into another rom bank?
Overflowing any of the ROM banks is a problem, but hopefully not one that will be difficult to overcome. The existing text is uncompressed, so if you're only over by 5-10%, adding a simple compression like DTE (which usually gets you 30-40% compression) should be more than enough. The existing text is also spread over multiple banks and there is a large chunk of free space in the final text bank, so probably there's a tiny data table somewhere that controls which bank gets loaded for each string, and you could modify that to shift the text around between banks or even extend it to use one (or more) of the existing empty banks.

Also, to your comment of DW2 and DW3's text size being roughly equivalent, that's actually shocking to hear. DW3 not only has more towns but has a day / night cycle that would seem to almost double the text. The translating / writing process definitely *felt* like it took 3x as long.
DW3 definitely has much more text than DW2. It depends exactly what you count and how, but 3x sounds about right. That "twice" was clearly a typo for "thrice" and not at all me just throwing out a number based on some vague recollection from a script size comparison I did months ago ;).

Abw, I downloaded abcde v4 and saw your setup and tables for all the various things (seriously WOW).
Heh, possibly my setup is overkill, but I like having the non-text data embedded in the script show up all nice and pretty in my script dumps; it saves me from having to go back to look up what the data is for every time I'm editing things, plus I can do all of its editing/inserting as part of the same process for editing/inserting the script.

Unless I missed something, when extracting, the atlas.txt didn't add the table changes (easy to add myself) or the JMP commands for jumping to various parts of the ROM (a little trickier). Was abcde SUPPOSED to add those?
Yeah, I've been of two minds about this. When you're not making any changes to the text engine, it would be nice to have more of the insert commands generated for you by the extract process, but when you are making engine changes, having insert commands based on the old engine is kind of annoying. Hmm, maybe I'll just add an option for that and let the end user decide what they want. For now, though, abcde does NOT add everything you'll want in your insert script, but usually it only takes a couple of minutes to add the missing parts yourself.

Choppasmith

  • Full Member
  • ***
  • Posts: 130
    • View Profile
Re: Dragon Warrior 1, 2 & 3 Hacking Discussion
« Reply #107 on: September 11, 2019, 11:26:39 pm »
So, I was running into some problems

First more of a program usage question abw, when trying to use abcde with all those tables I get

Code: [Select]
table 'C:\Users\mog11\Downloads\abcde_v0_0_4\menu_params.tbl' contains a control code table switch parameter to non-existant table 'heights' at C:\Users\mog11\Downloads\abcde_v0_0_4/abcde/Table/Table.pm line 82. at Atlas.txt line 0!

C:\Users\mog11\Downloads\abcde_v0_0_4>pause
Press any key to continue . . .

They're all in the same folder so I'm not sure what I'm missing here.

Also, for the asar usage, in your coding suggestions I see an added table file with inputting text with you noting "you can input these manually if you don't want to bother with a table $36,$18,$16,$0E,$FA ;" I thought I'd try this and just entered those bytes on a line and asar said it didn't understand the command. Is it db or something else? Also, just curious is the warnpc: address I see in some asm files is that a way to warn you if your code goes past a certain point?

Okay, so even worse news for me is that somehow or another my "base" rom (pre-script insert but had the new dictionary and item/monster name values changed) became corrupt somehow so I had to start over. I changed the dictionary and also from my notes changed the second script bank from 02 to 0C (bank 12) via x03FA92 and I'm getting garbled text (it also freezes once you get past the Prologue when starting a new game) I even cut out the extra stuff from the atlas.txt to focus just on the script, and I have no idea what happened.

This still looks correct, right?

Quote
// Define, load, and activate a TABLE
#VAR(Table, TABLE)
#ADDTBL("dw2_script_NEW.tbl", Table)
#ACTIVETBL(Table)

// add this near the top of the insert script:
#VAR(pointerNum, COUNTER) // create a COUNTER variable named pointerNum
#CREATECTR(pointerNum, 8, 0) // pointerNum is an 8-bit value initialized to 0
#AUTOCMD($17FE7, #WLB(pointerNum, $3FA90)) // update the code that controls which pointer starts the next bank

// Jump to start of script
#JMP($14010)
#HDR($C010)

// auto-commands for when DW2 does a mid-string bankswap and resets its read address:
#AUTOCMD($17FE7, #HDR($28010))
#AUTOCMD($17FE7, #JMP($30010, $3400F))

Really at a loss here.

abw

  • Sr. Member
  • ****
  • Posts: 282
    • View Profile
Re: Dragon Warrior 1, 2 & 3 Hacking Discussion
« Reply #108 on: September 12, 2019, 07:35:30 pm »
First more of a program usage question abw, when trying to use abcde with all those tables I get

Code: [Select]
table 'C:\Users\mog11\Downloads\abcde_v0_0_4\menu_params.tbl' contains a control code table switch parameter to non-existant table 'heights' at C:\Users\mog11\Downloads\abcde_v0_0_4/abcde/Table/Table.pm line 82. at Atlas.txt line 0!

They're all in the same folder so I'm not sure what I'm missing here.
What command were you running? The Atlas.bat script included in the examples folder does include all the required tables and works for me. It sounds like maybe you didn't include heights.tbl on the command line or inside your Atlas.txt file.

Also, for the asar usage, in your coding suggestions I see an added table file with inputting text with you noting "you can input these manually if you don't want to bother with a table $36,$18,$16,$0E,$FA ;" I thought I'd try this and just entered those bytes on a line and asar said it didn't understand the command. Is it db or something else? Also, just curious is the warnpc: address I see in some asm files is that a way to warn you if your code goes past a certain point?
Yup, the full line would be something like "db $36,$18,$16,$0E,$FA". I did say that I hadn't tested it :P. The xkas/Asar documentation describes what warnpc is supposed to do, though I vaguely recall having issues at some point with it not actually working. Might be worth giving it a test to confirm its behaviour.

Okay, so even worse news for me is that somehow or another my "base" rom (pre-script insert but had the new dictionary and item/monster name values changed) became corrupt somehow so I had to start over. I changed the dictionary and also from my notes changed the second script bank from 02 to 0C (bank 12) via x03FA92 and I'm getting garbled text (it also freezes once you get past the Prologue when starting a new game)
And this is why having a fully scripted insert process backed by source file version control is a Good Idea™ :P. For the crash, try modifying 0x3FA94 instead - 0x3FA92 is the +$02 in "BCC +$02", so changing that to "BCC +$0C" would probably have disastrous results.

Choppasmith

  • Full Member
  • ***
  • Posts: 130
    • View Profile
Re: Dragon Warrior 1, 2 & 3 Hacking Discussion
« Reply #109 on: September 17, 2019, 12:10:40 am »
So 1. I was using the old bat file I was using for my initial script inserts. Didn't realize you had to add ALL the tables to the command line. Lesson learned.

2. After a good 3 HOURS of trial and error, I found that it was indeed my dictionary text causing problems. I still don't know what exactly but since I was using the DW2 menu table to edit it, there must've been a random wrong byte getting swapped in somehow. To avoid future problems I just made a separate dictionary table and all is well again.

3.
Quote
And this is why having a fully scripted insert process backed by source file version control is a Good Idea™ :P. For the crash, try modifying 0x3FA94 instead - 0x3FA92 is the +$02 in "BCC +$02", so changing that to "BCC +$0C" would probably have disastrous results.

In my defense, having the same values right next to each other is sure easy to change the wrong one.

4. Now I can start messing around with those battle routines and I'm not having much luck so far. But so far with enemies I'm actually getting stuff like "(Hero name) appears!" for single enemies. Takign your suggestions from other posts, I did manage to combine a couple.

Code: [Select]
norom

org $1150C
base $94FC

LDA #$52
STA $A8 ; initialize per-group string ID to use in multi-group battles
LDA #$00
STA $A7 ; initialize total # of empty groups processed
process_group_string:
JSR $9EEE ; given an index (in A) into the array of structures at $0663, set $B5-$B6 to the address of the corresponding item inside that structure
LDY #$09
LDA ($B5),Y
STA $8F ; number of monsters in this group
BEQ done_display_string ; 0 monsters => no string to print
INC $A8 ; string ID to use for this group
LDY #$00
LDA ($B5),Y
STA $0161 ; current monster ID
LDX #$00
JSR $9CD6 ; write monster name in A (+ monster number within its group in X, if > 0) to $6119
LDA $60D8 ; total number of non-empty enemy groups in the current battle
CMP #$01
BEQ display_string ; if there's only 1 group, then use string ID #$0001 (change the text to be appropriate)
LDA $A8 ; otherwise use the per-group string ID (also change those texts to be appropriate)
display_string:
JSR $9CCA ; for A < #$60, display string ID specified by A; for A >= #$60, display string ID specified by A + #$A0
done_display_string:
INC $A7
LDA $A7
CMP #$04
BCC process_group_string
LDA $60D8 ; total number of non-empty enemy groups in the current battle
BNE next_section
LDA #$02 ; String ID #$0002: But it wasn't real.[end-FC]
JSR $9CCA ; for A < #$60, display string ID specified by A; for A >= #$60, display string ID specified by A + #$A0
LDA #$FD
STA $98 ; outcome of last fight?
JMP $9685
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP

next_section:

Code: [Select]
norom ; stop Asar from trying to apply SNES memory mapping to this NES code
org $00BF00 ; set the ROM file insertion point
base $8EF0 ; set the starting RAM address

LDA $0161 ; monster ID for the current group
CMP #$4E ; bosses have IDs >= #$4E (so does the "Enemies" monster, but that's not a monster ID you can encounter)
BCS no_change
SEC ; not strictly necessary since we got here by BCS and nothing has changed C
RTS
LDY $8F    ; number of monsters in group
DEY        ; count from 0 instead of 1
BEQ one     ; 0 => only one monster => handle "A" vs "An"
LDX #$00    ; read index
LDY #$00    ; write index
loop:
LDA some,X ; Monster Counts text
STA $60F1,Y ; start of text variable buffer
INY       
INX       
CMP #$FA    ; [end-FA]
BNE loop  ; if not end token, keep copying
done:
SEC        ; SEC to trigger read of [end-FA]-terminated string from $60F1, CLC to use A
RTS       
some:
db $36,$18,$16,$0E,$FA ;"Some" not using a table here
one:
; at this point we know Y = 0
LDA #$24 ; "A"
STA $60F1,Y ; start of text variable buffer
LDA $6119 ; first letter of monster name
CMP #$24 ; "A"
BEQ an
CMP #$28 ; "E"
BEQ an
CMP #$2C ; "I"
BEQ an
CMP #$32 ; "O"
BEQ an
CMP #$38 ; "U"
BNE no_change
an:
LDA #$17 ; "n"
INY
STA $60F1,Y ; start of text variable buffer
no_change:
LDA #$FA ; [end-FA]
STA $60F1,Y ; start of text variable buffer
BNE done

Also I meant to ask you if this "s" fix looked right to you

Code: [Select]
norom ; stop Asar from trying to apply SNES memory mapping to this NES code
org $01C7E8 ; set the ROM file insertion point
base $B7D8  ; set the starting RAM address

; data -> code
; if $8F-$90 == #$0001, print "s" + [end-FA] to $60F1 and SEC, else print [end-FA] and CLC
; indirect control flow target
; from $02:$BE37 via $8006
    LDA $90
    BNE s ; if $90 > 0, add "s"
    LDY $8F
    DEY
  BEQ end ; if $90 == 0 and $8F - 1 == 0 (i.e. $8F == 1), do not add "s"

s:
    LDA #$1C ; "s"

fix:
STA $60F1
    LDA #$FA ; [end-FA]
STA $60F2
    SEC
    RTS

end:
  LDA #$FA ; [end-FA]
    BNE fix
As I recall it's those last 2 bytes that needed fixing and you suggested a quick branch as an easy fix that would fit into the existing space. I just wanted to make sure I have this right.

But moving priorities a bit.

I was looking at your Latin translation so I could apply your border names code. I extracted the Latin script with Cartographer and strangely noticed that with mine, the original, the pointer and strings count up normally from 0 while yours jumps straight to 30 after 0 and seems to combine a bunch of those strings together. Did you maybe shift some pointers around or is it just Cartographer being weird?

abw

  • Sr. Member
  • ****
  • Posts: 282
    • View Profile
Re: Dragon Warrior 1, 2 & 3 Hacking Discussion
« Reply #110 on: September 17, 2019, 09:00:11 pm »
So 1. I was using the old bat file I was using for my initial script inserts. Didn't realize you had to add ALL the tables to the command line. Lesson learned.
You have to tell abcde where your table files are somehow; you can do that on the command line or inside the command files, but it's not going to go around opening random files and trying to use them as tables. A table's ID and file name can be completely different, so guessing at the file name based on the ID doesn't really work (and in v0.0.5 I re-added a pre-release idea where you can have multiple tables inside the same file, so it really doesn't work there).

2. After a good 3 HOURS of trial and error, I found that it was indeed my dictionary text causing problems. I still don't know what exactly but since I was using the DW2 menu table to edit it, there must've been a random wrong byte getting swapped in somehow. To avoid future problems I just made a separate dictionary table and all is well again.
The menus definitely use a different table - it's very similar to the table used for most other things, but not quite the same. Spaces in particular can be $81 in the menus, but putting a $81 in the dictionary might result in weirdness happening.

3. In my defense, having the same values right next to each other is sure easy to change the wrong one.
Yup, there are plenty of pitfalls in this business - I'm just saying that having a scripted insert process is one way of avoiding some of them :P.

4. Also I meant to ask you if this "s" fix looked right to you
Yeah, I think that was the smallest modification that would fix the F2 control code. For the 0xBF00 code, you can shuffle things around a little bit to save a couple of bytes:
Code: [Select]
norom ; stop Asar from trying to apply SNES memory mapping to this NES code
org $00BF00 ; set the ROM file insertion point
base $8EF0 ; set the starting RAM address

LDY $8F ; number of monsters in group
DEY ; count from 0 instead of 1
BEQ one ; 0 => only one monster => handle unique monsters and "A" vs "An"
LDX #$00 ; read index
LDY #$00 ; write index
loop:
LDA some,X ; Monster Counts text
STA $60F1,Y ; start of text variable buffer
INY
INX
CMP #$FA ; [end-FA]
BNE loop ; if not end token, keep copying
done:
SEC ; SEC to trigger read of [end-FA]-terminated string from $60F1, CLC to use A
RTS
some:
db $36,$18,$16,$0E,$FA ;"Some" not using a table here
one:
; at this point we know Y = 0
LDA $0161 ; monster ID for the current group
CMP #$4E ; bosses have IDs >= #$4E (so does the "Enemies" monster, but that's not a monster ID you can encounter)
BCS no_change
LDA #$24 ; "A"
STA $60F1,Y ; start of text variable buffer
LDA $6119 ; first letter of monster name
CMP #$24 ; "A"
BEQ an
CMP #$28 ; "E"
BEQ an
CMP #$2C ; "I"
BEQ an
CMP #$32 ; "O"
BEQ an
CMP #$38 ; "U"
BNE no_change
an:
LDA #$17 ; "n"
INY
STA $60F1,Y ; start of text variable buffer
no_change:
LDA #$FA ; [end-FA]
STA $60F1,Y ; start of text variable buffer
BNE done

I was looking at your Latin translation so I could apply your border names code. I extracted the Latin script with Cartographer and strangely noticed that with mine, the original, the pointer and strings count up normally from 0 while yours jumps straight to 30 after 0 and seems to combine a bunch of those strings together. Did you maybe shift some pointers around or is it just Cartographer being weird?
I think I mentioned it earlier, but I did reorder the menus to make them easier for me to work with (e.g. storing similar menus side by side), so what you're seeing sounds right.