This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

Dragon Quest (J).nes log cursor routine?

Dragon Quest (J).nes log cursor routine?
by on (#97230)
Hey guys,

How's everyone doing?

I'm working on translating Dragon Quest to English and am getting progress but ran into an issue with the cursor on the name entry screen. The japanese version has the cursor "jump" over the area where it is not needed, so when I edited the font, the cursor will not let me select some characters and in effect throws my selection out of wack and loads incorrect values in the name. pics best show what i mean

Image
Image

I'm using fceux and trying to log the data for when the cursor moves to find this but not having any luck. I've found the routine where the selected character is loaded (bf71), where the backspace routine is (f431), and the routine where the cursor is blinking (aba4).

1. How do I find the code that is moving the cursor so I can tell it not to skip over 3 positions in the areas i need in the 3rd and 5th rows (A,C,U,W are skipped)?

2. Where do I find where the character selected code is what is loaded in the "name" area. Eg. when i select 'a' it loads '0A' that i have mapped to the "a" character (stored in ppu?), but since I have some characters in different places I would need to change mapping, say if I decided to map 'a' to '0F' or something like that?

Just looking for hints to point me in the right direction if anyone gets a chance. :D

by on (#97232)
Okay I found part of your solution, the code is loaded at $05d2 from CHR-ROM. This game uses a lot this technique to load code form CHR-ROM to RAM because it was limited with only 32k of PRG-ROM.

The cursor's XY position on the screen is stored in variables $8e and $8f.

The two blank spots are simply hard-coded, there is something like this :
Code:

  :051E:E6 8E     INC $008E = #$11
  :0520:E6 8E     INC $008E = #$11
  :0522:20 D2 05  JSR $05D2
  :0525:D0 04     BNE $052B
  :0527:E6 8E     INC $008E = #$11
  :0529:E6 8E     INC $008E = #$11
  :052B:A5 8F     LDA $008F = #$11

[...]

  :05D2:A5 8E     LDA $008E = #$11
  :05D4:C9 13     CMP #$13
  :05D6:D0 0A     BNE $05E2
  :05D8:A5 8F     LDA $008F = #$11
  :05DA:C9 11     CMP #$11
  :05DC:D0 01     BNE $05DF
  :05DE:60        RTS
  :05DF:C9 15     CMP #$15
  :05E1:60        RTS
  :05E2:C9 17     CMP #$17
  :05E4:F0 F2     BEQ $05D8
  :05E6:60        RTS


This makes it basically check if you're before the blank space. Normally the cursor increments by two position, but if the routines returns Z=1, which means we are before a blank space, it will increment by four positions. I don't know if it's what you were looking for, but it seems a step towards the right direction.

Replacing the jsr $5d2 by nops will have the effect you want.

by on (#97235)
Thanks for the reply.

Quote:
If you found the cursor related routines, you're close. You should look for a routine that change the position of the blinking cursor, and find how it handles those jumps.


That's what im having trouble finding, i was thinking that if i started the code data / trace logger i would be able to pick it up when i move the cursor, but it doesn't seem to trigger any data

Quote:
The byte attributed for each letter is probably done in a lockup table, but if they are simply incremental, maybe it's just hard-coded somewhere.


The code for the name entry screen was in order,

Code:
0A=あ
0B=い
0C=う
0D=え
0E=お
10...


I guess im trying to understand where/how it retrieves the value for the selected character, if that makes sense? If i place the cursor on 'a' and press the button, where/how does it take 'a' and put it in the name. Basically it doesnt matter what letter i put in the 'a' location, it is going to look for '0A' value and put that in the name location at the top. The name entry screen is structured like:
offset in rom E732

Code:
0A 0B 0C 0D 0E 23 24 25 26 27
0F 10 11 12 13 28 29 2A 2B 2C
14 15 16 17 18 2D 5F 2E 5F 2F
19 1A 1B 1C 1D 30 31 32 33 34
1E 1F 20 21 22 35 5F 36 5F 37
38 39 3A 3B 53 54 2C....


raw hex:

Code:
3C5F0A5F0B5F0C5F0D5F0E5F235F245F255F265F275F5B5F5F5FFCF7065F3CF7155F5B5F5F5FFCF706
5F3C5F0F5F105F115F125F135F285F295F2A5F2B5F2C5F5B5F5F5FFCF7065F3CF7155F5B5F5F5FFCF706
5F3C5F145F155F165F175F185F2D5F5F5F2E5F5F5F2F5F5B5F5F5FFCF7065F3CF7155F5B5F5F5FFCF706
5F3C5F195F1A5F1B5F1C5F1D5F305F315F325F335F345F5B5F5F5FFCF7065F3CF7155F5B5F5F5FFCF706
5F3C5F1E5F1F5F205F215F225F355F5F5F365F5F5F375F5B5F5F5FFCF7065F3CF7155F5B5F5F5FFCF706
5F3C5F385F395F3A5F3B5F535F545F2CE5325F0E35315F5B5F5F5FFCF7065F5CF7155D5E5F5F5F


so I change it for my to point to my values:

Code:
0A 0B 0C 0D 0E 0F 10 11 12 13
14 15 16 17 18 19 1A 1B 1C 1D
...


now if i select with the cursor the value at 13, it will populate the name with the value i have for 27 (like the old structure). I want to change that.

by on (#97236)
Thanks Bregalad for the help with the first part, will play around with that.
How were you able to find it though?

by on (#97237)
I found it by watching the blinking routine you mentioned in FCEU, and I noticed the position of the cusor was form $3c and $3e, but they are only temporarly variables, the actual position is stored in $8e and $8f.

Its strange the game stores the name screen "raw" like this, with all those $5f wasting ROM when it would have been easier/shorter to write a program that does it from a shorter table.
Anyways it seems that changing the letters will be dead-easy then.

by on (#97278)
So I looked into this a little further with your help identifying $5D2 and made a couple patches and it works. I found 4 locations and documented some of it because I thought it was interesting so sharing it here. Thanks again for pointing me in the correct direction.

Code:
  :047D:A5 8F     LDA $008F = #$0F
  :047F:C9 0D     CMP #$0D
  :0481:F0 27     BEQ $04AA
  :0483:20 95 05  JSR $0595
  :0486:C6 8F     DEC $008F = #$0F
  :0488:C6 8F     DEC $008F = #$0F
  :048A:20 D2 05  JSR $05D2  <----- This jump is taken when moving the cursor up (offset E959) (also on the title screen up)
  :048D:D0 04     BNE $0493
  :048F:C6 8F     DEC $008F = #$0F
  :0491:C6 8F     DEC $008F = #$0F
  :0493:D0 15     BNE $04AA
  :0495:A9 01     LDA #$01
  :0497:24 47     BIT $0047 = #$00
  :0499:D0 A0     BNE $043B
  :049B:A9 10     LDA #$10
  :049D:24 47     BIT $0047 = #$00
  :049F:D0 DC     BNE $047D
  :04A1:0A        ASL
  :04A2:24 47     BIT $0047 = #$00
  :04A4:D0 23     BNE $04C9
  :04A6:70 4D     BVS $04F5
  :04A8:30 63     BMI $050D
  :04AA:A5 8E     LDA $008E = #$17
  :04AC:85 3C     STA $003C = #$17
  :04AE:A5 8F     LDA $008F = #$0F
  :04B0:85 3E     STA $003E = #$0F
  :04B2:20 9F AC  JSR $AC9F
  :04B5:A5 4F     LDA $004F = #$9B
  :04B7:29 10     AND #$10
  :04B9:D0 04     BNE $04BF
  :04BB:A9 56     LDA #$56
  :04BD:D0 02     BNE $04C1
  :04BF:A9 5F     LDA #$5F
  :04C1:85 08     STA $0008 = #$5F
  :04C3:20 A4 AB  JSR $ABA4
  :04C6:4C 25 04  JMP $0425
  :04C9:A5 8F     LDA $008F = #$0F
  :04CB:C9 17     CMP #$17
  :04CD:F0 DB     BEQ $04AA
  :04CF:20 95 05  JSR $0595
  :04D2:E6 8F     INC $008F = #$0F
  :04D4:E6 8F     INC $008F = #$0F
  :04D6:20 D2 05  JSR $05D2  <----- This jump is taken when moving the cursor down (offset E9A5)
  :04D9:D0 04     BNE $04DF
  :04DB:E6 8F     INC $008F = #$0F
  :04DD:E6 8F     INC $008F = #$0F
  :04DF:A5 8F     LDA $008F = #$0F
  :04E1:C9 17     CMP #$17
  :04E3:D0 C5     BNE $04AA
  :04E5:A5 8E     LDA $008E = #$17
  :04E7:C9 15     CMP #$15
  :04E9:F0 04     BEQ $04EF
  :04EB:C9 19     CMP #$19
  :04EB:C9 19     CMP #$19
  :04ED:D0 BB     BNE $04AA
  :04EF:C6 8E     DEC $008E = #$17
  :04F1:C6 8E     DEC $008E = #$17
  :04F3:D0 B5     BNE $04AA
  :04F5:A5 8E     LDA $008E = #$17
  :04F7:C9 07     CMP #$07
  :04F9:F0 AF     BEQ $04AA
  :04FB:20 95 05  JSR $0595
  :04FE:C6 8E     DEC $008E = #$16
  :0500:C6 8E     DEC $008E = #$16
  :0502:20 D2 05  JSR $05D2  <----- This jump is taken when moving the cursor right (offset E9D1) (also on the title screen right)
  :0505:D0 D8     BNE $04DF
  :0507:C6 8E     DEC $008E = #$16
  :0509:C6 8E     DEC $008E = #$16
  :050B:D0 D2     BNE $04DF
  :050D:A5 8E     LDA $008E = #$16
  :050F:C9 19     CMP #$19
  :0511:F0 97     BEQ $04AA
  :0513:C9 17     CMP #$17
  :0515:D0 04     BNE $051B
  :0517:C5 8F     CMP $008F = #$13
  :0519:F0 20     BEQ $053B
  :051B:20 95 05  JSR $0595
  :051E:E6 8E     INC $008E = #$16
  :0520:E6 8E     INC $008E = #$16
  :0522:20 D2 05  JSR $05D2  <----- This jump is taken when moving the cursor left (offset E9F1)
  :0525:D0 04     BNE $052B
  :0527:E6 8E     INC $008E = #$17
  :0529:E6 8E     INC $008E = #$17
  :052B:A5 8F     LDA $008F = #$0F
  :052D:C9 17     CMP #$17
  :052F:D0 0A     BNE $053B
  :0531:A5 8E     LDA $008E = #$17
  :0533:C9 15     CMP #$15
  :0535:D0 04     BNE $053B
  :0537:E6 8E     INC $008E = #$17
  :0539:E6 8E     INC $008E = #$17
  :053B:4C AA 04  JMP $04AA


Patched each JSR with NOP (EAEAEA)

05D6 @offset EAA1

Normal (Up, Down, Left, Right):
Code:
  :05D2:A5 8E     LDA $008E = #$19
  :05D4:C9 13     CMP #$13
  :05D6:D0 0A     BNE $05E2  <----- This jump is taken
  :05D8:A5 8F     LDA $008F = #$15
  :05DA:C9 11     CMP #$11
  :05DC:D0 01     BNE $05DF
  :05DE:60        RTS
  :05DF:C9 15     CMP #$15
  :05E1:60        RTS
  :05E2:C9 17     CMP #$17
  :05E4:F0 F2     BEQ $05D8  <----- This jump not taken
  :05E6:60        RTS        <----- Return


Sometimes this route is used instead:
Code:
  :05D2:A5 8E     LDA $008E = #$19
  :05D4:C9 13     CMP #$13
  :05D6:D0 0A     BNE $05E2  <----- This jump is not taken
  :05D8:A5 8F     LDA $008F = #$15
  :05DA:C9 11     CMP #$11
  :05DC:D0 01     BNE $05DF  <----- This jump is taken
  :05DE:60        RTS
  :05DF:C9 15     CMP #$15
  :05E1:60        RTS        <----- Return
  :05E2:C9 17     CMP #$17
  :05E4:F0 F2     BEQ $05D8
  :05E6:60        RTS


Skip A
Code:
  :05D2:A5 8E     LDA $008E = #$19
  :05D4:C9 13     CMP #$13
  :05D6:D0 0A     BNE $05E2  <----- This jump is not taken
  :05D8:A5 8F     LDA $008F = #$15
  :05DA:C9 11     CMP #$11
  :05DC:D0 01     BNE $05DF  <----- This jump is not taken
  :05DE:60        RTS        <----- Return
  :05DF:C9 15     CMP #$15
  :05E1:60        RTS
  :05E2:C9 17     CMP #$17
  :05E4:F0 F2     BEQ $05D8
  :05E6:60        RTS


Skip C
Code:
  :05D2:A5 8E     LDA $008E = #$19
  :05D4:C9 13     CMP #$13
  :05D6:D0 0A     BNE $05E2  <----- This jump is taken
  :05D8:A5 8F     LDA $008F = #$15
  :05DA:C9 11     CMP #$11
  :05DC:D0 01     BNE $05DF
  :05DE:60        RTS        <----- Return
  :05DF:C9 15     CMP #$15
  :05E1:60        RTS
  :05E2:C9 17     CMP #$17
  :05E4:F0 F2     BEQ $05D8  <----- This jump is taken
  :05E6:60        RTS


Skip U
Code:
  :05D2:A5 8E     LDA $008E = #$19
  :05D4:C9 13     CMP #$13
  :05D6:D0 0A     BNE $05E2  <----- This jump is not taken
  :05D8:A5 8F     LDA $008F = #$15
  :05DA:C9 11     CMP #$11
  :05DC:D0 01     BNE $05DF  <----- This jump is taken
  :05DE:60        RTS
  :05DF:C9 15     CMP #$15
  :05E1:60        RTS        <----- Return
  :05E2:C9 17     CMP #$17
  :05E4:F0 F2     BEQ $05D8
  :05E6:60        RTS


Skip W
Code:
  :05D2:A5 8E     LDA $008E = #$19
  :05D4:C9 13     CMP #$13
  :05D6:D0 0A     BNE $05E2  <----- This jump is taken
  :05D8:A5 8F     LDA $008F = #$15
  :05DA:C9 11     CMP #$11
  :05DC:D0 01     BNE $05DF  <----- This jump is taken
  :05DE:60        RTS
  :05DF:C9 15     CMP #$15
  :05E1:60        RTS        <----- Return
  :05E2:C9 17     CMP #$17ws
  :05E4:F0 F2     BEQ $05D8  <----- This jump is taken
  :05E6:60        RTS


Now I just need to find where the data is pulled when the char is selected.