+  RHDN Forum Archive
|-+  Romhacking
| |-+  ROM Hacking Discussion
| | |-+  Right to left language
Pages: [1]
Author Topic: Right to left language  (Read 1 times)
Squall
Guest
« on: February 19, 2010, 01:09:18 pm »

How can I make a NES ROM to support right to left language?
I don't have any problem for translating fixed text on the screen but texts which gradually appear from left to right, are really hard to translate.
Captain Tsubasa Arabic translation is a good example for this matter.
I guess I have to do it in assembly 6502 but I don't have any idea how to do it?
I appreciate anyone who can help me.

Ryusui
Guest
« Reply #1 on: February 19, 2010, 02:13:24 pm »

In the simplest scenario, the game writes the appropriate character value to the PPU, increments the index by one, and repeats indefinitely until all text is displayed.

In your case, you need to do two things:

1. Change the starting address so that the first character will be written to the right edge of the text box.

2. Decrement the index so that the text is written in reverse order.

So yes, it has to be done through ASM, but depending on the game, it shouldn't be difficult at all - changing a single value and a single instruction will probably do everything you need.
KingMike
Guest
« Reply #2 on: February 19, 2010, 02:24:10 pm »

The PPU is optimized for left-to-right or top-to-bottom writing (auto-increment address by 1 or $20 after each write).
So unfortunately, writing in the reverse direction would make for a slower to execute routine that may or may not work within the VRAM access time limit (during VBlank).

(though I guess I'm not sure exactly how critical timing on the NES usually is. I just have bad memories of Dragon Scroll (had to replace the VRAM buffer routines just to write four freakin' bytes extra (widen the window 2 tiles) to VRAM without causing flicker)
Squall
Guest
« Reply #3 on: February 20, 2010, 07:12:29 am »

I really didn't get it. Can you explain more?
Is there any tutorial for this or using 6502 debugger of fceux emulator?

Dragonsbrethren
Guest
« Reply #4 on: February 20, 2010, 04:47:02 pm »

Quote from: KingMike on February 19, 2010, 02:24:10 pm
The PPU is optimized for left-to-right or top-to-bottom writing (auto-increment address by 1 or $20 after each write).
So unfortunately, writing in the reverse direction would make for a slower to execute routine that may or may not work within the VRAM access time limit (during VBlank).

(though I guess I'm not sure exactly how critical timing on the NES usually is. I just have bad memories of Dragon Scroll (had to replace the VRAM buffer routines just to write four freakin' bytes extra (widen the window 2 tiles) to VRAM without causing flicker)
I don't think this would make a big difference. If the text is being printed letter by letter, the routine probably idles for a few frames anyway. Maybe I'm underestimating it, though, I've only coded stuff like this from scratch, rather than trying to work it into existing code.

Quote from: Squall on February 20, 2010, 07:12:29 am
I really didn't get it. Can you explain more?
Try following these tutorials:

http://www.nintendoage.com/forum/messageview.cfm?catid=22&threadid=7155

They're written for developing your own game, but the skills they teach can be applied to ROM hacking. Basicallly, if you look at the background2 tutorial's example loop:

Code:
LoadBackground:
  LDA $2002             ; read PPU status to reset the high/low latch
  LDA #$20
  STA $2006             ; write the high byte of $2000 address
  LDA #$00
  STA $2006             ; write the low byte of $2000 address
  LDX #$00              ; start out at 0

LoadBackgroundLoop:
  LDA background, x     ; load data from address (background + the value in x)
  STA $2007             ; write to PPU
  INX                   ; X = X + 1
  CPX #$80              ; Compare X to hex $80, decimal 128 - copying 128 bytes
  BNE LoadBackgroundLoop  ; Branch to LoadBackgroundLoop if compare was Not Equal to zero
                        ; if compare was equal to 128, keep going down


You'll want to change it to something like:

Code:
LoadBackground:
  LDX #$00              ; start out at 0
  LDY #$80              ; example starting low byte of PPU address

LoadBackgroundLoop:
  LDA $2002             ; read PPU status to reset the high/low latch
  LDA #$20
  STA $2006             ; write the high byte of $2080 address
  STY $2006             ; write the low byte of $2080 address (loaded in Y)
  LDA background, x     ; load data from address (background + the value in x)
  STA $2007             ; write to PPU
  DEY                   ; Decrease Y, next tile will be written to the left of previous
  INX                   ; X = X + 1
  CPX #$80              ; Compare X to hex $80, decimal 128 - copying 128 bytes
  BNE LoadBackgroundLoop  ; Branch to LoadBackgroundLoop if compare was Not Equal to zero

                        ; if compare was equal to 128, keep going down

Now, this code is probably nothing like the code you'll be working with in the game, but it gives you an idea of what you need to do. You need to write the new PPU address every time you read a character, rather than at the start of a string of characters.

I'm no expert, so there might be a better way of doing this.
« Last Edit: February 20, 2010, 07:09:24 pm by Dragonsbrethren »
tummai
Guest
« Reply #5 on: February 21, 2010, 04:19:31 am »

Quote from: Dragonsbrethren on February 20, 2010, 04:47:02 pm
Now, this code is probably nothing like the code you'll be working with in the game, but it gives you an idea of what you need to do. You need to write the new PPU address every time you read a character, rather than at the start of a string of characters.

I'm no expert, so there might be a better way of doing this.

Looks like a good example case to me.  You could improve it by taking LDA $2002 out of the loop.  Since you always write to $2006 in pairs you don't need to reset the latch every time.

The main point as you said is that you have to write the address manually for each tile.  This means more PPU writes per tile (3 vs. 1) which potentially increases your chances of spilling out of vblank.  If the game is only writing a few characters into the textbox per frame it might not be a big deal though.
Dragonsbrethren
Guest
« Reply #6 on: February 22, 2010, 07:38:58 am »

Quote from: tummai on February 21, 2010, 04:19:31 am
Looks like a good example case to me.  You could improve it by taking LDA $2002 out of the loop.  Since you always write to $2006 in pairs you don't need to reset the latch every time.

Interesting, I never knew that. I was under the impression you needed to reset it any time you fed it a new starting offset. When do you need to reset it?
tummai
Guest
« Reply #7 on: February 22, 2010, 08:46:27 am »

Quote from: Dragonsbrethren on February 22, 2010, 07:38:58 am
Quote from: tummai on February 21, 2010, 04:19:31 am
Looks like a good example case to me.  You could improve it by taking LDA $2002 out of the loop.  Since you always write to $2006 in pairs you don't need to reset the latch every time.

Interesting, I never knew that. I was under the impression you needed to reset it any time you fed it a new starting offset. When do you need to reset it?

When you don't know the state of the hi/lo latch.  If there's any doubt, it's good practice to read $2002 just to be safe.  Not necessary in this case because we know it will always be HI after each pair of writes.
Squall
Guest
« Reply #8 on: March 28, 2010, 04:32:20 pm »

Quote from: Dragonsbrethren on February 20, 2010, 04:47:02 pm
Quote from: KingMike on February 19, 2010, 02:24:10 pm
The PPU is optimized for left-to-right or top-to-bottom writing (auto-increment address by 1 or $20 after each write).
So unfortunately, writing in the reverse direction would make for a slower to execute routine that may or may not work within the VRAM access time limit (during VBlank).

(though I guess I'm not sure exactly how critical timing on the NES usually is. I just have bad memories of Dragon Scroll (had to replace the VRAM buffer routines just to write four freakin' bytes extra (widen the window 2 tiles) to VRAM without causing flicker)
I don't think this would make a big difference. If the text is being printed letter by letter, the routine probably idles for a few frames anyway. Maybe I'm underestimating it, though, I've only coded stuff like this from scratch, rather than trying to work it into existing code.

Quote from: Squall on February 20, 2010, 07:12:29 am
I really didn't get it. Can you explain more?
Try following these tutorials:

http://www.nintendoage.com/forum/messageview.cfm?catid=22&threadid=7155

They're written for developing your own game, but the skills they teach can be applied to ROM hacking. Basicallly, if you look at the background2 tutorial's example loop:

Code:
LoadBackground:
  LDA $2002             ; read PPU status to reset the high/low latch
  LDA #$20
  STA $2006             ; write the high byte of $2000 address
  LDA #$00
  STA $2006             ; write the low byte of $2000 address
  LDX #$00              ; start out at 0

LoadBackgroundLoop:
  LDA background, x     ; load data from address (background + the value in x)
  STA $2007             ; write to PPU
  INX                   ; X = X + 1
  CPX #$80              ; Compare X to hex $80, decimal 128 - copying 128 bytes
  BNE LoadBackgroundLoop  ; Branch to LoadBackgroundLoop if compare was Not Equal to zero
                        ; if compare was equal to 128, keep going down


You'll want to change it to something like:

Code:
LoadBackground:
  LDX #$00              ; start out at 0
  LDY #$80              ; example starting low byte of PPU address

LoadBackgroundLoop:
  LDA $2002             ; read PPU status to reset the high/low latch
  LDA #$20
  STA $2006             ; write the high byte of $2080 address
  STY $2006             ; write the low byte of $2080 address (loaded in Y)
  LDA background, x     ; load data from address (background + the value in x)
  STA $2007             ; write to PPU
  DEY                   ; Decrease Y, next tile will be written to the left of previous
  INX                   ; X = X + 1
  CPX #$80              ; Compare X to hex $80, decimal 128 - copying 128 bytes
  BNE LoadBackgroundLoop  ; Branch to LoadBackgroundLoop if compare was Not Equal to zero

                        ; if compare was equal to 128, keep going down

Now, this code is probably nothing like the code you'll be working with in the game, but it gives you an idea of what you need to do. You need to write the new PPU address every time you read a character, rather than at the start of a string of characters.

I'm no expert, so there might be a better way of doing this.

Can you tell me how can I find my own routine in the game?

And please tell me what is the "high/low latch"?
Squall
Guest
« Reply #9 on: May 05, 2010, 02:37:53 am »

What an excellent way is Trial and Error! Finally I did it without any error! (oh my god)  :crazy: :woot!:

Here is the brief explanation of what I had done :

1. Finding the hex value of the sentence which must be written from right to left.
(in my case was : EA A9 B7 A6 EB ...)

2. Finding the offset of the first character (EA) in the rom.
(in my case was : $319F)

3. Using KingMike's DTE document for finding the correct breakpoint.
(in my case was : $B18F)
http://www.romhacking.net/docs/%5B384%5Ddtehelp.zip

4. Using step over button and reviewing the routine that is running for printing the text.

5. changing an increment somewhere into a decrement so that the text will appear in a reverse order (right to left).
(in my case : 00:B044:EE 08 06 INC $0608 = #$02    TO    00:B044:CE 08 06  DEC $0608)

6. changing the code for when it resets to the left margin to instead set to the right margin.
(in my case :
00:B032:69 20     ADC #$20         TO       00:B032:69 1A     ADC #$1A
00:B0AC:AD 18 B1  LDA $B118      TO       00:B0AC:A9 23     LDA #$23
00:AF1F:AD 18 B1  LDA $B118       TO       00:AF1F:A9 23     LDA #$23)

To be honest I didn't get the point for the last step and I find it just by trial and error, and of course with the help of some other nice people in this forum and the following forum :
http://nesdev.parodius.com/bbs/viewtopic.php?t=6270&sid=d4f66ec9e0ffc75489059ffe2ab81198

Maybe in the future I will have enough knowledge to write a complete tutorial for this. I am sure it will be a great help for the people of the middle east.  :thumbsup:

Pages: [1]  


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