+  RHDN Forum Archive
|-+  Romhacking
| |-+  ROM Hacking Discussion
| | |-+  [NES] The Legend of Zelda (Italian)
Pages: [1] 2
Author Topic: [NES] The Legend of Zelda (Italian)  (Read 1 times)
MattDragon
Guest
« on: April 13, 2011, 09:08:23 am »

Hi guys, I'm translating The legend of Zelda in Italian and I need a hand with some problems.
The biggest one is: i want to change the colour of the text on the screen after the press start (Many years ago...), but i can't find how! Can someone help me with this? Thx a lot! Grin
Trax
Guest
« Reply #1 on: April 15, 2011, 02:32:38 am »

The data for the palette mappings of the intro text in Zelda 1 is located in the range: 1A81B - 1A85D.
Each byte codes for a block of 4x4 tiles, 2 bits for each of its four 2x2 blocks.
MattDragon
Guest
« Reply #2 on: April 15, 2011, 09:35:51 am »

YOU ARE GREAT!!!! YOU ARE MY SAVIOR!!! Thx a lot!!!
snarfblam
Guest
« Reply #3 on: April 15, 2011, 05:18:14 pm »

For future reference:
http://datacrystal.romhacking.net/wiki/Legend_of_Zelda:ROM_map

Relevant info is toward the end in this case.
MattDragon
Guest
« Reply #4 on: April 16, 2011, 04:20:51 am »

Ok guys you are really great! I have the last 2 questions:

1- I wanted to change the word "MAP" (1A395 - 1A397) that appear on the dungeon menu with the word "MAPPA" (in italian), but i have only 3 bytes and I need 5. How can I do?
2 - I have the same problem with the word "LEVEL-#" (19D17 - 19D1D) that I want to change with "LIVELLO-#" (I need 2 more bytes)

I tried to move all the following bytes but the result wasn't good. Can someone give me a hand? Thx a lot guys, you're awesome!
snarfblam
Guest
« Reply #5 on: April 18, 2011, 05:41:24 pm »

This text is stored in "PPU macros". These are used not just for text, but for all kinds of graphic layout data and palette data. The format of these PPU macros is pretty similar among many different games.

For example, the data for "MAP" actually starts at 1A392, and is part of a larger piece of data.

1A380: 70 4B 6A 2A 7B 01 6D FF 2B 43 07 0C 18 16 19 0A
1A390: 1C 1C 2A A5 03 16 0A 19 2A 8C 10 F5 F5 FD F5 F5
1A3A0: FD F5 F5 FD F5 F5 F5 FD F5 F5 F5 FF
2B AC 10 F5


I've highlighted the "MAP" data in red. The 2A A5 specifies where the data will be written in graphic memory (which determines where it ends up on screen). The 03 specifies the length of the macro data. Finally, the 03 16 0A is the actual tile data that spells out "MAP".

Zelda uses "strings" of PPU macros. This is just a list of PPU macros that are stored together and used at the same time. I've highlighted the macro string that contains the "MAP" macro, in blue. The string is terminated with an FF byte (in bold).

I'm guessing that the easiest way to increase the length of the text is to:
  • Find some free space, big enough to contain the PPU macro string, plus some extra bytes
  • Find the pointer to the PPU macro string (The PPU macro string starts at 0x1A388. I would expect the pointer to have a value of $A378, so you want to search for 78 A3.)
  • Move and modify the PPU macro string.
  • Update the pointer to said string.
« Last Edit: April 18, 2011, 08:14:06 pm by snarfblam »
Trax
Guest
« Reply #6 on: April 18, 2011, 07:13:04 pm »

I've searched the area too, and it seems the PPU chunks are grouped, just like Snarfblam said. The pointer to "COMPASS", "MAP" and the top of yellow map tile mappings is located at 1A050. And there is a considerable amount of unused space starting at 1ACD9, so there's more than enough latitude for changes in string lengths. The following modifications seem to work correctly, at least for the map and compass labels:
At 1A050:
E0 AC

At 1ACF0:
2B 43 07 0B 1E 1C 1C 18 15 0A 2A A4 05 16 0A 19
19 0A 2A 8C 10 F5 F5 FD F5 F5 FD F5 F5 FD F5 F5
F5 FD F5 F5 F5 FF 2B AC 10 F5 FE F5 F5 F5 FE F5
F5 F5 F5 FE F5 F5 F5 FE F5 FF
As for the level label, it's located at 19D14, and it can be easily replaced with:
20 41 07 15 12 1F 0E 15 15 18 FF 
But the level number is still displayed at the same location, which overwrites the "O". If you can find the bytes that define the level number location, you could add 2 to it and that would settle the matter. I presume it's hardcoded somewhere else. If someone knows the RAM address for the current level, that would help the search...
snarfblam
Guest
« Reply #7 on: April 18, 2011, 08:39:43 pm »

Here we go :D

05:B02A:AD B1 6B   LDA $6BB1  ; Load level number
05:B02D:F0 EB      BEQ $B01A
05:B02F:8D 25 68   STA $6825  ; Patch into PPU data

The game takes the current level number and patches it into a PPU macro.

Add or subtract from the value at 0x17040 in the ROM to move the level number digit left or right. (This is the number shown in red above.) As long as it falls within the PPU data you're good.
MattDragon
Guest
« Reply #8 on: April 19, 2011, 02:17:33 pm »

Quote from: Trax on April 18, 2011, 07:13:04 pm
I've searched the area too, and it seems the PPU chunks are grouped, just like Snarfblam said. The pointer to "COMPASS", "MAP" and the top of yellow map tile mappings is located at 1A050. And there is a considerable amount of unused space starting at 1ACD9, so there's more than enough latitude for changes in string lengths. The following modifications seem to work correctly, at least for the map and compass labels:
At 1A050:
E0 AC

At 1ACF0:
2B 43 07 0B 1E 1C 1C 18 15 0A 2A A4 05 16 0A 19
19 0A 2A 8C 10 F5 F5 FD F5 F5 FD F5 F5 FD F5 F5
F5 FD F5 F5 F5 FF 2B AC 10 F5 FE F5 F5 F5 FE F5
F5 F5 F5 FE F5 F5 F5 FE F5 FF
As for the level label, it's located at 19D14, and it can be easily replaced with:
20 41 07 15 12 1F 0E 15 15 18 FF 
But the level number is still displayed at the same location, which overwrites the "O". If you can find the bytes that define the level number location, you could add 2 to it and that would settle the matter. I presume it's hardcoded somewhere else. If someone knows the RAM address for the current level, that would help the search...

It's perfect, i tried and all work fine! Thx a lot!

Quote from: snarfblam on April 18, 2011, 08:39:43 pm
Here we go Cheesy

05:B02A:AD B1 6B   LDA $6BB1  ; Load level number
05:B02D:F0 EB      BEQ $B01A
05:B02F:8D 25 68   STA $6825  ; Patch into PPU data

The game takes the current level number and patches it into a PPU macro.

Add or subtract from the value at 0x17040 in the ROM to move the level number digit left or right. (This is the number shown in red above.) As long as it falls within the PPU data you're good.

I tried with the 20 41 09 15 12 1F 0E 15 15 18 FF string, but I need to write "LIVELLO " (with a space between "O" and the level number). How could i do?
« Last Edit: April 19, 2011, 02:59:48 pm by MattDragon »
snarfblam
Guest
« Reply #9 on: April 19, 2011, 04:45:12 pm »

This is the important bit. I probably should have put more emphasis on it.

Quote from: snarfblam on April 18, 2011, 08:39:43 pm
As long as it falls within the PPU data you're good.


Your problem is that you need a dummy tile in the PPU data. The game inserts the level number into the ppu macro. If you move the level number to the right two tiles, this is where the level number will be inserted:

20 41 07 15 12 1F 0E 15 15 18 FF **
----- -- L  O  V  E  L  L  O     #

The game is writing the level number beyond the end of the PPU data. With 20 41 07 15 12 1F 0E 15 15 18 FF, you don't give the game anywhere to write the level number. You need two more tiles: the space, and a dummy byte that will be replaced with the level number. In other words:
20 41 07 15 12 1F 0E 15 15 18 24 01 FF
----- -- L  O  V  E  L  L  O  _  1
.
MattDragon
Guest
« Reply #10 on: April 20, 2011, 03:16:41 am »

I understood, but the problem is: how can i add 2 bytes there?
snarfblam
Guest
« Reply #11 on: April 20, 2011, 08:42:18 pm »

The simple answer is you can't.

The data is copied to RAM and later read from there. It needs to be stored in RAM because it will need to be modified to update the level number in the PPU macro.

This makes things more difficult, because not only do you need to relocate the data to free space in the ROM, but you also need to load the data into free RAM, and then you need ASM to load the new data from ROM to RAM. (You can't just re-point this one piece of data because the old data is part of a larger chunk that's all loaded at once.)

You can use this code to load the new PPU data into RAM. The new data is included in the code.
Code:
; Data
destStart = $7F00
dataSize = endOfPpuData - ppuData
destEnd = destStart + dataSize

; Labels
HijackReturn = $809F
CopyBytes = $80D7

.org $BE00 ;0x1be10
   
DisplacedCode:
      ; We need to run the code that our hijack displaced
      JSR $80C6 ; LoadSomePointers
      JSR $80D7 ; CopyBytes

SetUpCopyPointers:
      ; Source address
      LDA #<ppuData
      STA $00
      LDA #>ppuData
      STA $01
   
      ; Dest addresses
      LDA #<destStart
      STA $02
      LDA #>destStart
      STA $03
   
      LDA #<destEnd
      STA $04
      LDA #>destEnd
      STA $05
     
CopyAndReturn:
      JSR CopyBytes
      JMP HijackReturn
   

ppuData:
      .db $20, $42 ,$09, $15, $12, $1F, $0E, $15, $15, $18, $62, $00, $FF
      ;   PPU dest, len, L    I    V    E    L    L    O   space  -  end
endOfPpuData:

This is the code in assembled form, which you can copy to 0x1BE10 in the ROM.

20 C6 80 20 D7 80 A9 24 85 00 A9 BE 85 01 A9 00
85 02 A9 7F 85 03 A9 0D 85 04 A9 7F 85 05 20 D7
80 4C 9F 80 20 41 09 15 12 1F 0E 15 15 18 30 62
FF


We need a hijack to run the above code.
Code:
JMP $BE00
In assembled form (copy to 0x180A9):
4C 00 BE

Finally, we need to update two pointers. The first pointer tells the game where to load the PPU macro from to write "LEVEL" on the screen. We change this to $7F00 (write 00 7F to 0x1A01C). The other pointer tells the game which byte in the PPU macro to update with the level number. We change this to $7F0B (write 0B 7F to 0x17040).


It seems rather elaborate for such a simple change, but it's the best I could come up with. Be aware that I'm not positive that the RAM at $7F00 is unused, but it appears to be.
« Last Edit: April 20, 2011, 08:52:42 pm by snarfblam »
Trax
Guest
« Reply #12 on: April 21, 2011, 02:16:20 pm »

But Snarf, where in ROM is the chunk of data that is transfered into RAM in the first place?
The location (PPU address) of the level number must be somewhere in the ROM...
snarfblam
Guest
« Reply #13 on: April 21, 2011, 04:52:07 pm »

I'm not sure I understand the question. You've identified the location of the original "LEVEL" data (19D14). This is loaded into RAM as part of a larger chunk of data that's all loaded at once. Its location in the ROM is never directly referenced. The only pointers for the "LEVEL" data point to the location where it is loaded into RAM. This is why you can't just write the new data to ROM and re-point.

Code:
; Copy source pointer to $00 (found at 8028)
        06:808C:     LDX #$00
        06:808E:     LDA $8028,X
        06:8091:     STA $0000 =
        06:8093:     INX
        06:8094:     LDA $8028,X
        06:8097:     STA $0001

; Load dest pointers (see below)
        06:8099:     JSR $80C6

; Copy routine
        06:809C:     JSR $80D7

; Unrelated crap follows
Code:
; Load copy destination pointers to $02 (start) and $04 (end)
; (67F0 - 687D)
; "LEVEL" macro is included in this (it is copied to $681C)
        06:80C6:     LDA #$F0
        06:80C8:     STA $0002
        06:80CA:     LDA #$67
        06:80CC:     STA $0003
        06:80CE:     LDA #$7D
        06:80D0:     STA $0004
        06:80D2:     LDA #$68
        06:80D4:     STA $0005

If you write the data elsewhere in the ROM (as I did), you'll need to load the additional data into RAM. (You NEED to load it into RAM, so it can be patched before it is handed to the PPU.)

Or do you mean, where does the byte used to patch the "LEVEL" macro come from? If that's the case, it comes from a block of level data that is also loaded into RAM. But this really isn't the issue. The level number isn't a PPU macro in itself, it's a single byte that is patched into "LEVEL" macro:
Code:
05:B02A:AD B1 6B  LDA $6BB1  ; Load level number (from level data block that has been loaded to RAM)
05:B02D:F0 EB     BEQ $B01A  ; Is it a level? (Overworld is level 0)
05:B02F:8D 25 68  STA $6825  ; Then write the level number into the "LEVEL" macro

So, the "LEVEL" macro is loaded into RAM, then modified, then loaded into the PPU.
« Last Edit: April 21, 2011, 05:10:32 pm by snarfblam »
Trax
Guest
« Reply #14 on: April 21, 2011, 05:01:43 pm »

So if the macro in Cartridge RAM is like any other PPU macro around, then there must be two other bytes that define the level number tile position in PPU RAM. Probably at 6823 and 6824...
Pages: [1] 2  


Powered by SMF 1.1.4 | SMF © 2006-2007, Simple Machines LLC