News:

11 March 2016 - Forum Rules

Main Menu

Help with Game Boy text pointers

Started by Q, May 02, 2018, 08:42:55 PM

Previous topic - Next topic

Q

Hey folks,

Trying to change the text pointers in a Game Boy game, specifically Final Fantasy Legend II, for the first time and I'm running into some trouble. I expanded the ROM to 0.5 MB and inserted a new line of dialogue at $40000. I changed the pointer for an NPC in the first town to 0040, which unless I'm mistaken should be the correct value to point to $40000. But when I try talking to the NPC, nothing happens. The dialogue window doesn't even open. Anyone have any ideas about what I'm doing wrong?
Sneko, the Super Nintendo Entertainment Kitty, wishes you luck.

mz

Quote from: Q on May 02, 2018, 08:42:55 PMAnyone have any ideas about what I'm doing wrong?
Yes, 0040 would point to position 0x0 in whatever ROM bank is currently set.

To access ROM position 0x40000 you first need to do a bank switch to 0x10 or something.

Game Boy games usually already support 24-bit pointers, so try changing one of the bytes around your 0040 pointer to 10 (or whatever the correct bank is). That is, insert the pointer as 100040 or 004010...
There has to be a better life.

Q

I'm pretty sure the pointers are only two bytes. Does that mean I would need to use ASM to expand the pointers to three bytes in order to point to $40000?
Sneko, the Super Nintendo Entertainment Kitty, wishes you luck.

mz

Quote from: Q on May 02, 2018, 09:54:10 PMDoes that mean I would need to use ASM to expand the pointers to three bytes in order to point to $40000?
Only if you plan to use multiple banks (that is, more than 0x4000 bytes); otherwise, just switch the bank to 0x10 once within the text routine. It's very likely that it is already switching the bank to the old text position, so you only have to change the number in that byte.

In any case: yes, you need to know and use ASM. I believe it was "ld ($2000),a" to switch banks, where the CPU register a contains your new bank number.
There has to be a better life.

Psyklax

If the pointers are definitely two bytes, then SOMETHING is going to change the bank. What precisely? Depends on the game. I translated Detective Conan and it used three byte pointers: one for the bank and two for the position within the bank. If this game only uses two bytes for its pointers, chances are it keeps the text largely in one bank (you can confirm that).

Would you need to hack the game to use three byte pointers? Maybe. First you need to figure out if there's a reason it only uses two bytes - i.e. is all the text in one bank, and if not, how does the game decide which bank to use for a particular line of dialogue.

Putting dialogue in a different bank is one of the first things I do in a translation, because if you can pull it off then things will get a lot easier. Learning assembly is always a good idea if you're serious about hacking, though: I expanded a NES game and switched banks by including a routine that checked which level you were on and switched banks accordingly.

One question I'd ask: where is all the text? In one bank or more? If one, does it have other non-text stuff clogging up the bank, or is the bank nothing but text? If the pointers are in the same bank as the text, that'll explain why they're two bytes.

Get back to us with the details on those questions and we'll go from there. ;)

Q

Hey again,

I'm at work right now, so I can't check the ROM, but I will get back to you with the locations of the text later. A couple other questions, though.

First, the banks would be 3FFF bytes long, correct?

Second, if the text is all in one bank, what are the chances that different types of text use different "bank pointers" (or whatever you'd call them)? What I'm wondering is, if I relocate the dialogue, what are the chances I would also need to relocate item/ability/monster names, menu text, and other miscellaneous text?
Sneko, the Super Nintendo Entertainment Kitty, wishes you luck.

mz

Quote from: Q on May 03, 2018, 12:35:45 PMFirst, the banks would be 3FFF bytes long, correct?
No, they would be 0x4000 bytes long.

Quote from: Q on May 03, 2018, 12:35:45 PMSecond, if the text is all in one bank, what are the chances that different types of text use different "bank pointers" (or whatever you'd call them)? What I'm wondering is, if I relocate the dialogue, what are the chances I would also need to relocate item/ability/monster names, menu text, and other miscellaneous text?
I've worked on a dozen or so games so far, and I've never found one that shares the pointers/programming for the dialogue and the other stuff. Obviously, it still is very possible, but not very common in my experience.

But I've only hacked rather complex games, and I imagine that it can become more common as the games get smaller/simpler...
There has to be a better life.

Q

Hey again,

The first text block I want to move is located from approximately 0x28200 to 0x2AAC0. The text is immediately preceded by the pointer table (from 0x28001 until the start of the text). The pointer table is immediately preceded by some free spaces (00s).

There are several other text blocks I also want to move that follow this one. Some of them definitely have their own pointer tables, but a few might share the same table as the one I'm currently trying to move. I haven't looked too closely yet. The last bit of text I want to move ends at approximately 0x2F390.
Sneko, the Super Nintendo Entertainment Kitty, wishes you luck.

Psyklax

#8
Quote from: Q on May 03, 2018, 06:01:47 PM
The text is immediately preceded by the pointer table (from 0x28001 until the start of the text). The pointer table is immediately preceded by some free spaces (00s).

There are several other text blocks I also want to move that follow this one. Some of them definitely have their own pointer tables, but a few might share the same table as the one I'm currently trying to move. I haven't looked too closely yet. The last bit of text I want to move ends at approximately 0x2F390.

Well, the bank starts at $28000 so the free space that precedes it is in a different bank. Remember that each bank is $4000, so $20000, $24000, $28000, $2C000 are the start points of different banks. So that free space ain't much good since it's in a different bank.

If you say that you have two-byte pointers are the very beginning of the bank, followed by most of the bank being text, that explains what I said before: those pointers are obviously going to be two-byte ones because they're in the same bank - why waste bytes if they're all in the same bank? Also, they "might share the same table"? Well, that's easy to figure out, just do what I do. Copy the whole pointer table from HxD to TextPad, put each pair of bytes on a new line, block cut the latter byte and paste it in front of the other byte, then I use OpenOffice Calc to add whatever the bank start is. Meh, it works for me. :D

Anyway, $28000 (and presumably $2C000 too) is obviously a text-only bank, and a bit of assembly and debugging will tell you how the game knows to look in that bank and not a different bank. Since I haven't looked at the game for more than five minutes, I can't say much on that. Incidentally, you're not translating the game... what exactly are you planning on doing? :)

EDIT: okay, in literally five minutes of looking at the ROM in HxD, I see precisely what we're dealing with. :D

Here are your table files and the first/last lines of each.

Table A: $28000
First line: $28200
Last line: $2BE0E (no idea about the stuff after it, cause $00 is clearly the end control code, and there's a bunch of stuff unaccounted for)

Table B: $2C000
First line: $2C180
Last line: $2E9C2

Table C: $2EB80
First line: $2EC5A
Last line: $2F37A

Table D: $2F400
First line: $2F49A
Last line: $2FFB4

I wasn't going to post the whole pointer list, but... ah, here you are. :D

28200
2820C
2821A
2822B
28238
28243
28251
2825E
2826F
2827E
28290
282B1
282C5
282C8
282F6
282F9
2833A
28342
283A2
283EF
2841A
28444
2845A
28467
28484
284A5
284A8
284AB
284AE
284EF
2850A
2850D
28510
2852F
28532
28547
28555
2859F
285C1
285D3
285E4
285EC
285FF
28620
28623
28650
28684
286A4
28805
28876
2888B
288A6
28908
28950
28956
289B5
289D4
289F4
28A0C
28A87
28AAB
28ACE
28AD2
28B01
28B04
28B1F
28B37
28B4C
28B75
28B91
28C11
28C51
28C6C
28C95
28CC7
28D52
28D59
28D7F
28F47
28F5F
28F74
28FA1
28FCE
29006
29205
29224
29240
29253
2932C
29352
2937B
2939F
293BB
293CE
29406
29499
2951A
2955B
29578
295B6
295F0
29610
2964C
29685
296C3
296E8
29714
29718
29774
297A7
297C3
297EE
29814
29837
2986D
298A8
29945
29A46
29A49
29AE8
29AEF
29AFB
29B0D
29B12
29B16
29B1D
29B5A
29B89
29B97
29BB6
29BBD
29BCE
29C0C
29C32
29C51
29CA7
29CCC
29CFD
29D1D
29D46
29D52
29D84
29DEE
29E33
29E41
29E9B
29EA6
29EB1
29F30
29F3B
29F3E
29F65
29F88
2A2A4
2A2A7
2A2E5
2A2FE
2A36B
2A39C
2A3F5
2A42F
2A43A
2A43B
2A43C
2A43D
2A45B
2A4EE
2A566
2A5A9
2A600
2A604
2A608
2A62F
2A64C
2A655
2A682
2A6A3
2A704
2A729
2A74E
2A782
2A7A9
2A7E7
2A7F9
2A810
2A817
2A84D
2A87D
2A945
2A948
2A975
2A997
2A9A3
2A9B3
2A9B8
2A9D1
2A9EA
2AA03
2AA47
2AA5C
2AA8B
2AABE
2AAE6
2AB0D
2AB35
2AB64
2AB6F
2AB7A
2AB8D
2ABD0
2ABDD
2AC98
2ACB3
2ADF6
2B073
2B07F
2B096
2B165
2B184
2B2DA
2B316
2B334
2B364
2B375
2B398
2B403
2B416
2B43B
2B450
2B5FA
2B633
2B822
2B9EE
2B9F2
2B9FF
2BA0D
2BA16
2BB6D
2BB86
2BBAC
2BBC2
2BBDE
2BBEA
2BBF8
2BC11
2BC1C
2BC39
2BC76
2BCC4
2BD0B
2BD41
2BD75
2BD94
2BDB8
2BDEA
2BE0E

2C180
2C181
2C784
2C796
2C7A0
2C7C7
2C7D9
2C7E1
2C7EC
2C807
2C80F
2C83C
2C844
2C859
2C86E
2C884
2C89B
2C8AC
2C8B7
2C8C5
2C90B
2C98D
2C9BA
2C9F5
2CA14
2CA1E
2CA6A
2CA72
2CA76
2CA87
2CA96
2CAA0
2CAA9
2CAB2
2CABB
2CAC4
2CACD
2CAD6
2CAF7
2CB22
2CB2D
2CB4C
2CBF9
2CC04
2CCB8
2CCBD
2CCC8
2CCD7
2CCEB
2CD00
2CD04
2CD0B
2CD16
2CE11
2CE1B
2CE85
2CE92
2CE9F
2CEAC
2CEB6
2CEC0
2CECB
2CECF
2CED6
2CF0B
2CF2A
2CF35
2CF7E
2CF89
2CF93
2CF9D
2CFA7
2CFB1
2CFBB
2CFC5
2CFCF
2CFD9
2CFE3
2CFED
2D03E
2D117
2D169
2D171
2D186
2D191
2D195
2D1A0
2D1A7
2D1B2
2D1F9
2D200
2D215
2D239
2D25F
2D26D
2D279
2D28D
2D297
2D2A1
2D2AB
2D2B5
2D2BF
2D2C9
2D2DA
2D2EB
2D2F5
2D2FF
2D309
2D313
2D31D
2D327
2D338
2D34B
2D3F4
2D3F7
2D41C
2D41F
2D43F
2D554
2D56E
2D820
2D99A
2D9DA
2D9E3
2DA19
2DA3B
2DA79
2DAC5
2DB1A
2DB21
2DB38
2DB62
2DC43
2DC61
2E070
2E089
2E0CE
2E0E6
2E0E9
2E0F6
2E103
2E111
2E15B
2E2AD
2E44F
2E458
2E45F
2E466
2E46D
2E474
2E482
2E489
2E490
2E497
2E49E
2E4A5
2E4AC
2E4B3
2E4BA
2E4C1
2E4CB
2E4D6
2E4E1
2E4EC
2E4F3
2E4FA
2E501
2E51A
2E55E
2E570
2E574
2E57D
2E588
2E58F
2E622
2E625
2E65C
2E687
2E6C0
2E6DC
2E72B
2E754
2E788
2E86D
2E88D
2E8B8
2E8E9
2E90B
2E93F
2E95B
2E987
2E9C2

2EC5A
2EC67
2EC77
2EC82
2EC89
2EC96
2ECA0
2ECB7
2ECC0
2ECC5
2ECD4
2ECE4
2ECF1
2ECFB
2ED08
2ED18
2ED1D
2ED28
2ED35
2ED4C
2ED54
2ED5D
2ED63
2ED6B
2ED7A
2ED8A
2ED8F
2ED9E
2EDA4
2EDBB
2EDCF
2EDE5
2EDFD
2EE15
2EE1C
2EE27
2EE29
2EE32
2EE49
2EE58
2EE75
2EE82
2EE95
2EEA9
2EEC6
2EEE4
2EEF8
2EF02
2EF1D
2EF29
2EF3E
2EF53
2EF68
2EF75
2EF77
2EF93
2EF9D
2EFA3
2EFAF
2EFC1
2EFC9
2EFD6
2EFE3
2EFEE
2EFF8
2F00E
2F020
2F03C
2F048
2F062
2F076
2F08B
2F08D
2F099
2F0A1
2F0B0
2F0BF
2F0C7
2F0D3
2F0DE
2F0F1
2F0FA
2F0FF
2F109
2F112
2F11F
2F129
2F133
2F13F
2F145
2F159
2F163
2F165
2F171
2F18A
2F1BB
2F1DD
2F1FB
2F211
2F237
2F2B4
2F2D4
2F2F2
2F300
2F334
2F347
2F357
2F369
2F37A

2F49A
2F510
2F53A
2F542
2F54D
2F5A5
2F5BE
2F5D3
2F5F8
2F644
2F6E1
2F6F0
2F707
2F717
2F737
2F7B9
2F7BE
2F80C
2F81E
2F830
2F8C4
2F904
2F960
2F984
2F9A8
2F9CC
2F9E1
2F9FE
2FA32
2FA42
2FA4B
2FA65
2FA80
2FA96
2FA9F
2FAAE
2FB22
2FB31
2FB4D
2FBC1
2FBCE
2FBFF
2FC15
2FC28
2FC36
2FC40
2FC47
2FC51
2FC86
2FCBE
2FCCF
2FCE2
2FCF7
2FD0C
2FD58
2FD6B
2FD80
2FD90
2FDAA
2FDB8
2FDC2
2FDCF
2FDDC
2FDE7
2FE0A
2FE11
2FE1B
2FE50
2FE55
2FE5B
2FF43
2FF54
2FF69
2FF79
2FF86
2FF96
2FFB4


So in case you're wondering, the reason each pointer is, for example, "00 42" is because the bank is loaded at $4000 in the CPU's address space, rather than $0000 (because the main game code will be loaded there). The Z80 CPU is little-endian, so the least significant byte (LSB goes first. Therefore, the next pointer, "0C 42", goes to $2820C: you put the second byte first (420C), take away the $4000 that I just mentioned (020C) and add whatever the start of that bank is (2820C). See? Simple. :)

So if you want to expand your ROM and put something at $40000, the game won't know where to look. You'll need to figure out how the game switches that $4000-$7FFF space.

Q

Quote from: Psyklax on May 03, 2018, 06:57:14 PM
Incidentally, you're not translating the game... what exactly are you planning on doing? :)

I'm not translating the game, but I do want to insert a new translation. The original English release of the game has an awful translation. But there was a DS remake that got a fan translation patch. I'd like to insert the script from that into the original GB version.
Sneko, the Super Nintendo Entertainment Kitty, wishes you luck.

Psyklax

Quote from: Q on May 04, 2018, 08:42:24 AM
I'm not translating the game, but I do want to insert a new translation.

Aha. So you're concerned that the new translation won't fit in that space, or what? If you have the new translation in a plain text form, you could dump the one from the GB ROM and compare. If the size is roughly the same then you may not need to worry about anything. :)

Alternatively, if the text is a bit large, you could go the compression route, like DTE. That's what I would do, though I haven't done it on GB before. It's a choice, really: DTE or bank switching, whichever is easier.

Q

I'm reasonably sure the script won't fit, although it's just an educated guess. The game already uses DTE extensively and there doesn't seem to be a ton of free space left over.

I actually haven't been able to compare the length of the text yet. Besides DTE making it an apples-to-oranges comparison, the DS version adds new dialogue AND rearranges the existing dialogue. I haven't had a chance to compile the script yet, but I plan to soon.
Sneko, the Super Nintendo Entertainment Kitty, wishes you luck.