Dragon Quest (J).nes log cursor routine?

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems.

Moderator: Moderators

Post Reply
sleepy9090
Posts: 81
Joined: Fri Aug 22, 2008 10:04 am

Dragon Quest (J).nes log cursor routine?

Post by sleepy9090 » Sat Jul 28, 2012 7:48 am

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

User avatar
Bregalad
Posts: 8008
Joined: Fri Nov 12, 2004 2:49 pm
Location: Chexbres, VD, Switzerland

Post by Bregalad » Sat Jul 28, 2012 8:48 am

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: Select all


  :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.
Useless, lumbering half-wits don't scare us.

sleepy9090
Posts: 81
Joined: Fri Aug 22, 2008 10:04 am

Post by sleepy9090 » Sat Jul 28, 2012 9:24 am

Thanks for the reply.
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
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: Select all

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: Select all

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: Select all

3C5F0A5F0B5F0C5F0D5F0E5F235F245F255F265F275F5B5F5F5FFCF7065F3CF7155F5B5F5F5FFCF706
5F3C5F0F5F105F115F125F135F285F295F2A5F2B5F2C5F5B5F5F5FFCF7065F3CF7155F5B5F5F5FFCF706
5F3C5F145F155F165F175F185F2D5F5F5F2E5F5F5F2F5F5B5F5F5FFCF7065F3CF7155F5B5F5F5FFCF706
5F3C5F195F1A5F1B5F1C5F1D5F305F315F325F335F345F5B5F5F5FFCF7065F3CF7155F5B5F5F5FFCF706
5F3C5F1E5F1F5F205F215F225F355F5F5F365F5F5F375F5B5F5F5FFCF7065F3CF7155F5B5F5F5FFCF706
5F3C5F385F395F3A5F3B5F535F545F2CE5325F0E35315F5B5F5F5FFCF7065F5CF7155D5E5F5F5F
so I change it for my to point to my values:

Code: Select all

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.

sleepy9090
Posts: 81
Joined: Fri Aug 22, 2008 10:04 am

Post by sleepy9090 » Sat Jul 28, 2012 9:28 am

Thanks Bregalad for the help with the first part, will play around with that.
How were you able to find it though?

User avatar
Bregalad
Posts: 8008
Joined: Fri Nov 12, 2004 2:49 pm
Location: Chexbres, VD, Switzerland

Post by Bregalad » Sat Jul 28, 2012 9:36 am

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.
Useless, lumbering half-wits don't scare us.

sleepy9090
Posts: 81
Joined: Fri Aug 22, 2008 10:04 am

Post by sleepy9090 » Sun Jul 29, 2012 7:03 pm

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: Select all

  :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: Select all

  :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: Select all

  :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: Select all

  :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: Select all

  :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: Select all

  :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: Select all

  :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.

Post Reply