Dragon Warrior II Name Generation Guide
                           Version 1.0  2009-02-22
            Copyright  2009 Robert Kosinski. All Rights Reserved.
                   whelkman in the proximity of hotmail.com


                                                           Quote of the guide:
                        "Mirror of Ra turns bitch into princess" --honestgamer

                            --------------------
                            *** Introduction ***
                            --------------------

Obsessive fans of the original Dragon Warrior know that name selection affects
the hero's initial stats and progression. While level growth is static in the
sequel, name selection determines your companions names from list. This guide
walks through the process the game uses to decide which names your companions
receive, both at practical and in-depth levels. Finally, I cover customizing
companion names by hacking the ROM itself.

                              ----------------
                              *** Overview ***
                              ----------------

Algorithmically, Dragon Warrior II's name generator works similarly to its
predecessor's: the outcome is determined by the sum of character codes of the
first four letters of the inputted name. Unlike the original Dragon Warrior,
however, Dragon Warrior II does not clear the "carry flag" during its additions.

Imagine you're given graph paper onto which you can write numbers. If you
wanted to write "99", it'd fit pretty easily in one square, but, for "100",
you might choose to write "00" in one box and the "1" in the square
immediately to the left. That's how it works for computers, too.

In Dragon Warrior II's case, when an addition result exceeds 255 (0xFF in
hexadecimal), a "one" to carry over is triggered internally as a "carry flag".
Normally a programmer would either check to see whether the carry flag is set
then tell the program the location of that box to the left or simply clear the
flag because we're not interested in the carry, but Dragon Warrior II does
neither. The carry flag is left to add back into the working result.

In our graph paper example, if we didn't have a box to the left to put the "1"
in "100" and subsequently added it back to our result, we'd get "00 + 1 = 01",
a totally different answer than we expected. The same sort of issue occurs in
Dragon Warrior II name generation, leading to to off by one or two results,
thus destroying the easy division method offered by the first Dragon Warrior
name guide. Complicating matters are junk numbers thrown into the equation
that guarantee triggering the carry condition. Fortunately, I've figured it
out so you don't have to.

                            ---------------------
                            *** Simple Method ***
                            ---------------------

                                  Name Table

               A  B  C  D  E  F  G  H    24 25 26 27 28 29 2A 2B
               I  J  K  L  M  N  O  P    2C 2D 2E 2F 30 31 32 33
               Q  R  S  T  U  V  W  X    34 35 36 37 38 39 3A 3B
               Y  Z  '  ,  .  ;  ~  >    3C 3D 5F 69 6B 70 75 63
               _  a  b  c  d  e  f  g    60 0A 0B 0C 0D 0E 0F 10
               h  i  j  k  l  m  n  o    11 12 13 14 15 16 17 18
               p  q  r  s  t  u  v  w    19 1A 1B 1C 1D 1E 1F 20
               x  y  z  !  ?             21 22 23 6F 6E

Dragon Warrior's character set doesn't exactly match up with ASCII.
Substitutions:

~ = ..
> = arrow
_ = space

To complete this calculation you'll need a calculator that supports
hexadecimal math and, preferably, bitwise AND. Windows' Calculator does the
job, and I will assume you are using it. You'll need to enable scientific
mode, located in the "View" menu; make sure you select hexadecimal mode by
clicking on the "Hex" radio button located to the far left, just below the
calculator display.

After choosing your name, look up the values of the first four characters in
the above table and add them together. Then add 180. Next, add whatever is in
the third ("hundreds") digit to the first. Now eliminate the third digit,
either by subtraction or by clearing the result and retyping the first two
digits. Store this result with the M+ button.

Now press the "And" button, located to the far right below the "C" button.
Input the number 7 and finish the calculation with the "Enter" key or the "="
button in the calculator. The number given will correspond to a prince below:

                               Prince   Princess
                            0  Bran     Varia
                            1  Glynn    Elani
                            2  Talint   Ollisa
                            3  Numor    Roz
                            4  Lars     Kailin
                            5  Orfeo    Peta
                            6  Artho    Illyth
                            7  Esgar    Gwen

Now press the "MR" key to recall our stored value. This time, press "And",
input 38, then divide by 8. Finally, use the value to look up the princess'
name on the chart.

As an example, I chose "Loto" as my name. Using the above procedure:

* Add name values together: 2F + 18 + 1D + 18 = 7C
* Add 180: 7C + 180 = 1FC
* Add third digit to first: 1FC + 1 = 1FD
* Subtract third digit: 1FD - 100 = FD
* Hit M+ key and see the 'M' indicator activate
* And 7: FD AND 7 = 5
* Look up Prince of Cannock #5: Orfeo
* MR: display = FD
* And 38: FD AND 38 = 38
* Divide by 8: 38 / 8 = 7
* Look up Princess of Moonbrooke #7: Gwen

                     ----------------------------------
                     *** What Happens in Game Logic ***
                     ----------------------------------

I used FCEUX for the forthcoming analysis. Other tools may yield different
results. The subroutine that calculates the names of your party members is
located at $ACEB. What follows is a "trace log", the 6502 code that executes
the algorithm:

$ACEB:A9 00     LDA #$00                   A:2F X:FF Y:00 P:NvUBdIzC
$ACED:A2 03     LDX #$03                   A:00 X:FF Y:00 P:nvUBdIZC
$ACEF:18        CLC                        A:00 X:03 Y:00 P:nvUBdIzC
$ACF0:7D 09 70  ADC $7009,X @ $700C = #$18 A:00 X:03 Y:00 P:nvUBdIzc
$ACF3:7D 63 70  ADC $7063,X @ $7066 = #$60 A:18 X:03 Y:00 P:nvUBdIzc
$ACF6:CA        DEX                        A:78 X:03 Y:00 P:nvUBdIzc
$ACF7:10 F7     BPL $ACF0                  A:78 X:02 Y:00 P:nvUBdIzc
$ACF0:7D 09 70  ADC $7009,X @ $700B = #$1D A:78 X:02 Y:00 P:nvUBdIzc
$ACF3:7D 63 70  ADC $7063,X @ $7065 = #$60 A:95 X:02 Y:00 P:NVUBdIzc
$ACF6:CA        DEX                        A:F5 X:02 Y:00 P:NvUBdIzc
$ACF7:10 F7     BPL $ACF0                  A:F5 X:01 Y:00 P:nvUBdIzc
$ACF0:7D 09 70  ADC $7009,X @ $700A = #$18 A:F5 X:01 Y:00 P:nvUBdIzc
$ACF3:7D 63 70  ADC $7063,X @ $7064 = #$60 A:0D X:01 Y:00 P:nvUBdIzC
$ACF6:CA        DEX                        A:6E X:01 Y:00 P:nvUBdIzc
$ACF7:10 F7     BPL $ACF0                  A:6E X:00 Y:00 P:nvUBdIZc
$ACF0:7D 09 70  ADC $7009,X @ $7009 = #$2F A:6E X:00 Y:00 P:nvUBdIZc
$ACF3:7D 63 70  ADC $7063,X @ $7063 = #$60 A:9D X:00 Y:00 P:NVUBdIzc
$ACF6:CA        DEX                        A:FD X:00 Y:00 P:NvUBdIzc
$ACF7:10 F7     BPL $ACF0                  A:FD X:FF Y:00 P:NvUBdIzc
$ACF9:48        PHA                        A:FD X:FF Y:00 P:NvUBdIzc
$ACFA:29 07     AND #$07                   A:FD X:FF Y:00 P:NvUBdIzc
$ACFC:0A        ASL                        A:05 X:FF Y:00 P:nvUBdIzc
$ACFD:0A        ASL                        A:0A X:FF Y:00 P:nvUBdIzc
$ACFE:0A        ASL                        A:14 X:FF Y:00 P:nvUBdIzc
$ACFF:AA        TAX                        A:28 X:FF Y:00 P:nvUBdIzc
$AD00:A0 00     LDY #$00                   A:28 X:28 Y:00 P:nvUBdIzc
$AD02:BD 39 AD  LDA $AD39,X @ $AD61 = #$32 A:28 X:28 Y:00 P:nvUBdIZc
$AD05:99 0D 70  STA $700D,Y @ $700D = #$32 A:32 X:28 Y:00 P:nvUBdIzc
$AD08:99 18 01  STA $0118,Y @ $0118 = #$00 A:32 X:28 Y:00 P:nvUBdIzc
$AD0B:BD 3D AD  LDA $AD3D,X @ $AD65 = #$18 A:32 X:28 Y:00 P:nvUBdIzc
$AD0E:99 67 70  STA $7067,Y @ $7067 = #$18 A:18 X:28 Y:00 P:nvUBdIzc
$AD11:99 8A 01  STA $018A,Y @ $018A = #$00 A:18 X:28 Y:00 P:nvUBdIzc
$AD14:E8        INX                        A:18 X:28 Y:00 P:nvUBdIzc
$AD15:C8        INY                        A:18 X:29 Y:00 P:nvUBdIzc
$AD16:C0 04     CPY #$04                   A:18 X:29 Y:01 P:nvUBdIzc
$AD18:D0 E8     BNE $AD02                  A:18 X:29 Y:01 P:NvUBdIzc
$AD02:BD 39 AD  LDA $AD39,X @ $AD62 = #$1B A:18 X:29 Y:01 P:NvUBdIzc
$AD05:99 0D 70  STA $700D,Y @ $700E = #$1B A:1B X:29 Y:01 P:nvUBdIzc
$AD08:99 18 01  STA $0118,Y @ $0119 = #$00 A:1B X:29 Y:01 P:nvUBdIzc
$AD0B:BD 3D AD  LDA $AD3D,X @ $AD66 = #$5F A:1B X:29 Y:01 P:nvUBdIzc
$AD0E:99 67 70  STA $7067,Y @ $7068 = #$5F A:5F X:29 Y:01 P:nvUBdIzc
$AD11:99 8A 01  STA $018A,Y @ $018B = #$00 A:5F X:29 Y:01 P:nvUBdIzc
$AD14:E8        INX                        A:5F X:29 Y:01 P:nvUBdIzc
$AD15:C8        INY                        A:5F X:2A Y:01 P:nvUBdIzc
$AD16:C0 04     CPY #$04                   A:5F X:2A Y:02 P:nvUBdIzc
$AD18:D0 E8     BNE $AD02                  A:5F X:2A Y:02 P:NvUBdIzc
$AD02:BD 39 AD  LDA $AD39,X @ $AD63 = #$0F A:5F X:2A Y:02 P:NvUBdIzc
$AD05:99 0D 70  STA $700D,Y @ $700F = #$0F A:0F X:2A Y:02 P:nvUBdIzc
$AD08:99 18 01  STA $0118,Y @ $011A = #$00 A:0F X:2A Y:02 P:nvUBdIzc
$AD0B:BD 3D AD  LDA $AD3D,X @ $AD67 = #$5F A:0F X:2A Y:02 P:nvUBdIzc
$AD0E:99 67 70  STA $7067,Y @ $7069 = #$5F A:5F X:2A Y:02 P:nvUBdIzc
$AD11:99 8A 01  STA $018A,Y @ $018C = #$00 A:5F X:2A Y:02 P:nvUBdIzc
$AD14:E8        INX                        A:5F X:2A Y:02 P:nvUBdIzc
$AD15:C8        INY                        A:5F X:2B Y:02 P:nvUBdIzc
$AD16:C0 04     CPY #$04                   A:5F X:2B Y:03 P:nvUBdIzc
$AD18:D0 E8     BNE $AD02                  A:5F X:2B Y:03 P:NvUBdIzc
$AD02:BD 39 AD  LDA $AD39,X @ $AD64 = #$0E A:5F X:2B Y:03 P:NvUBdIzc
$AD05:99 0D 70  STA $700D,Y @ $7010 = #$0E A:0E X:2B Y:03 P:nvUBdIzc
$AD08:99 18 01  STA $0118,Y @ $011B = #$00 A:0E X:2B Y:03 P:nvUBdIzc
$AD0B:BD 3D AD  LDA $AD3D,X @ $AD68 = #$5F A:0E X:2B Y:03 P:nvUBdIzc
$AD0E:99 67 70  STA $7067,Y @ $706A = #$5F A:5F X:2B Y:03 P:nvUBdIzc
$AD11:99 8A 01  STA $018A,Y @ $018D = #$00 A:5F X:2B Y:03 P:nvUBdIzc
$AD14:E8        INX                        A:5F X:2B Y:03 P:nvUBdIzc
$AD15:C8        INY                        A:5F X:2C Y:03 P:nvUBdIzc
$AD16:C0 04     CPY #$04                   A:5F X:2C Y:04 P:nvUBdIzc
$AD18:D0 E8     BNE $AD02                  A:5F X:2C Y:04 P:nvUBdIZC
$AD1A:68        PLA                        A:5F X:2C Y:04 P:nvUBdIZC
$AD1B:29 38     AND #$38                   A:FD X:2C Y:04 P:NvUBdIzC
$AD1D:AA        TAX                        A:38 X:2C Y:04 P:nvUBdIzC
$AD1E:A0 00     LDY #$00                   A:38 X:38 Y:04 P:nvUBdIzC
$AD20:BD 79 AD  LDA $AD79,X @ $ADB1 = #$2A A:38 X:38 Y:00 P:nvUBdIZC
$AD23:99 11 70  STA $7011,Y @ $7011 = #$2A A:2A X:38 Y:00 P:nvUBdIzC
$AD26:99 1D 01  STA $011D,Y @ $011D = #$00 A:2A X:38 Y:00 P:nvUBdIzC
$AD29:BD 7D AD  LDA $AD7D,X @ $ADB5 = #$5F A:2A X:38 Y:00 P:nvUBdIzC
$AD2C:99 6B 70  STA $706B,Y @ $706B = #$5F A:5F X:38 Y:00 P:nvUBdIzC
$AD2F:99 8E 01  STA $018E,Y @ $018E = #$00 A:5F X:38 Y:00 P:nvUBdIzC
$AD32:E8        INX                        A:5F X:38 Y:00 P:nvUBdIzC
$AD33:C8        INY                        A:5F X:39 Y:00 P:nvUBdIzC
$AD34:C0 04     CPY #$04                   A:5F X:39 Y:01 P:nvUBdIzC
$AD36:D0 E8     BNE $AD20                  A:5F X:39 Y:01 P:NvUBdIzc
$AD20:BD 79 AD  LDA $AD79,X @ $ADB2 = #$20 A:5F X:39 Y:01 P:NvUBdIzc
$AD23:99 11 70  STA $7011,Y @ $7012 = #$20 A:20 X:39 Y:01 P:nvUBdIzc
$AD26:99 1D 01  STA $011D,Y @ $011E = #$00 A:20 X:39 Y:01 P:nvUBdIzc
$AD29:BD 7D AD  LDA $AD7D,X @ $ADB6 = #$5F A:20 X:39 Y:01 P:nvUBdIzc
$AD2C:99 6B 70  STA $706B,Y @ $706C = #$5F A:5F X:39 Y:01 P:nvUBdIzc
$AD2F:99 8E 01  STA $018E,Y @ $018F = #$00 A:5F X:39 Y:01 P:nvUBdIzc
$AD32:E8        INX                        A:5F X:39 Y:01 P:nvUBdIzc
$AD33:C8        INY                        A:5F X:3A Y:01 P:nvUBdIzc
$AD34:C0 04     CPY #$04                   A:5F X:3A Y:02 P:nvUBdIzc
$AD36:D0 E8     BNE $AD20                  A:5F X:3A Y:02 P:NvUBdIzc
$AD20:BD 79 AD  LDA $AD79,X @ $ADB3 = #$0E A:5F X:3A Y:02 P:NvUBdIzc
$AD23:99 11 70  STA $7011,Y @ $7013 = #$0E A:0E X:3A Y:02 P:nvUBdIzc
$AD26:99 1D 01  STA $011D,Y @ $011F = #$00 A:0E X:3A Y:02 P:nvUBdIzc
$AD29:BD 7D AD  LDA $AD7D,X @ $ADB7 = #$5F A:0E X:3A Y:02 P:nvUBdIzc
$AD2C:99 6B 70  STA $706B,Y @ $706D = #$5F A:5F X:3A Y:02 P:nvUBdIzc
$AD2F:99 8E 01  STA $018E,Y @ $0190 = #$00 A:5F X:3A Y:02 P:nvUBdIzc
$AD32:E8        INX                        A:5F X:3A Y:02 P:nvUBdIzc
$AD33:C8        INY                        A:5F X:3B Y:02 P:nvUBdIzc
$AD34:C0 04     CPY #$04                   A:5F X:3B Y:03 P:nvUBdIzc
$AD36:D0 E8     BNE $AD20                  A:5F X:3B Y:03 P:NvUBdIzc
$AD20:BD 79 AD  LDA $AD79,X @ $ADB4 = #$17 A:5F X:3B Y:03 P:NvUBdIzc
$AD23:99 11 70  STA $7011,Y @ $7014 = #$17 A:17 X:3B Y:03 P:nvUBdIzc
$AD26:99 1D 01  STA $011D,Y @ $0120 = #$00 A:17 X:3B Y:03 P:nvUBdIzc
$AD29:BD 7D AD  LDA $AD7D,X @ $ADB8 = #$5F A:17 X:3B Y:03 P:nvUBdIzc
$AD2C:99 6B 70  STA $706B,Y @ $706E = #$5F A:5F X:3B Y:03 P:nvUBdIzc
$AD2F:99 8E 01  STA $018E,Y @ $0191 = #$00 A:5F X:3B Y:03 P:nvUBdIzc
$AD32:E8        INX                        A:5F X:3B Y:03 P:nvUBdIzc
$AD33:C8        INY                        A:5F X:3C Y:03 P:nvUBdIzc
$AD34:C0 04     CPY #$04                   A:5F X:3C Y:04 P:nvUBdIzc
$AD36:D0 E8     BNE $AD20                  A:5F X:3C Y:04 P:nvUBdIZC
$AD38:60        RTS                        A:5F X:3C Y:04 P:nvUBdIZC

Looking at the code, it becomes obvious that failing to clear the carry flag
is a likely bug. What Enix probably meant to do during its calculations is
head back to $ACEF, which contains the block's only CLC, instead of the next
address, $ACF0, which continues the accumulation.

The human readable version follows. In my example, I named the Prince of
Midenhall "Loto". The name is processed backwards, as "otoL". The procedure
yields Orfeo and Gwen as my companions. Arithmetic is in hexadecimal with
occasional binary. For brevity's sake, a few steps ultimately not affecting
logical flow are omitted.

* Set A to zero. A is the "accumulator" and performs all the math.
* Set X to 3. This is used to sequentially read name characters.
* Clear carry flag (for only time in the code block).
* Add to A 0x18, value of character 3, "o". (A=0x18)
* Add to A 0x60. (A=0x78)
* Decrement X. (X=2)
* Add to A 0x1D, value of character 2, "t". (A=0x95)
* Add to A 0x60. (A=0xF5)
* Decrement X. (X=1)
* Add to A 0x18, value of character 1, "o". Trigger carry. (A=0x0D)
* Add to A 0x60 plus the carry, 0x01. (A=0x6E)
* Decrement X. (X=0)
* Add to A 0x1D, value of character 0, "L". (A=0x9D)
* Add to A 0x60. (A=0xFD)
* Decrement X. (we're done)
* Push A onto stack, a place where we can later access stored values.
* Bitwise AND 0x07 with A (00000111 & 11111101 = 101). (A=0x05)
* Arithmetic shift left A (double result). (A=0x0A)
* Arithmetic shift left A (double result). (A=0x14)
* Arithmetic shift left A (double result). (A=0x28)
* Copy A to X. (X=0x28)
* Set Y to zero.

Until this point I have provided a near line-for-line translation of the
assembly code. However, the remainder is short on math and long on repetitive
memory copying, which can be generalized. Minus one more bitwise AND operation
that determines the Princess of Moonbrooke's name, the algorithm itself is
about finished. A short review before continuing:

We added the values of the first four name letters, padding, and the carry or
carries. We performed a bitwise AND to reduce the result to a number between 0
and 7; we needn't higher values because the built-in tables contain eight
names a piece for the prince and princess. Finally, we doubled the result
three times (2x2x2=8) and copied to X to use as an offset. Multiplying by
eight breaks the possibilities into "chunks" spaced eight apart, which is
perfect for reading against a table where entries are spaced eight bytes apart.

Moving on, we load contents of address $AD39, the start location of the Prince
of Cannock's name table plus our name-generated offset, previously copied into
X. This will choose one of eight names and copy his name into memory one
character at a time. Dragon Warrior II writes names to several locations,
which makes this code block look bloated.

Upon finishing writing out the Prince of Cannock's name, we come across three
instructions that determine the Princess of Moonbrooke's name:

* PLA pulls the value previously placed onto the stack into A. (A=0xFD)
* Bitwise AND 0x38 with A (00111000 & 11111101 = 00111000) (A=0x38)
* Copy A to X

Next we perform the same procedure as with the Prince of Cannock's, this time
at the Princess' name table, starting at $AD79. The Princess' bitwise AND
operation is the inverse of the Prince's: instead of taking the lower three
bits, we take the next three. Doing this allows for 64 possible name
combinations.

Finally, we call RTS, which exits this subroutine.

                    ------------------------------------
                    *** Taking Things a Step Further ***
                    ------------------------------------

Given our recently gained knowledge, we can create our own names for our
companions in ROM. For this we'll need the services of a hex editor. I
recommend XVI32: it's adequate and free. Specialized tools are available but
unnecessary unless you plan to make ROM hacking a regular habit. My offsets
include the iNES header.

Before getting to work on the ROM, make a copy. Completely destroying the ROM
with a hex editor is trivially easy. Name the copy something like
"dw2-hack.nes" so you can easily differentiate it from the original.

The first address we're interested in is located at $1AD49, which is the start
of the Prince's name table. Now we'll need to calculate the offset in order to
get us at the correct entry. If using a trace log, the value we're interested
in is the first value passed to X with the TAX instruction. Otherwise we'll
use our quick 'n dirty calculation method to derive the same value. Sticking
with "Loto":

* Add name values together: 2F + 18 + 1D + 18 = 7C
* Add 180: 7C + 180 = 1FC
* Add third digit to first: 1FC + 1 = 1FD
* Subtract third digit: 1FD - 100 = FD
* And 7: FD AND 7 = 5

This time we need to multiply the result by 8, which yields 0x28 in
hexadecimal. This is our offset. To get to the correct location, simply add
0x28 to 0x1D49, giving us $1D71. Unless the offset to be added is 0, you
should see "5F" immediately to the left of where ever you end up. These are
padding characters to fill spaces unused by letters. You have up to eight
characters to input. If your name is shorter than what's normally used by the
game, pad it out with 5F.

If I want to name the Prince of Cannock "Erdrick" with my main character as
"Loto", I insert the following starting at $1D71, using the above name table
as a reference: 28 1B 0D 1B 12 0C 14 5F.

For the princess, we get the correct value at the bitwise AND step;
multiplying by 8 is already "built in". Her names begin at $1AD89. So, if I
want her as "Gwaelin" with the Prince of Midenhall as "Loto", we'll need an
offset of 0x38 beyond $1AD89, which comes to $1ADC1. Using the name table
again, we get: 2A 20 0A 0E 15 12 17 5F.

Watch for mistakes! It'd be a shame to do all this work and wind up with
"Erdrjck" or something.

                              -----------------
                              *** Thanks to ***
                              -----------------

* the succession of FCE -> FCEU -> FCEUX for great emulation and powerful
  debugging tools
* 6502.org for their opcode list that allowed me to pick up 6502 in a few hours
* akira slime for his Dragon Warrior I generation guide