hide results

    Name Generation Guide by Presenter

    Version: 1.0 | Updated: 02/22/09 | Printable Version | Search Guide | Bookmark Guide

                       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