Destiny of an Emperor RH Guide Page 2

This is page 2 of the Destiny of an Emperor ROM Hacking Guide

Popular ROM's made using this guide:

For Contributors:

  • To contribute, go to the bottom of the page, join the page, and enter the password.
  • It is probably easiest to edit sections individually with +Options —> "Edit Sections" at the bottom of the page.

Page 1 Contains:

  • Destiny of an Editor
  • DoaE IPS Patch
  • Locations
  • Warps
  • Music
  • Battles
  • Damage
  • Tactics
  • Officer Attributes

Page 2:

Portraits & Sprites

Portraits for DoaE are stored in 48×48 bitmaps made up of 4 colors. When displayed in the game, these colors are black, skin color, brown, and whatever background color is chosen for the character. When the DoaE graphics engine loads the portraits in, it loads them in 8×48 slices like so:

  • caocao1af5.png
  • caocao2pm8.png
  • caocao3hf5.png
  • caocao4om8.png
  • caocao5sw7.png
  • caocao6vv9.png

(images from CayJay)

These slices are indexed with values 00-FF. That means in the original game there is a max of 255 "slices". There are about 30 completely unique characters (180 or so slices) and about 70 slices used for generic characters.

When loading a new portrait into the game, there are some rules:

  • The portraits must be 48×48 pixels.
  • The portraits must be 4 colors. However, these aren't the 4 colors you see in the game, they are:

BLACK (0,0,0)
GREEN (99,207,97)
BLUE (57,51,255)
WHITE (220,255,255)

The parenthesis show the exact RGB color mapping. Also note that "WHITE" becomes whatever background color you choose for the character in DoaEditor.

If you're looking for portrait backgrounds sonic penguin has provided a bmp with different portrait backgrounds to use for original portraits:

Portrait_Backgrounds_Master_by_zpsf5a0b50a.png

Loading Portraits With Feidian

Credit: MiDKnighT and Niahak

Software used (for me):

- Php –> http://www.php.net/archive/2010.php#id2010-03-04-1
- Feidian –> http://feidian.sourceforge.net/download.html
- nes8 template –> Download tiles.rar
- Infranview –> http://www.irfanview.com/
- Nana –> http://www.romhacking.net/utils/137/
- MS Paint
- Destiny of an Editor (DoaE tool)

Put feidian in the Php folder and extract nes8 from tiles.rar and stick it in the Phptiles folder. Also put the rom in the Php folder for simplicity.

OK so here's what we do next.

1. Find the tiles in the rom. You can use Nana to do this. Open the rom with nana at a dos prompt like "nana destiny.nes" and look at the tiles by pressing "t" and change to NES format by pressing the number 3 for NES tiles. To see the portraits right you have to use the "<" key to make the graphics 6 tiles wide then use pagedown or down arrow to find the portraits. You may have to use the right and left arrow keys to align it correctly. Then find the starting address of your portraits. To save time I found these already in the DoaE1 rom. They are at:

0x8810
0xC810

2. Use Feidian to unload those portraits at the DOS prompt (Start–>Command Prompt). Syntax is:

Code:
cd <folder where php and feidian live>
php feidian.php -cr nes8,6,128,0×008810 doae.nes output
nes8 = template
6 = # of tiles wide
128 = number of lines
0×008810 = starting address
doae.nes = rom
output = bmp output file

Once you run this you should have an output file that is basically a bitmap. If you open it up in paint you should see the portraits clearly in a blue/green/black/white state. It should look like this:

doae1_8x8.jpg

3. Now you'll want to pull portraits from another Rom. DoaE2 is the easiest… Use nana to find the starting addresses for the portrats in DoaE2 but I found some already at:

0x10
0x4010
0x8010

So the syntax would be:

php feidian.php -cr nes8,6,128,0×10 doae2e.nes d2

Now you'll have a d2 bmp file.

4***. The problem with DoaE2 portraits is that the colors are swapped. So if you try to directly use a DoaE2 portrait and put it in DoaE1 it won't look right. To fix this we can use Infranview to swap colors. Edit the palette on your DoaE2 bmp and switch the colors. The skin color of your characters should be green. The colors (specifically) should be:

0 0 0 black
97 207 99 green
57 51 255 blue
220 255 255 whitish

Now save your bmp.

Original DoaE2 colors:

d2_test_bad.jpg

Fixed colors (change green to white, blue to green, white to blue, and black to black (right color codes):

d2_test_good.jpg

5. Open your DoaE1 bmp and your DoaE2 bmp in paint. Zoom in on both. Cut your portrait from your DoaE2 bmp and paste it exactly over the DoaE1 portrait you are replacing. So for example you would cut DoaE2 Ji Ling and put him on top of DoaE1 Pang Tong.

6. Save your DoaE1 bmp after doing this (don't do save as, just save). For example here's how my 1st bmp looked for the Yuan Shao mod:

destiny1.jpg

(Note that I painstakingly added backgrounds to some of the portraits in MS Paint using some of the DoaE1 original backgrounds).

7. Now you can load your bmp back into the rom with feidian. Example:

php feidian.php -ci nes8,6,128,0×008810 output.bmp doae.nes

Note: If your portraits in the ROM look garbled after this it means that somehow during your process your bmp ended up in the wrong format. It needs to be the exact same format as the one you unloaded (DPI, resolution, colors, etc…)

8. Open Destiny of an Editor and change your general to the portrait you replaced. In this example it would be Pang Tong. It will look like Pang Tong in the tool but in the game it will be your new pic.

You're done!

*** If you want to use pics from other games, it can be trickier. Other NES games are fairly easy like ROTK1. You'll just have to pull the portraits out (either via screenshot or feidian) and change the colors to the blue/green/white/black format using the color codes I provided before by editing the palette in Infranview. If the pic has more than 4 colors (pretty much all SNES portraits do) you'll have to "Diffuse" down to 4 colors in Infranview. This could really mess up the pic if it's a SNES portrait or more complicated portrait because it uses more colors. However, you could always touch it up with MS Paint.

If you want to test and see how your portrait will look in the game (with a white background), edit the palette in Infranview and replace the colors with this:

green = 252 213 156
black = 0 0 0
white = 253 253 250
blue = 256 108 80

It's not exact but close enough… If you want to see how it would look with a different color background change white to whatever background color.

Example from Yuan Shao mod with a white background: (ooh pretty…)

destiny1_test.jpg

(NOTE: Don't save the bmp with these colors. The game won't recognize them)

Then export this palette for later reference.

Also note that anything that is white will use the background color you use in the DoaE tool. So if their eyes are white and you change the background color to purple their eyes will be purple (not good). To fix this either leave the background white or fill in the white colors in the portrait (besides the background).

New Portraits Banks for Up to 340 Unique Portraits

Credit: MiDKnighT

…..TO EXPAND YOUR ROM:

Use the latest version of "Destiny of an Editor" to expand your ROM (preferred method).
Now you have a 1MB ROM. This allows us to add more portraits and other stuff!

More info about ROM expansion can be found in this thread:

http://www.lordyuanshu.com/forums/topic/uber-rom-expansion

Now…a little about how the portrait system works. A portrait is made up of 6 horizontal slices. Each slice is indexed from 00 to FF and they are stored in 2 banks in the ROM at 0×8810 and 0xC810. The reason we could never have more than 255 slices before was because of this two character index system. In order to have MORE portraits we need a 2nd pointer, a place to put our new slices, and new code in the game to allow it to use our new banks.

…..USING NEW PORTRAIT BANKS:

You can use "Destiny of an Editor" to add new portrait banks while expanding your ROM and assign the portraits to generals (preferred). Or…

1. The 2nd pointer. Each general has a little "profile" if you will in the ROM. I'm going to borrow an old post from Niahak to show this:

Officer structure notes (from various sources, as well as DoaEd code)
STR
INT
Region
Sprite
Sprite color (AP as enemy)
DP as enemy
Soldiers (Enemy)
Soldiers (Ally)
Tactics
AGI
portrait 1
portrait 2
portrait 3
portrait 4
portrait 5
portrait 6
portrait BG (single-color BG only)
unknown <
unknown
Name spacing
Officer name

See the 2 "unknown" slots? We have never found any use for these 2 slots and it is likely that these were used for Japanese characters. I am using the 1st "unknown" slot for the 2nd portrait slice pointer.

With that said I will be using the following values for that byte:

00 = Use the original DOAE portrait banks.
F1 = This officer's portrait lives in new ROM page 16 or 17 (hex: 10 or 11)
F3 = This officer's portrait lives in new ROM page 18 or 19 (hex: 12 or 13)
F5 = This officer's portrait lives in new ROM page 20 or 21 (hex: 14 or 15)
F7 = This officer's portrait lives in new ROM page 22 or 23 (hex: 16 or 17)
F9 = This officer's portrait lives in new ROM page 24 or 25 (hex: 18 or 19)
FB = This officer's portrait lives in new ROM page 26 or 27 (hex: 1A or 1B)
FD = This officer's portrait lives in new ROM page 28 or 29 (hex: 1C or 1D)

Note: If you want to do the expanded sprites section below then don't use page FD

2. The assembly part (nasty). OK for the short version, just open your hex editor and paste this into 0x7CFE4 and 0xFCFE4: "4C3083000000". You'd be pasting this over "10044980E6F1".

Then copy this into 0x30340:

85158425A011B1F3C9F19004E9E185F1A51510064980E6F18515A4254CDACF

That's all the magic right there.

The first copy is changing the code that adjusts the ROM lookup for any slice at index 80 or greater to just jump to $8330 where I put my new code. Here's what the new code is doing and *this* is what took the most time to do:

00:8330:85 15 STA $0015 = #$0F
00:8332:84 25 STY $0025 = #$0F
00:8334:A0 11 LDY #$11
00:8336:B1 F3 LDA ($F3),Y @ $B8F9 = #$36
00:8338:C9 F1 CMP #$F1
00:833A:90 04 BCC $8340
00:833C:E9 E0 SBC #$E1
00:833E:85 F1 STA $00F1 = #$02
00:8340:A5 15 LDA $0015 = #$0F
00:8342:10 06 BPL $834A
00:8344:49 80 EOR #$80
00:8346:E6 F1 INC $00F1 = #$02
00:8348:85 15 STA $0015 = #$0F
00:834A:A4 25 LDY $0025 = #$0F
00:834C:4C DA CF JMP $CFDA

Essentially it has to figure out where to look in the ROM for the slice based on what the index number is and if that new bit is set.

3. Loading your portraits! Of course my preferred method is feidian. The two existing banks you'd load at 0×8810 and 0xC810. Note that any slice at hex:80 or above will go to page 2.

The new banks you can load into will be at:

0x40810 (F1)
0x44810 (F1 – 2nd page)
0x48810 (F3)
0x4C810 (F3 – 2nd page)
0x50810 (F5)
0x54810 (F5 – 2nd page)
0x58810 (F7)
0x5C810 (F7 – 2nd page)
0x60810 (F9)
0x64810 (F9 – 2nd page)
0x68810 (FB)
0x6C810 (FB – 2nd page)
0x70810 (FD)
0x74810 (FD – 2nd page)

Note: If you want to do the expanded sprites section below then don't use page FD

And with these new banks you can load 128 rows for each page (the first page has slices 00-7F, the 2nd page has slices 80-FF). Example commands which would load up banks F1 and F3:

Using Php and Feidian to Properly Inject Portraits

Credit: sonic.penguin

A common error when using php and feidian is getting the "Php is not an internal or external command" error message. This is one of the most technical aspects of DOAE Mod editing and often one of the most frustrating, yet also one of the most rewarding once you get it correct! These are step-by-step instructions that will help you to get new portraits into your DOAE mod once you have "Php" folder with Feidian installed properly into it.

1. Copy your php with feidian folder into C:
2. Open the command prompt using

cmd

3. Type in the following:

Type: cd/php
Type: php feidian.php

4. You will get a message that says
,—————————————————————————.
| FEIDIAN: The Freaking Easy, Indispensible, Dot-Image formAt coNverter |
| Version 0.90a (C)Derrick Sobodash 2003,2004 |
‘—————————————————————————’

Now type in the following, replacing the .bmp name and .nes name where necessary. Example below:

php feidian.php -ci nes8,6,128,0×040810 F1_1.bmp doae.nes
php feidian.php -ci nes8,6,128,0×044810 F1_2.bmp doae.nes
php feidian.php -ci nes8,6,128,0×048810 F3_1.bmp doae.nes
php feidian.php -ci nes8,6,128,0x04C810 F3_2.bmp doae.nes

If you were to go nuts with it you could load 340 unique portraits in a couple minutes if your bitmaps were ready.

When it works it should provide some output. Ie…here's what a good run looks like:

C:\Users\Owner>cd\php
C:\Php\php feidian.php
,—————————————————————————.
| FEIDIAN: The Freaking Easy, Indispensible, Dot-Image formAt coNverter |
| Version 0.90a (C)Derrick Sobodash 2003,2004 |
`—————————————————————————'
C:\Php>php feidian.php -ci nes8,6,128,0x40810,pictures1.bmp DOAE.nes

Injecting 8×8 into DOAE.nes…
    Converting bitmap to bitplane…
    Injecting new bitplane data…
DOAE.nes was updated!

4. Assigning a portrait to a general. Destiny of an Editor now allows you to pick your portrait bank with an expanded ROM!

Loading New Sprite Banks for Up to 210 Sprites (Expanded ROM)

Credit: MiDKnighT

Follow these instructions to add 126 new sprite slots for a grand total of 210 sprites in the game. Likely more than you will ever need.

You can use "Destiny of an Editor" to expand your ROM and add new sprite slots (preferred) or…

1. Add the following hex code to these locations for the new slots:

0x7DE71: 4CC0A5
0xFDE71: 4CC0A5
0x325D0:
E0D290034CDADEA01C84F484F2E0A890
0818A02EE9A74CE9A5E07E900818A01D
E97D4CE9A5A01CE953AA4C6EDE000000

The new code does the following:

0x7DE71 and 0xFDE71:
00:DE61:4C C0 A5 JMP $A5C0

0x325D0:
00:A5C0:E0 D2 CPX #$D2
00:A5C2:90 03 BCC $A5C7
00:A5C4:4C DA DE JMP $DEDA
00:A5C7:A0 1C LDY #$1C
00:A5C9:84 F4 STY $00F4 = #$00
00:A5CB:84 F2 STY $00F2 = #$00
00:A5CD:E0 A8 CPX #$A8
00:A5CF:90 08 BCC $A5D9
00:A5D1:18 CLC
00:A5D2:A0 2E LDY #$2E
00:A5D4:E9 A7 SBC #$A7
00:A5D6:4C E9 A5 JMP $A5E9
00:A5D9:E0 7E CPX #$7E
00:A5DB:90 08 BCC $A5E5
00:A5DD:18 CLC
00:A5DE:A0 1D LDY #$1D
00:A5E0:E9 7D SBC #$7D
00:A5E2:4C E9 A5 JMP $A5E9
00:A5E5:A0 1C LDY #$1C
00:A5E7:E9 53 SBC #$53
00:A5E9:AA TAX
00:A5EA:4C 6E DE JMP $DE6E

Essentially you have 2 original and 3 new ROM pages for sprites (1C, 1D, and 2E). You can now load 42 sprites into each page at the following locations:

0x00090 (page 1 - original mod)
0x05A10 (page 2 - original mod)
0x70090 (page 1C) (in IPS Patch 1.2 Page 1 of New Sprites starting w/ LiuBei2)
0x74090 (page 1D) (in IPS Patch 1.2 Page 1 of New Sprites starting w/ HuangZhong2)
0xB8010 (page 2E) (currently unused)

2. Load your sprites… This part can be a pain. The likely source of your sprites is going to be DoaE2. But the problem is the format is different.

DOAE1 format:

liu_bei_sprite.jpg

DOAE2 format:

guan_yu_doae2.jpg

Problems:

  • DoaE2 character starts facing sideways before he starts facing backwards.
  • DoaE2 character is looking sideways in the wrong direction vs DoaE1.
  • DoaE2 character's last sideways stance is the back not the front of the character (reverse from DoaE1).

So…in order for you to get your DoaE2 portraits to work in DoaE1 you'll need to adjust the sprite to match the DoaE1 format then load it into your ROM.

If done properly in DOAE1 format, it will appear like this:

Guan_Yu_NES_Sprites.JPG

You can use nana to find the sprites in the ROM and feidian to unload/load them. Example unload from doae2:

php feidian.php -cr nes8,1,1008,0xd010 doae2e.nes d2sprites1.bmp

This will unload a whole page of sprites starting at 0xD010.

Example command to load a whole page of sprites:

php feidian.php -ci nes8,1,1008,0×70090 newsprites1.bmp YuanShao_DoaE.nes

You can put 42 sprites on each ROM page.

3. Assigning your new sprite to a general. The current sprites available are 00-53. If you have loaded pages 1C, 1D, and 1E with sprites then you can now use slots 54-D1.

Changing Default Portrait Background Colors

Credit: MiDKnighT

You can change the portrait background colors in DoaEditor for a general but you are limited to these colors right?

00=Black (no portrait)
01=Light Blue
02=Dark Blue
03=Green
04=Purple
05=Gray
06=Hot Pink
07=Rust Orange
08=Clown Barf (greenish-brown)
09=White

Wrong, you *can* change those colors… These colors are set at 0x3D10E (or 0x7D10E and 0xFD10E in 1MB rom):

21 11 1A 14 00 15 17 18 20

And you can use the NES pallettes to see these colors:

pallettes.jpg

Note that you can't change the "00 – No portrait color" but you can change all the others. Want to change "hot pink" to gray? Easy, just change the "15" in the hex sequence above to "2D". Want to change "clown barf" to an actual brown? Just change "18" to "08".

Changing Sprite Colors

Credit: Meteorstrike and MiDKnighT

This is actually pretty easy. Just change line 0x3C610 (0x7C610 and 0xFC610 in a 1MB ROM) using the color palette below:

sprites.jpg

Towns

Town names can be changed by:

1. Open the ROM in your hex editor.

2. Load the doaetable.tbl from DoaEditor.

3. Find the town names at 0x3FC90 (0x7FC90 and 0xFFC90 in a 1MB ROM)

4. Change the town name as needed. Be careful about spacing! The other town names have pointers to them and we don't want to move them.

towns.jpg

Changing Town Colors

Credit: MiDKnighT

Town colors can be changed by playing with the pallettes at 0x3C665 to 0x3C66F (in a 1MB ROM 0x7C665-0x7C66F and 0xFC665-0xFC66F). Simply use the NES color palette to know the colors:

pallettes.jpg

Here I have changed all the values from 0x3C665 to 0x3C66F (in a 1MB ROM 0x7C665-0x7C66F and 0xFC665-0xFC66F) to "01" which is blue:

town_colors.jpg

Night has fallen upon Xu Zhou…

You can also change the colors of the world map, forts, villages, etc… All the palettes for these are in the 0x3C6## area (0x7C6## and 0xFC6## in a 1MB ROM). See below…

World Map Color Editing

Credit: sonic.penguin

You can edit the world map colors at the following addresses. Use the Palette to choose colors. Bear in mind that some tiles use the same colors, for example, grass spots and trees.

World Map Color Edits (256 ROM):
3C601-7C602 Grass Colors
3C603- Tree Colors and Grass Spots
3C605-7C607 Mountain Colors
3C609-7C60B Hill Colors
3C60D-7C60F Water Colors

World Map Color Edits (1Mb ROM):
7C601-7C602 Grass Colors
7C603- Tree Colors and Grass Spots
7C605-7C607 Mountain Colors
7C609-7C60B Hill Colors
7C60D-7C60F Water Colors

pallettes.jpg

Inn

Credit: MidKnight

The cost of staying at the inn comes down the formula MULTIPLIER * # OF OFFICERS IN YOUR PARTY. The key to finding the multilier lies here:

0E:91B7:AC 11 60 LDY $6011 = #$02
0E:91BA:BE 11 60 LDX $6011,Y @ $6013 = #$7E
0E:91BD:BD A2 91 LDA $91A2,X @ $9220 = #$01

$6011 = Map hierarchy (02 = inside a building). It uses that value to pull the place ID which in this case is 7E (Xu Zhou). Using that ID it looks at the data in $91A2 to $9221 to find the multiplier which is 0x391B2 to 0×39231 in the ROM. This explains why the prices are vastly different between Xu Zhou, who's multiplier is 01, and Jian Ye, who's multiplier is 0x40 (64).

Stores

Credit: Meteorstrike, James, and MiDKnighT

Want to edit what the shop keeper sells? Want to edit the price? Sure… First, you need to know the item codes.

The list of items is on page 1.

So want to edit the Chang An weapon store? Here's an example of how to do it…

The weapons for sale in Chang An are:

Flail
Ax
Club
Leather
Bandana
Cap

Looking up their item codes I have:

41 42 43 5B 68 69

Searching for this string I find it on Line 0x390D0 in my hex editor.

Simply change those values and you change the items.

But what about the price? The item names and prices are all stored in the ROM at 0x2FAF0.

1. Use a hex editor that supports the "Load Table" feature.

2. Open the ROM in the hex editor and load the doaetable.tbl from DoaEditor.

3. Now on the right you should be able to see the item names at 0x2FAF0. It should look like this:

Items.jpg

The 4 characters before the item name are the price. For example the Flail is "64 00". These two entries are swapped. So it's actually 0064. Using your windows calculator in scientific mode you can convert 0×64 in hex and it is 100 in decimal which is the price of the Flail. Because there are 4 digits in the price the maximum price in the game is "FF FF" which is 65535. Note that you can also change the weapon and item names here too but be careful not to move other names because of the pointers.

You can also change the power of elixirs and resurrects with the following:

Elixer A Address (100 HP): (Default= 00 64)
High Value: 38CBF
Low Value: 38CC3

Elixer B Address (500 HP): (Default= 01 F4)
High Value: 38CC9
Low Value: 38CCD

Elixer C (1000 HP) Address: (Default= 03 E8)
High Value: 38CD3
Low Value: 38CD7

Elixer D (4500 HP) Address: (Default= 11 94)
High Value: 38CDD
Low Value: 38CE1

// Storing the value of 400 into $11 – $12 so that it can be added
// to the General's HP when Resurrect is used:
$8C8F:A9 01 LDA #$01
$8C91:85 11 STA $11 = #$A7
$8C93:A9 90 LDA #$90
$8C95:85 10 STA $10 = #$10

8C8F = 0x38C9F so if you want to change the resurrect value you would change the following from 190 (400) to something else:

0x38CA0: 01
0x38CA4: 90

Villagers

Credit: Meteorstrike, sonic penguin, and MiDKnighT

Villagers are defined at around 0×31### and 0×32###. For example one of the first villagers you see in LouSang is:

Quote:
0x31AD1 = Villager 1 Starting Y1 Position
0x31AD2 = Villager 1 Starting Y2 Position
0x31AD3 = Villager 1 Starting X1 Position
0x31AD4 = Villager 1 Starting X2 Position
0x31AD5 = Villager 1 Dialog Line
0x31AD6 = Villager 1 Dialog Line 2
0x31AD7 = Villager 1 General ID

Now if I change 0x31AD7 to C0 and 0x31AD5 to 98, then you will be able to recruit Lu Bu at the beginning of the game… without any buggy or glitchy graphics… If you already have all the "Dialog Line" memory locations as you (supposedly) do, then all you have to do is to change the General ID to the General you want that villager to be, which is just 2 bytes later…

http://www.gamefaqs.com/boards/563402-destiny-of-an-emperor/47999342?page=6

With this information you can turn Song Ren into a villager or turn a villager into Song Ren.

The villager addresses reads just like the map coordinates at $60-$63. There is also additional information stored in each of their location bytes. Namely:

Starting Y1 Position: Which text bank it uses. It takes the value and does this:

AND #$30
 LSR
 LSR
 LSR
 LSR

Which essentially removes the Y1 position and produces a text bank number.

Starting Y2 Position: Event associated with the villager. Usually it means you talk to them once and their text switches to something else. This is true with the merchant in the first village who gives you gold and rations. If he didn't have this event he'd keep giving you money forever. So when it pulls the Y2 value it does this to the value:

AND #C0

Which again chops the Y2 value giving us 0x80 which enables the event (if it's set).

Starting X1 Position: Villager direction. It takes the value in the X1 position and does this to it:

 LSR 
 LSR
 LSR
 LSR

Which again chops the X1 value and gives us a value we can use to tell the villager how he is standing. Once we LSR the value 4 times, we are left with these possible entries:

0 = face up, wander around
1 = face down, wander around
2 = face left, wander around
3 = face right, wander around
4 = face up, feet not moving
5 = face down, feet not moving
6 = face left, feet not moving
7 = face right, feet not moving
8 = face up, feet moving
9 = face down, feet moving
A = face left, feet moving
B = face right, feet moving

C-F could also be used but they just repeat 4-7.

Here are some known locations for villagers.

LuoSang – 31AAE-31AE5
XuZhou – 31A75-31AAc
QingZhou – 31A51-31A73
DaXing – 31A34-31A4F
TieMenXia – 31A07-31A32
SiShuiGate – 319BA-31A05
HuLaoGuan – 31996-319B8
Old Luo Yang 31931-3196D
YangZhou – 3190D-3192F
ChangAn – 318B6-3190B
Yuan – 3187B-318B4
HuaiNan – 31857-31879
ChenCang – 31847-31855
NanYang – 3180C-31845
BoHai – 317D8-3180A
Chang – 317CE-317D6
GuangZong – 317A1-317CC
JiZhou – 3177D-3179F
ChangSha – 31742-3177B
GuiYang – 3170E-31740
LingLing – 316E1-3170C
WuLing – 316B6-316DF
LuoFengPo – 31420-31428
FuShui – 31688-316B3
Luo – 3163F-31686
MianZhuGuan – 31619-3163D
ChengDu – 315EE-31617
JianAn – 315C3-315EC
HuiJi – 315AD-315C1
Wu – 31579-315AB
PoYang – 3155A-31577
JinDu – 31534-1558
JianYe – 31502-31532
GuangLing – -314DE-31500
HeFei – 314C8-314DC
RuNan – 314AB-314C6
ChenLiu – 3148E-314A9
Chen – 3145C-3148C
New Luo Yang- 3142A-3145A
Dong Zhuo's Hut in Mt. Da Xing- 31416-3141E
Unknown (uses Merchant sprite)- 3140E-31414
Merchants/Inn people – 31111-3113A

Level Ups

Soldier Gains

Credit: ludmeister, Meteorstrike, and MiDKnighT

There are 5 different soldier gain level up algorithms:

  • Huang Zhong leveling
  • Ma Chao leveling
  • Guan Yu leveling
  • Zhao Yun leveling
  • Zhang Fei leveling

How quickly these gain soliders depends on the values at 0x3B51B. Each value represents 10 levels of solider gains:

  • Huang Zhong: 24 24 1F 1F 1A
  • Ma Chao: 22 22 22 22 1A
  • Guan Yu: 24 24 24 1F 1A
  • Zhao Yun: 1F 22 26 26 1A
  • Zhang Fei: 26 26 24 1F 1A

As you can see Zhao Yun starts off slow and picks up while Huang Zhong starts off fast then…gets old. If you change these values you'll change the soldier progression. To test this, all 5 of these start off with 100 soliders. So when you gain your first level, you can use this algorithm to see how many soldiers they will have:

#OFSOLIDERS * (256 + MULTIPLIER) / 256

MS Excel was made for this. Just make 50 rows (1 for each level) and put the above formula in using the different multiplier every 10 rows. Make sure your soldiers do not exceed 64k at end game.

So using the formula, after 1 level, Huang Zhong and Guan Yu would have 114 soldiers while Zhao Yun would only have 112 soldiers. Remember that the level up multiplier will change every 10 levels. So for example, at level 11 Zhao Yun's multiplier would change from 1F to 22 meaning that he will start to gain soldiers faster.

Additional Soldier Progressions

Credit: MiDKnighT

How about 25 different soldier growth progressions? To do this we'll need to add some new assembly code. To do this add the following at these ROM locations:

0x3B4B0:
9D626120FBC407B5297FA84C1DB500A2
0x3B4E6: 4C0BB5
0x3B510:
9D6161A5129D626168A860A90D2082C4
8AA6254CD9B40000A5104CAFB4A90D20
82C400000A141E28AE7360CA8610A900
0x37510:
8625B950B5AA4C0BB50000A90E2082C4
4C00B5A90E2082C40000000000000000
EAEAEAEAEAC0649005A9FA4C42B5C04B
9005A9C84C42B5C0329005A9964C42B5
A96485104C13B5000000000000000000

Now put all your level growths at 0×37560. Example:

0x37560: 24241F1F1A222222221A2424241F1A1F2226261A2626241F1A0A…continued…

You can put up to 5*25 entries there (125). And now in the general's "Soldiers (Ally)" slot you can put any of the following values for different soldier progressions:

  • 80 – Huang Zhong leveling (0×37560-0×37564) (starts with 100 soldiers)
  • 85 – Ma Chao leveling (0×37565-0×37569) (starts with 100 soldiers)
  • 8A – Guan Yu leveling (starts with 100 soldiers)
  • 8F – Zhao Yun leveling (starts with 100 soldiers)
  • 94 – Zhang Fei leveling (starts with 100 soldiers)
  • 99 (starts with 100 soldiers)
  • 9E (starts with 100 soldiers)
  • A3 (starts with 100 soldiers)
  • A8 (starts with 100 soldiers)
  • AD (starts with 100 soldiers)
  • B2 (starts with 150 soldiers)
  • B7 (starts with 150 soldiers)
  • BC (starts with 150 soldiers)
  • C1 (starts with 150 soldiers)
  • C6 (starts with 150 soldiers)
  • CB (starts with 200 soldiers)
  • D0 (starts with 200 soldiers)
  • D5 (starts with 200 soldiers)
  • DA (starts with 200 soldiers)
  • DF (starts with 200 soldiers)
  • E4 (starts with 250 soldiers)
  • E9 (starts with 250 soldiers)
  • EE (starts with 250 soldiers)
  • F3 (starts with 250 soldiers)
  • F8 (starts with 250 soldiers)

Initial soldier count code added:

00:B4AB:4C 20 B5 JMP $B520
00:B520:A9 0D LDA #$0D
00:B522:20 82 C4 JSR $C482

…function to switch page to 0D…

00:B525:C0 64 CPY #$64
00:B527:90 05 BCC $B52E
00:B529:A9 FA LDA #$FA
00:B52B:4C 42 B5 JMP $B542
00:B52E:C0 4B CPY #$4B
00:B530:90 05 BCC $B537
00:B532:A9 C8 LDA #$C8
00:B534:4C 42 B5 JMP $B542
00:B537:C0 32 CPY #$32
00:B539:90 05 BCC $B540
00:B53B:A9 96 LDA #$96
00:B53D:4C 42 B5 JMP $B542
00:B540:A9 64 LDA #$64
00:B542:85 10 STA $0010 = #$00
00:B544:4C 13 B5 JMP $B513
00:B513:A9 0E LDA #$0E
00:B515:20 82 C4 JSR $C482
…function to switch page to 0E…
00:B518:A5 10 LDA $0010 = #$C8
00:B51A:4C AF B4 JMP $B4AF

Level up code added:

00:B4D6:4C 0B B5 JMP $B50B
00:B50B:A9 0D LDA #$0D
00:B50D:20 82 C4 JSR $C482
…function to switch page to 0D…
00:B510:4C 00 B5 JMP $B500
00:B500:86 25 STX $0025 = #$0F
00:B502:B9 50 B5 LDA $B550,Y @ $B5AF = #$FF
00:B505:AA TAX
00:B506:4C 0B B5 JMP $B50B
00:B50B:A9 0E LDA #$0E
00:B50D:20 82 C4 JSR $C482
…function to switch page to 0E…
00:B510:8A TXA
00:B511:A6 25 LDX $0025 = #$FF
00:B513:4C D9 B4 JMP $B4D9

TP Gains

Credit: Meteorstrike

First of all you must be learning a new tactic to gain tactical points. And you have to have an officer in your party capable of learning the new tactic (INT must be high enough). With that said, here's a post to show the random TP gains:

Now, as far as how many POINTS you gain for the TP, this is stored in a list of 16 entries, each which contains a number between 3 and 5. A random entry in this table is chosen and its number is how many TP you gained.

The table is located at 0x3B666 and contains the following values:

$B656 == 0x3B666 =
{
03 04 05 03 04 05 04 05
04 05 04 05 04 05 04 04
}

So you got the following probabilities to gain TP:

03 = 2 in 16
04 = 8 in 16
05 = 6 in 16

http://www.gamefaqs.com/boards/563402-destiny-of-an-emperor/47999342?page=7

Simply change the values in that table and you change the probabilities of how many tactical points you get on each level.

Changing Experience Needed for Level Up

Credit: James, Meteorstrike, and ludmeister

There is a nice tool to do this on kongming.net. See:

http://kongming.net/doae/rom_hacking/level-up-progression/

Also:

0x39a28-0x39a2f- Experience gain multiplier (by chapter)

05 08 0a 0f 11 14 19 1e

Ever notice how you gained about 4x more experience points when you entered a new chapter? It's because of the formula for calculating experience, which is based off of the above list. Each officer's/rebel force's experience value is determined separately.

Soldiers * multiplier / 256 = experience awarded

The formula was arrived at via mathematics, not via code inspection, so it may be off, if ever so slightly.

Events

Events are things that happen in the game. For example when Liu Bei leaves and sits on the fancy chair. That is an event. Or when they build a bridge south of Gui Yang. An event controls that too… Events actually call to a specific part of the ROM to do something. For example, event 8822 is when Tao Qian asks you if you'd like to take over. Once you get into that event the code takes over and you lose Liu Bei… The "8822" is jumping to a part of the code. Namely A288. It's essentially "8822" flipped around where the first 2 represents the 3rd ROM section value (8 then 9 then A since the ROM part starts at $8000). So you can absolutely influence events by changing the numbers/letters but you have to know where we want to jump to. That's the tricky part.

Event List

Credit: Xu Yuan and MiDKnighT

  • Event 0025 – Yuan Shu whining about Dong Zhuo
  • Event 0221 – Dead
  • Event 0222 – Recruiting Song Yong and Song Ren
  • Event 0A28 –Villager telling you to go to the cave in the West
  • Event 1033 – Qing Long recieved! (Appears to work anywhere, just assure that the person you may give this event to has more than one line.) Note from sonic.penguin: You can actually use this to gain Qing Long after a battle.
  • Event 1229 – Battle with Yuan Shang (same issue as before with Ma Yuanyi)
  • Event 152F – Coming to the rescue of Shu?
  • Event 1827 – Showing the Intro Letter to Sima Hui's servant
  • Event 182D – Saving Guan Yu from Wu? Or maybe its Zhang Fei? Trigger to report back to Liu Bei
  • Event 1A25 – Yuan Shao's Retreat at Luo Yang
  • Event 1D2F – Liu Bei's praising Guan Yu and Zhang Fei and talk about Swordsmith
  • Event 2023 – Recruiting Chen Deng
  • Event 248E – From the one instance I experimented at the fellow seemed to sell only the Xuzhou items, maybe this changes depending on what Chapter Zone you are in? Worth more experimentation.
  • Event 2D27 – Hearing of Pang Tong and Zhuge from Sima Hui
  • Event 2D31 – Swordsmith going on about his masterpiece and need for ore.
  • Event 2E2C – Jingzhou is at peace, stop Yuan Shao. (Odd? I thought you couldn't finish Jingzhou without defeating Yuan Shao?
  • Event 4134 – After being trounced by Sima Yi's Thunder. (Event Trigger to get Guan Suo I believe.)
  • Event 4325 – Dong Zhuo is dead message? (Not sure what this does or who normally says it. Liu Bei?
  • Event 4333 – Battling with Lu Meng
  • Event 482A – Zhuge Liang sleeping event. Appears to work nearly flawlessly, Zhuge Liang's sprite will appear where ever the X/Y ordinarily is supposed to. Unfortunately he runs off to Gui Yang.
  • Event 4923 – Battling Ma Yuanyi (Will bring up the Ma Yuanyi fight with Rebel Force's with unbeatable numbers if no battle is won after starting a new game.)
  • Event 4934 – Sima Yi trigger…? I'm not entirely sure what this does. (Note from Boneduke: this one makes Runan appear on your Gullwing list in the original ROM. Unlike most other gullwing warps, Runan isnt given from just entering the city)
  • Event 4D27 – Yuan Shu trying to flee from his loss. If "No" is selected, Yuan Shu joins Yuan Shao for another battle.
  • Event 4D2D – Someone tells party that Zhuge Liang has some info. for them.
  • Event 4E28 – Xu Zhe's (Xu Shu's) Stalker moving from the bridge (what an odd plot device?)
  • Event 5134 – Allows the bridge to be built south of Luo Yang and triggers rebuilt Luo Yang
  • Event 5824 – Meeting with Sun Ce
  • Event 5829 – Level Up! Event. Works perfectly.
  • Event 5991 – Inn, doesn't seem that you ever have enough money when used outside of a real inn. Odds are though that the cost can only go to 65,535 gold. So if you want to make a really expensive inn… by all means.
  • Event 642B – If you had lost to Zhao Fan the first time I believe? (Seems to always be an ambush though)
  • Event 642D – How peculiar… this is clear the actual "Recruit Zhuge Liang" event but… if an officer in an area were to join you anyway they join you instead. In fact testing this on Song Ren and Song Yong they can be recruited individually. How strange. This may have potential.
  • Event 651E -Saving seems to work fine and it appears that castles are designated by Zones… it seems. At least in LouSang when I tried to invite Liu Bei it had told me that it was Tao Qian's castle.
  • Event 6792 – A supply station, it appears to work anywhere. I guess that has a bit of… potential. (Note from Boneduke: this is a Food vendor)
  • Event 6C34 – Sima Yi's death.
  • Event 712E – Jingzhou finished trigger.
  • Event 7224 – Yang Jin recruitment
  • Event 7825 – Mission Objective: Defeat Yuan Shu
  • Event 7831 – Some Wu Officers running away saying they'll have the final victory.
  • Event 7923 – Battling the Zhang Bros. (Seems to work perfectly, unsure of after events though.)
  • Event 7B2D – Xu Zhe telling the party where to find Zhuge Liang
  • Event 8029 – Defeating Yuan Shao and Shu for the final time.
  • Event 8525 – Returning to Liu Bei after defeating Dong Zhuo
  • Event 8728 – Receive the Black Powder from Sima Hui
  • Event 8822 – Obtaining Xuzhou (May work in Castles?)
  • Event 8B24 – Meeting with Cao Cao
  • Event 902E – Pang Tong becomes a battle.
  • Event 9433 – Sun Quan's death event.
  • Event 9931 – "Tell Liu Bei that Wei has an Alliance with Wu". I'm not sure what that does. (Note from Boneduke: this is one of two events that must be triggered in order to progress the storyline from Chengdu to Wu in the original ROM. The other is event 7831)
  • Event 9D34 – Credits!
  • Event A12D – Zhang Fei gathering intelligence on Wu.
  • Event A133 – Battle with Pirates. (Appears to work anywhere and unlike other "forces" when called randomly these pirates have set amounts of Troops. (note from Boneduke: finishing this Pirate battle also grants a gullwing warp. I believe it is Jianan in the original ROM)
  • Event A429 – Being pointed towards the Ma's.
  • Event A42E – News on Zhuge Jin visiting Liu Bei to say that Zhuge was home (start of the Zhuge chain)
  • Event A624 – Chi Tu Ma Story. (For what it's worth this seems to work anywhere)
  • Event B08E – Well it's clear the Merchant format… but he continues to sell the Weapons from the value above. This doesn't make much sense all in all… maybe it depends on the NPC you attached it to?
  • Event B327 – Buying the Silver Key (I think?) from the Merchant. The 4000 Gold is still required.
  • Event B726 – Finding out info. on the walls of Nan Yang
  • Event B72E – Pang Tong joins you (and likely cancels the encounter with him)
  • Event B731 – I'm not sure who this belongs to. I'll paste the lines though and see if anyone recognizes them. You routed my men. In all my years of war, I[>] have never suffered such adefeat. I would[>]be honored tofight at your side if you'll[>]have me.[>][EVENT-B731] My guess is either Wei Yan or Huang Zhong, but the text has been jumping around a bit recently, so I'm not too sure.
  • Event BD30 – Liu Bei declaring himself Emperor.
  • Event C523 – Han Zhong Bridge Event (Requires Han Zhong to activate)
  • Event C533 – Recruiting Jiang Wei . Just like the Zhuge recruitment this seems to be able to be used nearly anywhere.
  • Event CA2A – Directing the player back to LouSang to find Zhuge Liang. (This does put Cui Zhouping in his home, wasn't there a theory that there were two sets for Lou Sang only because of Cui Zhouping or something?)
  • Event CB28 – Receives Zhou Ltr, I wonder if it works on earlier Zhao Yun's found? (Note from Boneduke: No, I don't think it would - Zhao Yun has to be standing in the exact place he is in the original ROM when you offer him the letter, in order to trigger the proper response. If you even move him one space in the same Place, the event no longer works. So I am sure it would not work if you tried to trigger it on a villager/officer in a different place - such as the Zhao Yun found earlier in the bar)
  • Event CC26 – Intro letter given. (If you're going to give this to someone new, assure they have a secondary line so you're not given more than 1 Intro Letter if you speak with them again.)
  • Event CD92 – Outside billeting appears to work fine and I guess that has potential for swapping officers out on the fly.
  • Event E516 – Zhao Yun's Recruitment Pledge
  • Event E628 – Having two bandits join you in a tunnel?
  • Event E62A – Cui Zhouping telling you he's already left.
  • Event E724 – Wang Jin?
  • Event E91C – Main recruit event.
  • Event ED2E – If you ram into the door… speech.
  • Event EE2A – Zhao Fan having you rest. If accepted it is the same case as the Ma and Yuan battle scenario as displayed earlier.
  • Event F231 – Lu Bu's Demise. (Trigger to assure he doesn't appear again if I had to guess?)
  • Event FA20 – Cao Cao's Messenger on Yuan Shu
  • Event FA20 – Liu Bei's warning to his troops about Yuan Shao.
  • Event FA20 – Trigger for the majority of the Jingzhou battles.
  • Event FA31 – Request to make the bomb to blow up the canal (I assume that having the three pieces needed will give you the bomb)
  • Event FB32 -Request to defeat Brigands

Items Awarded for Events

Credit: ludmeister

I was curious about where the item gains were defined during events, and I think I found many of them:

This one is tested, and I was able to change the reward:

0x37333:    "51" <– Item ID for Qinglong, gained after Pirates defeated, in Jin Du

I found four other event item gains by doing a search for "206FE9", which translates to

20 6F E9 JSR $E96F

This subroutine gives the item to the first officer with space to carry it. Here are four others item gains:

0x366dd: "1A" <– Get Intro Letter
0x3680f: "18" <– Get Silver Key after paying 4000 gold
0x368a2: "1B" <– Get Gunpowder after talking to Sima Hui
0x368dc: "22" <– Get Zhou Letter from Zhao Yun's sister

Found where the Gemsword is, in Wang Yun's safe. (19 is Gemsword's ID)

0E:8BE4:A9 19 LDA #$19

This instruction is found at 0x38bf4.

Forced Officer Leave Events

Credit: MiDKnighT

I’ve added 12 forced officer leave events. Here’s the main things to know about it:

  • You add the event to the text. Example: “Lu Bu has been defeated, Song Yong ran home to his mommy.[EVENT-A83F][END]”
  • This probably only works in the “after battle” text. I haven’t tested it anywhere else.
  • There is a list at 0xF4200 where you would put the officer IDs for the generals you want to leave for each event.
  • The events are:

[EVENT-903F] (general ID: 0xF4200)
[EVENT-963F] (general ID: 0xF4201)
[EVENT-9C3F] (general ID: 0xF4202)
[EVENT-A23F] (general ID: 0xF4203)
[EVENT-A83F] (general ID: 0xF4204)
[EVENT-AE3F] (general ID: 0xF4205)
[EVENT-B43F] (general ID: 0xF4206)
[EVENT-BA3F] (general ID: 0xF4207)
[EVENT-C03F] (general ID: 0xF4208)
[EVENT-C63F] (general ID: 0xF4209)
[EVENT-CC3F] (general ID: 0xF420A)
[EVENT-D23F] (general ID: 0xF420B)

So for example if you wanted Song Yong to leave on event ID A83F you’d put 36 (Song Yong’s officer ID) in 0xF4204. Hex changes are:

0x37F90:
00000000000000000000A93D2082C460
208ABF4CA6C4208ABF4CA6C4208ABF4C
A6C4208ABF4CA6C4208ABF4CA6C4208A
BF4CA6C4208ABF4CA6C4208ABF4CA6C4
208ABF4CA6C4208ABF4CA6C4208ABF4C
A6C4208ABF4CA6C478EED9FF4CC9EFFF

0xF4010:
A9009D00638E1078A9FF8D1178A200BD
A860CD1078D0038E1178E8E008D0F0AD
1178C907F006AAA900201881A9FF8D12
78A200BD9060CD1178D0038E1278E8E0
07D0F0AD1178C9FFF017AE1278E007B0
10BD91609D9060E8E007D0F5A9FF8D96
60A9FF8D1378A200BD3060CD1078D003
8E1378E8E041D0F0AD1378C9FFF00EAE1
378BD31609D3060E8E041D0F560000068
C992D00748AEF081200080C998D00748A
EF181200080C99ED00748AEF281200080
C9A4D00748AEF381200080C9AAD00748
AEF481200080C9B0D00748AEF5812000
80C9B6D00748AEF681200080C9BCD00
748AEF781200080C9C2D00748AEF881
200080C9C8D00748AEF981200080C9C
ED00748AEFA81200080C9D4D00748AE
FB812000804C8ABF9DA8609D9C606000

0xF7F90:
00000000000000000000A90D2082C44C
90800000000000000000000000000000

Miscellaneous

Iron Ore bug fix

Credit: Meteorstrike

To avoid the open treasure chests bug which can cause you to miss key items like the Iron Ore, do the following:

0x3B604 = 20 7C B7

Patch them to:

0x3B604 = 4C FB B5

Ref: http://kongming.net/doae/glitches/open-treasure-chests/

For all the gory details on this see: http://faqs.ign.com/articles/974/974431p1.html

Guo Si bug fix (Expanded Rom only)

Credit: ludmeister

it's the notorious mysterious "Smite Guo Si" bug. You know the one… if you were to cancel the leader's move in battle, it overwrote $6312 with "00". This has the effect of killing Guo Si and removing him from the game.

Here's the fix:

0x3ae2b:
"A678 A900 9D1362" -> "A91E 2082C4 EAEA"
0x7ae2b:
a90e 2082c4 a678 e0ff d002 a200 a900 9d1362 4c1bae

Effectively, this subroutine was zeroing out something concerning officer orders. It is officer before the one that canceled that is affected by this subroutine. Of course, when we cancel the leader's orders, we zero out the value corresponding to the member who goes before him in battle… and that means "ff" gets added to the pointer where party orders get stored ($6213). So "00" is placed in $6312, which happens to be the status byte for poor old Guo Si. You just toasted him.

The new subroutine checks for the "ff" value, and puts a "00" in there instead, thus saving Guo Si's life. I'd say he owes me now.

Keeping characters that leave (Liu Bei, Guan Yu, Zhang Fei, Lu Bu, Xu Shu)

Credit: MiDKnighT

To keep Liu Bei from leaving your party, change:

0x3630A: A2808E9E6000
0x36314: FF

Which changes this:

00:A2FA:8E AA 60 STX $60AA = #$A8
00:A2FD:8E C2 60 STX $60C2 = #$03
…
$A303:A9 02 LDA #$02

To this:

00:A2FA:A2 80 LDX #$80
00:A2FC:8E 9E 60 STX $609E = #$00
…
00:A303:A9 FF LDA #$FF

And now Liu Bei stays.

To keep Guan Yu and Zhang Fei change these 4 lines:

0x36FA0-0x36FDF:
8562A91E8563EAEAEAEAEAEAEAEAEAEA
EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA
EAEAEAEAEAEAEAEAEAEAEAEAEA85F1AA
EAEAEAA90185F1A200EAEAEAA91220C6

Some of the main things removed are:

00:AFA3:A9 00 LDA #$00
00:AFA5:8D 9C 60 STA $609C = #$80 <— clearing alive status
00:AFA8:8D 9D 60 STA $609D = #$80 <— clearing alive status
00:AFAB:8D A8 60 STA $60A8 = #$A9 <— removing from your party
00:AFAE:8D A9 60 STA $60A9 = #$AA <— removing from your party
00:AFB1:8D C0 60 STA $60C0 = #$0A
00:AFB4:8D C1 60 STA $60C1 = #$0A
00:AFB7:8D B4 60 STA $60B4 = #$8C
00:AFBA:8D B5 60 STA $60B5 = #$8C
00:AFBD:85 F1 STA $00F1 = #$00
00:AFBF:AA TAX
00:AFC0:20 FF 9D JSR $9DFF <– subroutine that removes general
00:AFC3:A9 01 LDA #$01
00:AFC5:85 F1 STA $00F1 = #$00
00:AFC7:A2 00 LDX #$00
00:AFC9:20 FF 9D JSR $9DFF <– subroutine that removes general

To change the guys sitting in the chairs at Chang Sha and Gui Yang. Change:

0x312F8 from "A9" to some other general ID for Chang Sha.
0x3134A from "AA" to some other general ID for Gui Yang.

To keep Lu Bu after Yuan Shao ambush, change:

0x3AEB5 from "BC" to "FF"

Essentially changing Lu Bu's general ID to a non-existent one.

To keep Xu Shu, change:

0x36C77 to "FF".

Note that you can also change this to some other general ID and if you do, also change 0x36CA4 to that general ID for his little leaving speech. If you don't talk to a new general outside the castle make sure you still trigger [EVENT-7B2D] which kicks in the Zhuge Liang plot part.

Food Usage and Store

Credit: ludmeister, MiDKnighT, sonic penguin

0x39b26, 0x39b2a, 0x39b2e: Food use threshold
0x39b26: e8
0x39b2a: 03
0x39b2e: 00

String them together: 0003e8 (1000)
Every (active) soldier in your army is counted, and that total is divided by this threshold. If the value is less than one, then it becomes one. This is the amount of food your army eats every step on the map. This value is only calculated after a battle. That's why your army doesn't eat after leaving the first village at the start of a game (until you fight a battle).

Editing the display of food/cost in the merchant menu addresses:

Original ROM Size:

3EBD7-3EBE1 = 300- 100
3EBE3-3EBED = 3000-1000
3EBEF-3EBF9 =30000-10000

1MB ROM:

7EBD7-7EBE1 = 300- 100
7EBE3-7EBED = 3000-1000
7EBEF-7EBF9 =30000-10000
FEBD7-FEBE1 = 300- 100
FEBE3-FEBED = 3000-1000
FEBEF-FEBF9 =30000-10000

Keep in mind that the ACTUAL food cost is edited @ addresses:

0x392D7 = 2C B8 30 01 0B 75

That translates to 300 (012C), 3000 (0BB8), and 30000 (7530).

Title Screen

Credit: ludmeister, sonic penguin, and others who have edited the title screen prior

Title Screen text hacking

The title screen, replete with copyright info, produced by yadda yadda yadda lives @ 0x3499f-0x34a4f, like so:

0×34990    —- —- —- —- —- —- —- —- |
0x349a0    1C21 AB0B 1F24 2217 0A0A 2223 1021 23FF    | M~~~PUSH__START|
0x349b0    21E5 172A 0A17 1821 1E22 1718 0A1C 1E23 | ~~~c_HIROSHI_MOT
0x349c0    1E1C 1828 100A 0109 0809 2225 122A 0A1C | OMIYA_1989~~~c_M
0x349d0    0A10 1D13 0A1C 0A12 1E63 0A01 0908 0922 | _AND_M_CO._1989~
0x349e0    650F 2A0A 2217 2414 1822 1710 0A01 0908 | ~~c_SHUEISHA_198
0x349f0    0922 A21D 1F21 1E13 2412 1413 0A11 280A | 9~~~PRODUCED_BY_
0x34a00    1210 1F12 1E1C 0A12 1E63 620A 1B23 1363 | CAPCOM_CO.,_LTD.
0x34a10    7C22 E613 1210 1F12 1E1C 0A24 6322 6310 | /~~~CAPCOM_U.S.A
0x34a20    6362 0A18 1D12 6323 290B 1B18 1214 1D22 | .,_INC.~~~LICENS
0x34a30    1413 0A11 2823 6518 1D18 1D23 141D 131E | ED_BY~~~NINTENDO
0x34a40    0A1E 150A 101C 1421 1812 100A 181D 1263 | OF_AMERICA_INC.

Note that I used the ~ character to render formatting bytes.

This renders into these commands/lines of output (I didn't capitalize every letter, just so I could read it better):

21AB 0B    Push start
21E5 17    c Hiroshi Motomiya 1989
2225 12    c M and M Co. 1989
2265 0F    c Shueisha 1989
22A2 1D    Produced by Capcom Co., Ltd./
22E6 13    Capcom U.S.A., Inc.
2329 0B    Licensed by
2365 18    Nintendo of America Inc.

The first two bytes above (like 21AB) are the values in the PPU table where the next line of text will begin to be stored. Every line on the screen is 0×20 bytes long. These byte pairs aren't exactly an (X, Y) pair… it's not that simple. Suffice it to say that most of you will want to write text on lines beginning with 21a0, 21e0, 2220, 2260, 22a0, 22e0, 2320, and 2360. The third byte (like 17) is much more understandable– it is how long the line is (23 characters).

Once you have your text edited and looking pretty, DoaE begins to tell the story. It wipes the screen… and textual abnormalities happen. Well, there's another little place that tells DoaE how to wipe the screen after it's done showing the copyright info:

This string that determines how the Title Screen is wiped is at 0x1d340 – 0x1d362:

21AB 4B 0A
21E5 57 0AFF
2225 52 0A
2265 4F 0A
22A2 5D 0AFF
22E6 53 0A
2329 4B 0A
2365 58 0AFF

Fairly similar to how the Title Screen text is formatted above. The differences are that the length byte (#3) is OR'ed by 40… presumably used as a "fill" function by the DoaE engine. The fourth byte ends up being the "fill character". In this case, it is "0a", or a space.

You can change the title colors for "Destiny of an Emperor" by modifying values between 3C699-3C69B (7C699-7C69B in 1MB). You will need to refer to the color palette for color choices:

pallettes.jpg

Opening Bios

Credit: MiDKnighT

The portraits for the opening bios are listed from 0x1D4C4-0x1D4D0. These are just a list of general IDs. They are listed in this order:

Liu Bei – A8
Guan Yu – A9
Zhang Fei – AA

Zhang Jao – OC
Dong Zhuo – BB
Lu Bu – C0

Yuan Shao – 26
Yuan Shu – 1B

Zhao Yun – D7
Ma Chao – B0
Huang Zhong – 41

Zhuge Liang – D5
Pang Tong – 9D

Simply change these general IDs to change the portraits displayed. The text is right after this section. To edit it use a hex editor and load the doaetable.tbl from DoaEditor. Then (carefully) edit the text while preserving line breaks. The breaks are usually a function like 20####.

Note that editing this is a major pain :)

Starting Lineup

Credit: MiDKnighT and ludmeister

By default you start with the characters Liu Bei (A8), Guan Yu (A9), and Zhang Fei (AA). This lineup is stored at 0×35558-0x3555A (A9 AA A8). Change these to different general IDs if you want a new starting lineup. Note that in the opening sequence the first character (in hex) will use color palette 1 (Guan Yu), the second character (in hex) will use palette 2 (Zhang Fei), and the third character (in hex) will use palette 0 (Liu Bei).

Starting Equipment:

Liu Bei: 0x3557C
Guan Yu: 0x3556C
Zhang Fei: 0×35574

Add 0x80 to the item ID to pre-equip it. But if you want the weapons pre-equipped your gonna have to add a bit of code to make that happen when the game starts. You can do this with:

0x35447: 4CC0B5EAEA
0x357D0: A90A8DF861A9018DC0608DC160A9028DC260A9148DB4608DB5604C3C94

Not that this code equips daggers (01) and robes (14) to Guan Yu and Zhang Fei and equips the flail (02) to Liu Bei. Any other setup requires different code. You can change this around by playing with the code.

Here's the code from the above changes:

00:97C0:A9 0A LDA #$0A
00:97C2:8D F8 61 STA $61F8 = #$00
00:97C5:A9 01 LDA #$01 <– Dagger
00:97C7:8D C0 60 STA $60C0 = #$00 <– Guan Yu weapon slot
00:97CA:8D C1 60 STA $60C1 = #$00 <– Zhang Fei weapon slot
00:97CD:A9 02 LDA #$02 <– Flail
00:97CF:8D C2 60 STA $60C2 = #$00 <– Liu Bei weapon slot
00:97D2:A9 14 LDA #$14 <– Robe
00:97D4:8D B4 60 STA $60B4 = #$00 <– Guan Yu armor slot
00:97D7:8D B5 60 STA $60B5 = #$00 <– Zhang Fei weapon slot
00:97DA:4C 3C 94 JMP $943C

If you wanted to, you could also add to this code to pre-load other weapons and items into any of the allies' packs (1-7):

$60B4 -> $60BA = Allies AC
$60C0 -> $60C6 = Allies Weapons
$6100 -> $6137 = Allies Items

Note that Guan Yu is general 1, Zhang Fei is general 2, Liu Bei is general 3, the first general you recruit will be general 4, etc…

+++ Changing Music
Credit: sonic penguin, Xhinaeria, and Meteorstrike

To change the music of the game, simply replace the address with the hex values below. For example, the World Map music is located at address 3BF8F and has a value of 27. Change 3BF8F to 20 and the World Map music will play the Menu Theme.

Music Hex ID's
20= Menu Theme
21= New World Theme
22= Intro Theme
23= Battle Theme
24= Field Boss Battle Theme
25= Insanely Hard Boss Battle Theme
26= Castle Boss Battle Theme
27= World Map 1 Theme
28= World Map 2 Theme
29= Village Theme
2A= Fort Theme
2B= Shop Theme
2C= Castle Theme
2D= Ending Theme
2E= Cave
2F= Victory
30= Defeat
31= Inn Jingle
32= Level Up

Changing Overworld Music
Credit: sonic penguin

3BF8F= World Map 1
3BF90= Shop
3BF91= Cave
3BF92= Castle
3BF93= Fort
3BF94= Village
3BF8A= World Map 2
3BF6C= New World (Played everywhere after defeating final boss)

Changing Battle Music
Credit: sonic penguin

Changing Normal Battle Music:
3E1A1 (1MB expanded ROM 7E1A1)

Changing Field Boss Battle Music:
3E198 (1MB expanded ROM 7E198)

Changing Castle Boss Battle Music:
3E192 (1MB expanded ROM 7E192)

Changing Insanely Hard Boss Battle Theme:
3E1A5 (1MB expanded ROM 7E1A5)

Pre-Determined Battle Music
Credit: Xhinaeria and Meteorstrike

For battles:

00EA holds what music should be playing. Check for break when writing to 00EA and log it. Enter battle, recieve this:

0F:C4D3:85 EA STA $00EA = #$27
0F:C4D5:86 EE STX $00EE = #$02
0F:C4D7:A6 E8 LDX $00E8 = #$07
0F:C4D9:95 E0 STA $E0,X @ $00E4 = #$88
0F:C4DB:E8 INX
0F:C4DC:8A TXA
0F:C4DD:29 07 AND #$07

"Write Music 27 (Normal battle) to 00EA" Check logger, I get a couple of COMPARISONS!

$E17F:10 F8 BPL $E179 A:80 X:0A Y:01 S:2C P:nvUbdIzc
$E179:D9 E7 E1 CMP $E1E7,Y @ $E1E8 = #$47 A:80 X:0A Y:01 S:2C P:nvUbdIzc
$E17C:F0 16 BEQ $E194 A:80 X:0A Y:01 S:2C P:nvUbdIzC
$E17E:88 DEY A:80 X:0A Y:01 S:2C P:nvUbdIzC
$E17F:10 F8 BPL $E179 A:80 X:0A Y:00 S:2C P:nvUbdIZC
$E179:D9 E7 E1 CMP $E1E7,Y @ $E1E7 = #$36 A:80 X:0A Y:00 S:2C P:nvUbdIZC
$E17C:F0 16 BEQ $E194 A:80 X:0A Y:00 S:2C P:nvUbdIzC
$E17E:88 DEY A:80 X:0A Y:00 S:2C P:nvUbdIzC
$E17F:10 F8 BPL $E179 A:80 X:0A Y:FF S:2C P:NvUbdIzC
$E181:A9 26 LDA #$26 A:80 X:0A Y:FF S:2C P:NvUbdIzC
$E183:A6 75 LDX $0075 = #$80 A:26 X:0A Y:FF S:2C P:nvUbdIzC
$E185:10 0F BPL $E196 A:26 X:80 Y:FF S:2C P:NvUbdIzC
$E187:A9 24 LDA #$24 A:26 X:80 Y:FF S:2C P:NvUbdIzC
$E189:AE AF 60 LDX $60AF = #$04 A:24 X:80 Y:FF S:2C P:nvUbdIzC
$E18C:E0 08 CPX #$08 A:24 X:04 Y:FF S:2C P:nvUbdIzC
$E18E:B0 06 BCS $E196 A:24 X:04 Y:FF S:2C P:NvUbdIzc
$E190:A9 23 LDA #$23 A:24 X:04 Y:FF S:2C P:NvUbdIzc
$E192:D0 02 BNE $E196 A:23 X:04 Y:FF S:2C P:nvUbdIzc
$E196:20 CF C4 JSR $C4CF A:23 X:04 Y:FF S:2C P:nvUbdIzc
$C4CF:C5 EA CMP $00EA = #$27 A:23 X:04 Y:FF S:2A P:nvUbdIzc
$C4D1:F0 10 BEQ $C4E3

Look at the battle order, counted up from 00 in hex order, battle 36 and 47 are Sun Quan and Sa Ma Yi! There are six other comparisons at FF. Look in ROM for "36, 47, FF, FF, FF, FF, FF, FF" and found it at 0x3E1F7 (1MB ROM: 0x7E1F7 and 0xFE1F7).

So you can have up to 8 battles with "hard boss battle" music. Just enter the battle IDs in 0x3E1F7. (0x7E1F7 and 0xFE1F7 in 1MB expansion)

Smoke Pot Timing

Credit: Xhinaeria

First using the cheat I found that 008A is where the temporary information was stored for how many spaces the smoke pot has left, so using 6502 I noticed it break when calling a value of "40" (64) was being written to. When I highlighted the screen to the left, it noted an offset "0x38C73" noticing that 38C71 was A9, which apparently in 6502 coder means something like "use value" or "replace value with" and a preceeding value was 40 (0x38C72), so I changed it to FF, loaded 'er all up again, and watched the value at 008A go to 255, which is what I wanted.

So for example if you change 0x38C72 to 80 you double the timing of the smoke pot. If you change it to 20 you cut it in half.

Making Wei Generals Not Auto-Recruitable

Credit: MiDKnighT

After Sima Yi kills Cao Pi, a bunch of Wei generals automatically become encounterable and recruitable. The list is at: 0x37FF2:

72 73 74 75 76 77 7A 7B 83 84 85 86 95 96 FF

To prevent these generals' status from changing, just change this all to "FF". Or to shorten the list put the general IDs then FF at the end. The code is:

$E400:9D 00 63 STA $6300,X @ $6395 = #$98 A:90 X:95 Y:0C S:2A P:NvUbdIzc
$E403:C8 INY A:90 X:95 Y:0C S:2A P:NvUbdIzc
$E404:D0 F1 BNE $E3F7 A:90 X:95 Y:0D S:2A P:nvUbdIzc
$E3F7:B1 00 LDA ($00),Y @ $B43F = #$96 A:90 X:95 Y:0D S:2A P:nvUbdIzc
$E3F9:C9 FF CMP #$FF A:96 X:95 Y:0D S:2A P:NvUbdIzc
$E3FB:F0 09 BEQ $E406 A:96 X:95 Y:0D S:2A P:NvUbdIzc
$E3FD:AA TAX A:96 X:95 Y:0D S:2A P:NvUbdIzc
$E3FE:A9 90 LDA #$90 A:96 X:96 Y:0D S:2A P:NvUbdIzc
$E400:9D 00 63 STA $6300,X @ $6396 = #$80 A:90 X:96 Y:0D S:2A P:NvUbdIzc
$E403:C8 INY A:90 X:96 Y:0D S:2A P:NvUbdIzc
$E404:D0 F1 BNE $E3F7 A:90 X:96 Y:0E S:2A P:nvUbdIzc
$E3F7:B1 00 LDA ($00),Y @ $B440 = #$FF A:90 X:96 Y:0E S:2A P:nvUbdIzc
$E3F9:C9 FF CMP #$FF A:FF X:96 Y:0E S:2A P:NvUbdIzc
$E3FB:F0 09 BEQ $E406 A:FF X:96 Y:0E S:2A P:nvUbdIZC
$E406:A6 02 LDX $0002 = #$03 A:FF X:96 Y:0E S:2A P:nvUbdIZC
$E408:A4 03 LDY $0003 = #$01 A:FF X:03 Y:0E S:2A P:nvUbdIzC
$E40A:60 RTS A:FF X:03 Y:01 S:2A P:nvUbdIzC

So once it sees "FF" it stops reading the list.

Weapon, Armor, and Tactic Icons + Text Enhancements

Credit: ludmeister (with tactic icon design ideas from DragonAtma)

Place @ 0x27c10 (0xb0 bytes)
004060703C181606C0E0713A1C0F1727
E0F0FA7A3A043B0340406030391E070B
D0E0609008040201402098FCFEE7713C
70D8B8E87C0E0703384442212162E4C2
002E94E8F4622100804F31324C485060
1048249E5B331F0E42E7FF7E7E5A3C3C
28D6AA546C54AA44DBBD7E66183C5ADB
097AFFDF8D0D18107C027CFE1E7C1E00
3C182442FFFFFF7E031E2F7F7FFFF160
0F304758233C77F13C1E396DD6EE7C38
3E427E4A7E527E00000006FDF9AD0600

@ 0x27cc0:
C0E070381C0E070300007ED0E0C00000
7C82BABABA443800205068542A1A0404
1830BAFA6EE44638000C18387C6E261C
0E1C387E0C1830607C80DE401C280C08
0018187E7E1818006CFEFEFE7C381000
@ 0x27d60:
60909048080402003874E2F6FE7C3800

@ 0x27d70 (replace):
"0814227F083E2A7F" -> "384C9E8A82443800"

@ 0x27da0 (replace):
"00000000000104000000000000020502" -> "10A0CEE60A1020007CFEAAFE7C304000"

@ 0x27db0:
384492928A4438003C4298A492443800
387C547C38003800

@ 0x27e08 (replace):
"08107E2424FF2442" -> "3844A2928A443800"

Here's a rundown of the icons that you will receive.

Weapons and Armor:

40- Dagger
41- Sword
42- Broadsword
43- Curved Sword
44- Spear
45- Large Polearm Head
46- Mace
47- Whip
48- Axe
49- Bow
4a- Claw
4b- Robe
4c- Mail
4d- Armor
4e- Bandana
4f- Helm
50- Potion
51- Horse Head
52- Wing
53- Generic Pouch
54- Letter
55- Key
56- Staff

Here's a screenshot with some of the new enhancements in action:

doae-remix-v3.0-01.png

Tactics:

0×57: Rifle
0×58: Shield
0×59: Herb
0x5a: Fire
0x5b: Water
0x5c: Lightning
0x5d: Cyclone
0x5e: Healing Cross
0x5f: Life Heart
0x6a: Curved Staff
0x6b: White Orb
0x6c: Black Orb (replaced a Chinese character)
0×72: Evasion (replaced a .. symbol)
0×73: Thwart/Silence (replaced a modified dot symbol)
0×74: Haste Clock
0×75: Confuse curly-Q
0×76: Skull
0x7f: Negate (replaced a Chinese character)

And the new icons:

doae-icons.png

To use these icons, just open up a hex editor and use the doetable.tbl file (from DoaEditor) to see the names like this:

tactics.jpg

Then for the first character in each name, plug in the text value. For example if you wanted to call Lian Huo "Fire" you would use the fire icon "5A" in hex (left side) followed by the word "Fire" in ascii (right side).

The palette changes depending on where you are so the text colors can change. To find out which palette it is using open the PPU viewer and you'll see groups of 4 colors. Mouse over each color to see the number then look in the ROM for that pattern of 4 numbers. Then you can change the text color but that may also affect the surroundings in the area you are in. Note that I think the text color is always the 2nd (white) and 4th color in the palette.

Dual Colored Font

Credit: ludmeister
Note: This enhancement requires a 1MB expanded rom.

I have successfully hacked the font loading routines, and set the stage for a 2-bit font-set. Here’s a litany of what I’ve changed. Keep in mind, this requires an expanded font-set in 0×8010-0x880f (0×800 bytes).

0x7c39b: This will make font load 2-bytes-per-character at a time

Code:
“20B9C3 20CEC3″ -> “4C7DC3 EAEAEA”

0x7defb: This pointer originally pointed to Page 09, BA00. Pointing to Page 2, Starting at 8000.

Code:
“00BA” -> “0080″

0x7deed: Page switch to 02, rather than 09.

Code:
“A909 2082C4″ -> “A902 2082C4″

0x7c687: Palette swap for status/army/battle screen. Not sure how much more. Other palettes will likely need tweaking.

Code:
“01200F200F200F200F170F170F372621″ -> “012021110F2011210F220F320F372621″

0x7c3a7: Font data changed slightly when going into status/army/battle screens. This guards against that.

Code:
“38″ -> “60″

For 0×8010-0x880f, go into FCEUX’s PPU with DoaE running, while your party is in the overworld, and copy 0×1000-0x17ff. Paste those bytes directly into the DoaE ROM.

Here’s a screenshot of just enough done of the new font to take care of the numbers:

doae-font-creation-in-progress.png

Dual Colored Font AND Status Screen

Credit: ludmeister
NOTE: Using this requires the above section on Dual Colored font to be implemented prior to adding this code

This palette swap is essential so that you can read the title screen. :smirk:

Code:
0x7c69c: “0F200F0F0F200F0F” -> “0F2021110F202111″

Here is the hex code for the font, to be placed in 0×8010 to 0x880f (0×800 bytes):

Code:
7C0000D6E60000007CC6CE0000C67C00
30000030300000003070300000307800
7C00000C180000007CC606000030FE00
7C00001C060000007CC6060000C67C00
1C00008CFE0000001C2C4C00000C0C00
FE0000FC06000000FEC0C00000C67C00
7C0000FCC60000007CC6C00000C67C00
FE00001830000000FE060C0000303000
7C00007CC60000007CC6C60000C67C00
7C00007E060000007CC6C60000C67C00
00000000000000000000000000000000
38383C3F1F0F4000505456582F304F00
0000FFFFFF00000000FF00FF00000000
000000FFFFFF000000000000FF00FF00
00104410104410000010542828541000
1000BA38382800821010C64400544482
3800006CFE00000038386C0000C6C600
FC0000FCC6000000FCC6C60000C6FC00
7C0000C0C00000007CC6C00000C67C00
FC0000C6C6000000FCC6C60000C6FC00
FE0000FCC0000000FEC0C00000C0FE00
FE0000FCC0000000FEC0C00000C0C000
7C0000C0CE0000007CC6C00000C67C00
C60000FEC6000000C6C6C60000C6C600
30000030300000003030300000303000
06000006C60000000606060000C67C00
CC0000F0F8000000CCD8F00000DCCE00
C00000C0C0000000C0C0C00000C0FE00
C60000D6D6000000C6EEEE0000C6C600
C60000DECE000000C6E6F60000C6C600
7C0000C6C60000007CC6C60000C67C00
FC0000C6FC000000FCC6C60000C0C000
7C0000C6D60000007CC6C600007C0E00
FC0000FCD8000000FCC6C60000CCC600
7C00007C060000007CC6C00000C67C00
FC00003030000000FC30300000303000
C60000C6C6000000C6C6C60000C67C00
C60000C66C000000C6C6C60000381000
C60000D6FE000000C6D6D600006C6C00
C600001038000000C66C3800006CC600
CC00007830000000CCCCCC0000303000
FE00003870000000FE0E1C0000E0FE00
3C0000A1A100003C3C4299000099423C
3C0000A5B900003C3C42B90000A5423C
000000CCCC00000E0000780000CC7C0E
000000706000000000006C0000606000
000000E07800000000007C00001CF800
30000030300000003030FC0000301800
0000000C7C0000000000780000CC7600
C00000CCCC000000C0C0F80000CCF800
000000CCC00000000000780000CC7800
0C0000CCCC0000000C0C7C0000CC7C00
000000CCFC0000000000780000C07C00
18000030FC0000001834300000303000
000000CCCC0000780000780000788C78
C00000D8EC000000C0C0C00000CCCC00
00000000300000000000300000301800
00000000180000300000180000185830
600000787000000060606C0000786C00
30000030300000003030300000301800
000000B6B60000000000EC0000B6B600
000000CCCC0000000000F80000CCCC00
000000CCCC0000000000780000CC7800
000000CCCC0000C00000F80000F8C0C0
004040402C1816060000203010000002
C0A0512B160C1A30004020110A060D13
0060703E121E1E00E0908A442C1A2503
004020301D0F060D4000402024110106
107050F81C0E0703C0D03068140A0502
2070B09884C2613C605028647A251201
883030089C0E07022040C878340A0503
3866422123224682002A00420240A240
001CB89CCE67230000322C743A050200
00403A322A003800C08F182060464440
00082418540C01021040008E1B331F0E
00427E7E7E00242442A58100245A3C3C
44AA54287C2844006CFEFE7C007CEE44
42993C1818187E189924427E002424DB
01285A8D8D0C10100952A55200050800
0000387C3C381C007C06448222440200
3C182452A1A1817E000000105E5E7E00
01021F3F3F7F6100021C28404080D060
000082C468300000008244AA44281000
180C106D566C7C102412290180820028
1E267E5A7E5A7C002064001000080200
000002FFAD27020000000402548A0400
804020100804020140A05028140A0502
00003C70E0C00000000042A000400000
FE828282EE6C38008200383854280000
0028542814240C0420586C542A3A0800
10202A8050983A001830BAFA6EE44638
0008000440000000000C183C7C6E261C
0408387E0C1020400A14204204081020
BA80582008100008C680642014100808
3030F0FE1E1818002828EE00EE282800
287CFE7CFE3800004492008282001000
66000000000000006666880000000000
18000000000000001818200000000000
00000000000000200000000000181820
00000000000000000000000000181800
000000CCCC0000000000CC0000DC6C00
000000C66C0000000000C600006C3800
000000D6D60000000000D60000EE4400
00000078300000000000CC000078CC00
000000663E00003C000066000006463C
00000018300000000000FC000060FC00
60F0D048080402000060480004000402
385CBEBE9A4438003864C2C2E67C3800
384C968A82443800384C9E8A82443800
00400F1F3F3C3838004F302F58565450
0002F0F8FC3C1C1C00F20CF41A6A2A0A
1C1C3CFCF8F002000A2A6A1AF40CF200
5028349A3428500030188CC68C183000
0010826CBA54281000381082C66C3810
38F0EEEE1E3810002850200814283000
FEFEAAFEFE1800008200000082284000
386CC682C66C3800002854104C280000
3C66D8ACD66C38000024400844280000
7C7C5438383838004400004400380000
00000040400000000078400000000000
00000000180000000000000000000000
000000007E0000000000000000000000
1800001818000018183C3C0000001818
3C00001C180000183C66060000001818
00000008100000000002040000204000
38383838383838385050505050505050
1C1C1C1C1C1C1C1C0A0A0A0A0A0A0A0A
386CF6BADE6C38000028542854280000

That was a bit of work, but was well worth it. Looks great! Perhaps this might inspire others to play with the palettes some more…

doae-font-demo.png

What address is the ppu editable for the blue/white mixture?

If you bring up the PPU Viewer in FCEUX, you’ll see the palettes at the bottom of the window. Those correspond to PPU Memory addresses 0x3f00-3f1f.

You can find the Status/Army/Battle screen palettes in the DoaE ROM at 0x7c687-0x7c696.

Status Screen Borders

Credit: ludmeister

Each font character is 8×8, and so each is 8 bytes in size. Row 1 is first bit, Row 2 is second, etc.

So, a DoaE 1 "zero" looks like this:

Code:
-* **– 7c
**– -
- c6
– -- c6
– -- c6
– -- c6
– -- c6
-*** **– 7c
—- —- 00
This is found @ 0x27a10, where the first character in the font set is stored in the ROM (zero is char ID #00).

Here's where the box borders are:

Bottom-Left: 0b (0x27a68)
Top: 0c (0x27a70)
Bottom: 0d (0x27a78)
Top-Left: 6d (0x27d78)
Top-Right: 6e (0x2d80)
Bottom-Right: 6f (0x27d88)
Left: 7d (0x27df8)
Right: 7e (0x27e08)

I suggest firing up a graphics program (Paint will work fine), create an 8×8 bitmap. Magnify it so you can see all the pixels, and start playing around to see what looks good. When you like it, hex-edit the character, using the graphic you created.

Additional Reading

Here are some links that I have found very helpful for DoaE ROM Hacking:

About DoaE ROM Hacking:

History Links:

NES Rom Hacking Info:

Assembly Info (these will be tough if you aren't familiar with assembly):

Advanced ROM Debugging

Credit: MiDKnighT and Meteorstrike

Need to figure out something that nobody has figured out yet? Ready to contribute some major information to the DoaE ROM hacking effort? You'll need to read up on 6502 assembly and use a debugger!

I recommend FCE Ultra. Tools that can be used:

  • Debug –> Hex Editor –> View –> NES Memory
  • Debug –> Hex Editor –> View –> ROM File
  • Debug –> Debugger
  • Debug –> Trace Logger
  • Tools –> Memory Watch

When you are tracing or debugging, you'll usually see the memory address of the ROM page ($8000-$BFFF) if it's being loaded into memory. You'll have to figure out which ROM page it's loading from (ya…sorry).

Mainly the whole approach to debugging is that some value happens (like damage, or some portrait ID that's being loaded, or how long the smoke pot lasts, or whatever). Typically the important value we speak of is stored near the top of the memory stack in the zero page. Usually somewhere in values $0000 to $00FF. You can watch these areas of memory either with "Debug –> Hex Editor –> View –> NES Memory" or "Tools –> Memory Watch". If you can get lucky enough to see the value you're looking for right away, good for you. Then you'll have to test it by switching that value around (if possible). Does it change the behavior? You may need a debugger, the trace logger, or some other option if it is difficult to find your value in memory. Once you find the value in memory and confirm it's the right one, then you have to find out how that value got there. That's where the assembly fun kicks in. Ideally you can use the debugger to trap where the value gets set. You can do this by setting a break point. Add the break point to say…watch $0015 to see when it gets set to "01".

breakpoint1.jpgbreakpoint2.jpg

Add $0015 in both address fields, click the "write" button, then in the condition field say "$0015 == #01". Then hit run. Now do whatever needs to be done in the game and the debugger should stop the game once that condition is met in the debugger. Now you can try to back track in the debugger to see how the value got set or to get everything you might need the Trace Logger. Here's what the output of trace logger looks like:

FCEUX 2.0.0 – Trace Log File
$C1A2:85 11 STA $0011 = #$40 A:05 X:80 Y:00 P:nvUbdIzc
$C1A4:A5 13 LDA $0013 = #$00 A:05 X:80 Y:00 P:nvUbdIzc
$C1A6:85 12 STA $0012 = #$05 A:00 X:80 Y:00 P:nvUbdIZc
$C1A8:68 PLA A:00 X:80 Y:00 P:nvUbdIZc
$C1A9:A8 TAY A:0C X:80 Y:00 P:nvUbdIzc
$C1AA:68 PLA A:0C X:80 Y:0C P:nvUbdIzc
$C1AB:85 16 STA $0016 = #$00 A:E8 X:80 Y:0C P:NvUbdIzc
$C1AD:60 RTS A:E8 X:80 Y:0C P:NvUbdIzc
$CFE9:A5 F1 LDA $00F1 = #$02 A:E8 X:80 Y:0C P:NvUbdIzc
$CFEB:20 82 C4 JSR $C482 A:02 X:80 Y:0C P:nvUbdIzc
$C482:85 44 STA $0044 = #$0C A:02 X:80 Y:0C P:nvUbdIzc
$C484:85 ED STA $00ED = #$0C A:02 X:80 Y:0C P:nvUbdIzc
$C486:A9 01 LDA #$01 A:02 X:80 Y:0C P:nvUbdIzc
$C488:85 EB STA $00EB = #$00 A:01 X:80 Y:0C P:nvUbdIzc
$C48A:A5 ED LDA $00ED = #$02 A:01 X:80 Y:0C P:nvUbdIzc
$C48C:20 B7 C4 JSR $C4B7 A:02 X:80 Y:0C P:nvUbdIzc
$C4B7:8D F9 FF STA $FFF9 = #$AC A:02 X:80 Y:0C P:nvUbdIzc
$C4BA:4A LSR A:02 X:80 Y:0C P:nvUbdIzc
$C4BB:8D F9 FF STA $FFF9 = #$AC A:01 X:80 Y:0C P:nvUbdIzc
$C4BE:4A LSR A:01 X:80 Y:0C P:nvUbdIzc
$C4BF:8D F9 FF STA $FFF9 = #$AC A:00 X:80 Y:0C P:nvUbdIZC
$C4C2:4A LSR A:00 X:80 Y:0C P:nvUbdIZC
$C4C3:8D F9 FF STA $FFF9 = #$AC A:00 X:80 Y:0C P:nvUbdIZc

You'll need to read up on the assembly links in the "ADDITIONAL READING" section to understand what it's doing. I won't go into that here. Note that you can't really run the Trace Logger for more than a few seconds or you will end up with megabytes and megabytes of trace.

ROM Type:

DoaE ROM type: 256k PRG / 0k CHR MMC1 (MMC1B2) –> http://en.wikipedia.org/wiki/Memory_Management_Controller#MMC1
http://nesdev.parodius.com/mmc1.txt
http://wiki.nesdev.com/w/index.php/Nintendo_MMC1

Original ROM:

PRG ROM: 16 x 16KiB
CHR ROM: 0 x 8KiB
ROM CRC32: 0xa558fb52
ROM MD5: 0x516136715d9e29e889f3c9d7c7d12a42
Mapper: 1
Mirroring: Vertical
Battery-backed.

Expanded ROM:

PRG ROM: 64 x 16KiB
CHR ROM: 0 x 8KiB
Mapper: 245

ROM Map

*** Current ROM page is loaded into $8000-$BFFF in memory at any given time.

*** Page 0F is always loaded in $C000-$FFFF in memory

*** In the 1MB ROM Page 1F or 3F is loaded in $C000-$FFFF in memory

Additional map data can be found at:

http://wildplants.es.land.to/text/tenchi1_RomMap.txt (translate from Japanese)


Page 00 – Starting Address: 0×10

0×00000-0x0008F: Header
0×00090-0x0408F: Sprites


Page 01 – Starting Address: 0×4010

0×04010-0x05A0F: Japanese Text Graphics (A.I., Duel, etc.. enhancements replace this)
0x05A10-0x0808F: Sprites


Page 02 – Starting Address: 0×8010

0×08010-0×08800: Japanese Text Graphics (A.I., Duel, etc.. enhancements)
0×08810-0x0B80F: Portrait bank 1
0x0B810-0x0C80F: "Destiny of an Emperor" Title Graphic


Page 03 – Starting Address: 0xC010

0x0C010-0x0C80F: Peach Garden Graphic Part 1
0x0C810-0x0F80F: Portrait bank 2
0x0F810-0x0FA2F: Peach Garden Graphic Part 2


Page 04 – Starting Address: 0×10010

0×10010-0x139EF: Game Graphics


Page 05 – Starting Address: 0×14010

0×14010-0x1800F: Map Data


Page 06 – Starting Address: 0×18010

0×18010-0x1C00F: Map Data


Page 07 – Starting Address: 0x1C010

0x1C010-0x1C20F: Address of the event data movement 1C010-1C20F map
0x1C370-0×1####: Warps
0x1D410-0×1####: Ending sequence
0x1D4D4-0x1DC55: Intro Sequence Text
0x1DF57-0x1E18#: Ending Credits


Page 08 – Starting Address: 0×20010

0×20010-0x2400F: NSF Sound data


Page 09 – Starting Address: 0×24010

0×24010-0x2480F: Map Chip Data
0×26710-0x2770F: Map Coordinates
0x27A10-0x27FBF: Number and Letter Graphics


Page 0A – Starting Address: 0×28010

0×28400-0x2BF1F: Text Bank 1


Page 0B – Starting Address: 0x2C010

0x2C390-0x2F1CF: Text Bank 2
0x2FAF0-0x2FD3B: Item Names
0x2FE4F-0x2FF45: Tactic Names


Page 0C – Starting Address: 0×30010

0×30010-0x3080F: Map Data
0×30910-0x309E6: Treasure Chests
0x309E7-0x30A0F: Unused space?
0x30A10-0x30B23: Hidden item locations
0x30C10-0x30D6F: Battle Locations
0x30D70-0x30EFF: Officer Battle Lineups
0x30F00-0x30FFF: Unused space?
0×31010-0×31###: Villager Attributes
0x31D10-0x322F8: Keywords 1
0x323D0-0x3270F: Name and prices
0×32810-0x33E07: Officer Definitions (STR, INT, Name, etc…)
0x33EE0-0x33FDF: Enemy Soldier Counts


Page 0D – Starting Address: 0×34010

0x3556C-0x3555A: Starting Equipment + Lineup
0×35722-0×35741: Officer Initial Statuses
0×37910-0x37DF1: Keywords 2
0x37E02-0x37EE5: Chapter Locations


Page 0E – Starting Address: 0×38010

0×38609-0x3861C: Displayed Weapon Strength Table
0x38E04-0x38E33: Gullwing Locations
0x38FE9-0×39068: Store Items for Sale
0×39069-0x390B8: Address of shops
0x39A28-0x39A2f: Experience Awarded Per Chapter Multipliers
0x39AD7-0x39AE6: Gold Awarded Per Chapter Multipliers
0x39CEB-0x39CFB: Ambush Battle Locations
0x3ADF8-0x3AE13: Soldier Bar Attributes
0x3AF21-0x3AFC8: Opening Battle Taunt Pointers
0x3B0A3-0x3B14A: Closing Battle Taunt Pointers
0x3B153-0x3B172: Officer Recruitability Table
0x3B51B-0x3B533: 5 Tiger Soldier Progressions
0x3B880-0x3BC31: Tactic Attributes


Page 0F – Starting Address: 0x3C010 (this page is different in the 1MB ROM, see the Exanded ROM section)

0x3C610-0x3C61F: Sprite Colors
0x3C665-0x3C66F: Town Colors
0x3D10E-0x3D116: Portrait Background Colors
0x3E41B-0x3E4CA: Random Enemy Attributes
0x3E710-0x3E737: Weapon Damage Table
0x3E9##-0x3E###: Menu, Status Screens, etc…
0x3FC90-0x3FDE2: Town Names
0x3FFB0-0x3FFF#: Game Graphics

Expanded ROM (1MB):


Page 0F – Starting Address: 0x3C010

Text banks 0A and 0B


Page 10 – Starting Address: 0×40010

Portrait Bank F1


Page 11 – Starting Address: 0×44010

Portrait Bank F1


Page 12 – Starting Address: 0×48010

Portrait Bank F3


Page 13 – Starting Address: 0x4C010

Portrait Bank F3


Page 14 – Starting Address: 0×50010

Portrait Bank F5


Page 15 – Starting Address: 0×54010

Portrait Bank F5


Page 16 – Starting Address: 0×58010

Portrait Bank F7


Page 17 – Starting Address: 0x5C010

Portrait Bank F7


Page 18 – Starting Address: 0×60010

Portrait Bank F9


Page 19 – Starting Address: 0×64010

Portrait Bank F9


Page 1A – Starting Address: 0×68010

Portrait Bank FB


Page 1B – Starting Address: 0x6C010

Portrait Bank FB


Page 1C – Starting Address: 0×70010

Sprites


Page 1D – Starting Address: 0×74010

Sprites


Page 1E – Starting Address: 0×78010

Custom Code for ROM Enhancements


Page 1F – Starting Address: 0x7C010 (System Page)

0x7C610-0x7C61F: Sprite Colors
0x7C665-0x7C66F: Town Colors
0x7D10E-0x7D116: Portrait Background Colors
0x7E41B-0x7E4CA: Random Enemy Attributes
0x7E710-0x7E737: Weapon Damage Table
0x7E9##-0x7E###: Menu, Status Screens, etc…
0x7FC90-0x7FDE2: Town Names
0x7FFB0-0x7FFF#: Game Graphics


Page 20- Starting Address: 0×80010

0×80010-0×80??: New page switch code for 1MB ROM


Page 21- Starting Address: 0×84010

Empty


Page 22- Starting Address: 0×88010

Empty


Page 23- Starting Address: 0x8C010

Empty


Page 24- Starting Address: 0×90010

Empty


Page 25- Starting Address: 0×94010

Empty


Page 26- Starting Address: 0×98010

Empty


Page 27- Starting Address: 0x9C010

Empty


Page 28- Starting Address: 0xA0010

Empty


Page 29- Starting Address: 0xA4010

Empty


Page 2A- Starting Address: 0xA8010

Empty


Page 2B- Starting Address: 0xAC010

Empty


Page 2C- Starting Address: 0xB0010

Empty


Page 2D- Starting Address: 0xB4010

Empty


Page 2E- Starting Address: 0xB8010

Sprite Page 3


Page 2F- Starting Address: 0xBC010

Empty


Page 30- Starting Address: 0xC0010

Empty


Page 31- Starting Address: 0xC4010

Empty


Page 32- Starting Address: 0xC8010

Empty


Page 33- Starting Address: 0xCC010

Empty


Page 34- Starting Address: 0xD0010

Empty


Page 35- Starting Address: 0xD4010

Empty


Page 36- Starting Address: 0xD8010

Empty


Page 37- Starting Address: 0xDC010

Empty


Page 38- Starting Address: 0xE0010

Empty


Page 39- Starting Address: 0xE4010

Empty


Page 3A- Starting Address: 0xE8010

Tactic Expansion Code


Page 3B- Starting Address: 0xEC010

New Tactics


Page 3C- Starting Address: 0xF0010

New Tactic A.I.


Page 3D- Starting Address: 0xF4010

Empty


Page 3E- Starting Address: 0xF8010

Code Enhancements


Page 3F- Starting Address: 0xFC010

Copy of System Page 1F:

0xFC610-0xFC61F: Sprite Colors
0xFC665-0xFC66F: Town Colors
0xFD10E-0xFD116: Portrait Background Colors
0xFE41B-0xFE4CA: Random Enemy Attributes
0xFE710-0xFE737: Weapon Damage Table
0xFE9##-0xFE###: Menu, Status Screens, etc…
0xFFC90-0xFFDE2: Town Names
0xFFFB0-0xFFFF#: Game Graphics


Important Memory Locations

Additional memory data can be found at:

http://wildplants.es.land.to/text/tenchi1_Mem.txt (translate from Japanese)

  • $0060-$0063: Location coordinates
  • $6010 = Current rank
  • $6011 = Hierarchy of the map
  • $6013 = Location ID
  • $6030-#### = Billeting
  • $6070 -> $6072 = Experience
  • $6073 = Party Level
  • $6076 -> $6078 = Money
  • $6079 -> $6081 = Food
  • $6090 -> $6096 = Allies Party Formation (Values = Party Member Indices)
  • $6097 -> $609B = Allies Party Formation 2 (Values = Party Member Indices)
  • $609C -> $60A2 = Allies Flags (Alive Status + Others)
  • $60A3 -> $60A7 = Enemies Flags (Alive Status + Others)
  • $60A8 -> $60AE = Allies General IDs (Addresses = Party Member Indices)
  • $60AF -> $60B3 = Enemies General IDs (Addresses = Party Member Indices)
  • $60B4 -> $60BA = Allies AC
  • $60BB -> $60BF = Enemies AC
  • $60C0 -> $60C6 = Allies Weapons
  • $60C7 -> $60CB = Enemies Weapons
  • $60CC -> $60CF = ???
  • $60D0 -> $60EB = Allies HP
  • $60EC -> $60FF = Enemies HP
  • $6100 -> $6137 = Allies Items
  • $6138 -> $615F = ???
  • $6160 -> $617B = Allies Max HP
  • $617C -> $618F = Enemies Max HP
  • $6190 -> $619B = ???
  • $619C -> $61A2 = Allies STR
  • $61A3 -> $61A7 = Enemies STR
  • $61A8 -> $61AE = Allies INT
  • $61AF -> $61B3 = Enemies INT
  • $61B4 -> $61BA = Allies AGI
  • $61BB -> $61BF = Enemies AGI
  • $61D0 -> $61D4 = Are we going to defend? (02 = defend)
  • $61E4 -> $61ED = Target (who am I attacking?)
  • $61F8 -> $61F9 = Tactic Points – Max
  • $61FB -> $61FC = Tactic Points – Current
  • $61FE -> $61FF = Tactic Points – Used
  • $6200 -> $6204 = Allies what are we going to do? (00 = attack or tactic ID)
  • $6205 -> $6209 = Enemy what are they going to do? (00 = attack or tactic ID)
  • $6220 = Are we near water? (01 = near water)
  • $6222 -> $622F = Status tactics currently in use
  • $6300 -> $63FF = Officer flags
  • $6400 -> $6406 = Allies LDR (enhancement)
  • $6407 -> $640B = Enemies LDR (enhancement)
  • $6410 -> $6416 = Allies VIT (enhancement)
  • $6417 -> $641B = Enemies VIT (enhancement)
  • $6420 -> $6426 = Allies POL (enhancement)
  • $6427 -> $642B = Enemies POL (enhancement)
  • $65A0 -> $65C9 = Allies Available Tactics
  • $65CA -> $65E7 = Enemies Available Tactics
  • $65E8 -> $65FF = ???
  • $6600 -> $667F = Treasure chests opened
  • $6680 -> $66BF = Items found on the ground
  • $7F90 -> $7FBF = Page switching code for 1MB ROM

From Meteorstrike's Item Disappearing FAQ:

  • $60A8 -> $60AE = Allies General IDs (Addresses = Party Member Indices)

These memory locations represent which Generals are in the player's party. For example, if $60A8 contains 0x9D, then that means that the General at Party Member Index 0 ($60A8) is Pang Tong (0x9D).

  • $60AF -> $60B3 = Enemies General IDs (Addresses = Party Member Indices) Much in the same way as it is done with the player's party, these memory locations store the General IDs that compose the Enemy's Party. Note that these are stored immediately after the player's party. This means that a Party Member Index of 7 is a valid Party Member Index, in the sense that it will indicate the first Party Member in the Enemy's Party.
  • $6090 -> $6096 = Allies Party Formation (Values = Party Member Indices) These represent the party formation. The value at $6090 indicates which General is in the lead on the party formation. The value at $6096 indicates which General is 7th in the party formation. The values stored in these memory addresses are the Party Member Indices. For example, if $6090 contains 0×03, that means that the first member in the party formation ($6090) is whatever General happens to be in Party Member Index 3 ($60A8 + 03 = $60AB). This indirection can be somewhat confusing at times. The values here are indices into another array, namely ($60A8 -> $60AE), and NOT the actual General IDs. Hopefully, the difference between Party Member Index and Party Formation Index is better understood now. The Party Member Index is an index into ($60A8 -> $60AE), and the Party Formation Index is an index into ($6090 -> $6096), which itself contains the indices into ($60A8 -> $60AE).
  • $6097 -> $609B = Allies Party Formation 2 (Values = Party Member Indices) This is identical to the above, except that this array is used whenever we are in battle. If, for example, the player's first 2 Generals were killed, and the player has a full party of 7 Generals, then the Party Members in battle will include the Party Members at the end of the party formation. Using this second, temporary array in battle simply makes calculations easier.

Regarding status tactics:

Enemy statuses:

  • $6222 = #$00 <– Cheng Nei, Ji Rou/Guard, Wuo Jian, or Shui Jian on?
  • $6224 = #$00 <– Ce Mian on?
  • $6226 = #$00 <– Ji Main on?
  • $6228 = #$00 <– Yi Xin on?
  • $622A = #$00 <– Li Jian on?
  • $622C = #$00 <– Qi Shou on?
  • $622E = #$00 <– Bei Ji on?

Ally statuses (basically one after each enemy status):

  • $6223 = #$00 <– Cheng Nei, Ji Rou/Guard, Wuo Jian, or Shui Jian on?
  • $6225 = #$00 <– Ce Mian on?
  • $6227 = #$00 <– Ji Mian on?
  • $6229 = #$00 <– Yi Xin on?
  • $622B = #$00 <– Li Jian on?
  • $622D = #$00 <– Qi Shou on?
  • $622F = #$00 <– Bei Ji on?

The value stored decides which allies/enemies it is turned on for. For the case of $6222 and $6223 the value determines which tactic is in use (Cheng Nei, Ji Rou, Wuo Jian, or Shui Jian):

Ji Rou: 01
Douse: 02
Levee: 04
Cheng Nei: 08

Another interesting piece is that if the enemy successfully uses Jie Ce/Negate it zeroes out all the ally statuses and if an ally successfully uses Jie Ce/Negate it zeroes out all the enemy statuses.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License