Skeetendo

’Cause all games were better on the GBC

You are not logged in.

#1 2012-07-14 19:07:20

Danny-E 33
Administrator
Registered: 2012-06-09
Post 55/1,022

Pokemon Red: "Scripting"

So this seems to be pretty simple, yet I can't seem to figure this out...
For some reason I can't change the coordinates of the event that triggers the "[Player] is playing the SNES! ...Okay! It's time to go!" text string in the second floor of the hero's house. I'm pretty sure this would be in what the ROM Map calls "object data" but I don't really know the differences between "script data" and "object data".

The object data is at 0x5C0D0 and goes until 0x5C0EB, so it's really not very long. The default coordinates for the event are (3,5) but there aren't any values in the object data for this map that resemble those coordinates. (although, I have checked the script data also, but I doubt that's where the coordinates would be stored anyway)

Also, the second floor of the Copycat's house reads off of the same map data as the hero's house, but the Copycat's house has it's own script and object data. So the coordinates of the SNES 2x2 tile image are same in both houses, and the coordinates for the text string event are still (3,5). And sure enough, in the Copycat's house object data (which starts at 0x5CD21) there are the bytes 05 03 at address 0x5CD28 which are used as the coordinates (3,5) for the text string event.
So how come there isn't something this obvious in the hero's house object data? I haven't usually had this much of a problem finding undocumented coordinates of an event.

For example: The event of Giovanni's gym that displays the text "The Gym's doors are locked..." has never been editable in a map editor as far as I have seen. But in fact, the offset for the y-coordinate is 0x19022 and the x-coordinate is located at 0x19028. I'm not sure why these coordinates are not side-by-side like most coordinates on a map and that's probably why events like these are not widely known or editable in any map editors. But if anyone's interested, I did find that on my own through lots and lots of trial and error :P
Anyway, I would really appreciate it if anyone could offer any insight as to why I can't seem to find the coordinates of that text string event :)

Last edited by Danny-E 33 (2012-07-15 06:34:19)


Red Hack: Pokémon Prototype

Total number of registered users: 7000+
Total number of active users: ~12

Offline

#2 2012-07-15 01:46:49

488/700

Re: Pokemon Red: "Scripting"

The SNES in Red’s house is implemented as a hidden object. This data starts at 0x46a40; see the disassembly for how to interpret it.

Danny-E 33 wrote:

The event of Giovanni's gym that displays the text "The Gym's doors are locked..." has never been editable in a map editor as far as I have seen. But in fact, the offset for the y-coordinate is 0x19022 and the x-coordinate is located at 0x19028. I'm not sure why these coordinates are not side-by-side like most coordinates on a map and that's probably why events like these are not widely known or editable in any map editors.

This is because the locked door is part of Viridian City’s script:

ld a, [$d361]
cp $8
ret nz
ld a, [$d362]
cp $20
ret nz

This is ASM that checks the current coordinates of the player and checks if they equal the coordinates of the door, and if they don’t, bail out.

(On an unrelated note, please split things up into paragraphs! Your post is hard to read.)

#3 2012-07-15 06:43:01

Danny-E 33
Administrator
Registered: 2012-06-09
Post 58/1,022

Re: Pokemon Red: "Scripting"

IIMarckus wrote:

The SNES in Red’s house is implemented as a hidden object. This data starts at 0x46a40; see the disassembly for how to interpret it.

Oh! That makes alot of sense. So how come the exact same text is used as a hidden object in Red's house but appears as a sign event in Copycat's house? Is there any sort of logical reason that doing it that way was more convinient?

IIMarckus wrote:
Danny-E 33 wrote:

The event of Giovanni's gym that displays the text "The Gym's doors are locked..." has never been editable in a map editor as far as I have seen. But in fact, the offset for the y-coordinate is 0x19022 and the x-coordinate is located at 0x19028. I'm not sure why these coordinates are not side-by-side like most coordinates on a map and that's probably why events like these are not widely known or editable in any map editors.

This is because the locked door is part of Viridian City’s script:

ld a, [$d361]
cp $8
ret nz
ld a, [$d362]
cp $20
ret nz

This is ASM that checks the current coordinates of the player and checks if they equal the coordinates of the door, and if they don’t, bail out.

Hm, interesting! So I didn't try dissassembling this small peice of code myself, but isn't there more to that code for the event? Is there something around it that checks if the player has every badge so it can skip the coordinate check? Or maybe after the coordinate check, if the player coordinate do equal the coordinates of the door, then it checks if the player has all the badges so it can skip the text display?

IIMarckus wrote:

(On an unrelated note, please split things up into paragraphs! Your post is hard to read.)

I'm sorry :/ I tend to just ramble on. I'll watch out for this from now on.


Red Hack: Pokémon Prototype

Total number of registered users: 7000+
Total number of active users: ~12

Offline

#4 2012-07-15 17:51:59

Sawakita
Administrator
Registered: 2010-10-16
Post 286/364

Re: Pokemon Red: "Scripting"

Danny-E 33 wrote:
IIMarckus wrote:
ld a, [$d361]
cp $8
ret nz
ld a, [$d362]
cp $20
ret nz

This is ASM that checks the current coordinates of the player and checks if they equal the coordinates of the door, and if they don’t, bail out.

Hm, interesting! So I didn't try dissassembling this small peice of code myself, but isn't there more to that code for the event? Is there something around it that checks if the player has every badge so it can skip the coordinate check? Or maybe after the coordinate check, if the player coordinate do equal the coordinates of the door, then it checks if the player has all the badges so it can skip the text display?

Why don't you try checking out on your own. Looking through some small piece of ASM code is a good chance to gain experience in it (in case you didn't know, the game stores the information about won badges in the 8 bits in RAM [$D356]).

Last edited by Sawakita (2012-07-15 17:56:14)

Offline

#5 2012-07-17 02:45:17

Danny-E 33
Administrator
Registered: 2012-06-09
Post 61/1,022

Re: Pokemon Red: "Scripting"

Alright. So here's what I found:

;$19011
ld a,[$D356]
cp $7F
jp nz $06
ld hl,$D74C
set 0,hl
ret
ld a,[$D361]
cp $08
ret nz
ld a,[$D362]
cp $20
ret nz
ld a,$0E

So at address $19011, it first loads the byte at $D356 into a, which are the 8 flags for the badges.
Then it compares that to $7F (or 01111111 i.e. checks if you have the first 7 badges)
If the z flag is not set (if you do not have the first 7 badges i.e. the door is locked) jump ahead 6 bytes in code.

(now this is the code it would read if you do have exactly the first 7 badges)
Load hl with the address $D74C
Set bit 0 of the byte at address $D74C?
I don't know what ret means... I think some kind of "return" command?

(now this is where it would jump to if you do have exactly the first 7 badges)
Load the byte at $D361 into a (player's current y-coordinate)
Compare a to $08
Again, I do not know what ret means, but it will only do it if the z flag is not set (if player's current y-coordinate does not equal $08)
Load the byte at $D362 into a (player's current x-coordinate)
Compare a to $20
Again, I do not know what ret means, but it will only do it if the z flag is not set (if player's current x-coordinate does not equal $20)

So I imagine that the ret nz commands are used to tell the game to stop reading when it knows that your coordinates are not equal to the coordinates of the space below the door, bacause it will not need to load the text. Although, I do not know exactly what these commands do. I'm also not sure what the code that is read when you do have exactly 7 badges is used for.


Red Hack: Pokémon Prototype

Total number of registered users: 7000+
Total number of active users: ~12

Offline

#6 2012-07-17 04:20:40

490/700

Re: Pokemon Red: "Scripting"

Danny-E 33 wrote:

Alright. So here's what I found:

;$19011
ld a,[$D356]
cp $7F
jp nz $06
ld hl,$D74C
set 0,hl
ret
ld a,[$D361]
cp $08
ret nz
ld a,[$D362]
cp $20
ret nz
ld a,$0E

So at address $19011, it first loads the byte at $D356 into a, which are the 8 flags for the badges.
Then it compares that to $7F (or 01111111 i.e. checks if you have the first 7 badges)
If the z flag is not set (if you do not have the first 7 badges i.e. the door is locked) jump ahead 6 bytes in code.

You have this reversed. “cp $nn” (compare) is a subtraction, but the results are thrown away. If a = $nn, then a − $nn = 0, so the z (zero) flag is set. If a < $nn, then a − $nn requires a carry, so the c (carry) flag is set.

Danny-E 33 wrote:

(now this is the code it would read if you do have exactly the first 7 badges)
Load hl with the address $D74C
Set bit 0 of the byte at address $D74C?
I don't know what ret means... I think some kind of "return" command?

Yes, ret (“return”) ends every called routine (well, most of them). “call $xxyy” pushes the current location onto the stack and starts execution at $xxyy; “ret” pops the last value from the stack and starts execution there, effectively returning you to where you were before the call.

Danny-E 33 wrote:

(now this is where it would jump to if you do have exactly the first 7 badges)

Again, reversed. And that makes sense if you think about it—why would the script need to know your coordinates if you had all seven badges? It only prints the locked door text if you don’t. If you do have them all, it returns early and never prints the text.

#7 2012-07-17 07:16:54

Danny-E 33
Administrator
Registered: 2012-06-09
Post 62/1,022

Re: Pokemon Red: "Scripting"

IIMarckus wrote:
Danny-E 33 wrote:

(now this is where it would jump to if you do have exactly the first 7 badges)

Again, reversed. And that makes sense if you think about it—why would the script need to know your coordinates if you had all seven badges? It only prints the locked door text if you don’t. If you do have them all, it returns early and never prints the text.

Ah. Well here was my mistake:

Danny-E 33 wrote:

(now this is the code it would read if you do have exactly the first 7 badges)
Load hl with the address $D74C
Set bit 0 of the byte at address $D74C?
I don't know what ret means... I think some kind of "return" command?

(now this is where it would jump to if you do have exactly the first 7 badges)

So I didn't have it reversed exactly. I just literally forgot to type "not" the second time.

IIMarckus wrote:
Danny-E 33 wrote:

Alright. So here's what I found:

;$19011
ld a,[$D356]
cp $7F
jp nz $06
ld hl,$D74C
set 0,hl
ret
ld a,[$D361]
cp $08
ret nz
ld a,[$D362]
cp $20
ret nz
ld a,$0E

So at address $19011, it first loads the byte at $D356 into a, which are the 8 flags for the badges.
Then it compares that to $7F (or 01111111 i.e. checks if you have the first 7 badges)
If the z flag is not set (if you do not have the first 7 badges i.e. the door is locked) jump ahead 6 bytes in code.

You have this reversed. “cp $nn” (compare) is a subtraction, but the results are thrown away. If a = $nn, then a − $nn = 0, so the z (zero) flag is set. If a < $nn, then a − $nn requires a carry, so the c (carry) flag is set.

What exactly do I have reversed? If you do not have the first 7 badges then [$D356] will not equal $7F and the z flag will not be set. "jp nz" means jump forward x bytes if the z flag is not set, so if you do not have 7 badges then it will continue with the door being locked and jump to the coordinate check.

IIMarckus wrote:
Danny-E 33 wrote:

(now this is the code it would read if you do have exactly the first 7 badges)
Load hl with the address $D74C
Set bit 0 of the byte at address $D74C?
I don't know what ret means... I think some kind of "return" command?

Yes, ret (“return”) ends every called routine (well, most of them). “call $xxyy” pushes the current location onto the stack and starts execution at $xxyy; “ret” pops the last value from the stack and starts execution there, effectively returning you to where you were before the call.

Alright, that clears alot up. So is push just like call, except it doesn't begin executing at that new location, it only changes the value in the stack by loading it from bc, de, hl or af then continues executing the next command?

And likewise, pop is kind of like ret, except it doesn't start executing from the value in the stack, but instead it takes the value currently in the stack and puts it into bc, de, hl or af, right?

And what does reti mean?
or rst?

Thanks for helping me out so much, IIMarckus. It feels pretty good getting the hang of asm ^_^

Last edited by Danny-E 33 (2012-07-17 07:20:19)


Red Hack: Pokémon Prototype

Total number of registered users: 7000+
Total number of active users: ~12

Offline

#8 2012-07-17 13:56:13

Miksy91
Member
Registered: 2010-10-16
Post 976/2,305

Re: Pokemon Red: "Scripting"

Danny-E 33 wrote:

So is push just like call, except it doesn't begin executing at that new location, it only changes the value in the stack by loading it from bc, de, hl or af then continues executing the next command?

And likewise, pop is kind of like ret, except it doesn't start executing from the value in the stack, but instead it takes the value currently in the stack and puts it into bc, de, hl or af, right?

And what does reti mean?
or rst?

*All of the following definitions are taken from document "GameBoy Assembly Language Commands"

POP nn         - Pop two bytes off stack into register pair nn.
                  Increment Stack Pointer (SP) twice.

        nn = AF,BC,DE,HL


PUSH nn        - Push register pair nn onto stack.
                  Decrement Stack Pointer (SP) twice.

        nn = AF,BC,DE,HL

RETI           - Pop two bytes from stack & jump to that address
                  then enable interrupts.

RST n          - Push present address onto stack.
                  Jump to address $0000 + n.

        n = $00,$08,$10,$18,$20,$28,$30,$38


RETI is basically same as RET expect it enables interrupts after the instruction is executed. I'm not sure what this actually means though.
The start of ROM bank 0 (those addresses that can be loaded in n) contains several different instructions that can be called with RST n. In other words, I guess you could as well use call $00n (which would waste two bytes, CD n 00).

Offline

#9 2012-07-18 05:29:23

491/700

Re: Pokemon Red: "Scripting"

Danny-E 33 wrote:
IIMarckus wrote:
Danny-E 33 wrote:

(now this is where it would jump to if you do have exactly the first 7 badges)

Again, reversed. And that makes sense if you think about it—why would the script need to know your coordinates if you had all seven badges? It only prints the locked door text if you don’t. If you do have them all, it returns early and never prints the text.

Ah. Well here was my mistake:

Danny-E 33 wrote:

(now this is the code it would read if you do have exactly the first 7 badges)
Load hl with the address $D74C
Set bit 0 of the byte at address $D74C?
I don't know what ret means... I think some kind of "return" command?

(now this is where it would jump to if you do have exactly the first 7 badges)

So I didn't have it reversed exactly. I just literally forgot to type "not" the second time.

IIMarckus wrote:
Danny-E 33 wrote:

Alright. So here's what I found:

;$19011
ld a,[$D356]
cp $7F
jp nz $06
ld hl,$D74C
set 0,hl
ret
ld a,[$D361]
cp $08
ret nz
ld a,[$D362]
cp $20
ret nz
ld a,$0E

So at address $19011, it first loads the byte at $D356 into a, which are the 8 flags for the badges.
Then it compares that to $7F (or 01111111 i.e. checks if you have the first 7 badges)
If the z flag is not set (if you do not have the first 7 badges i.e. the door is locked) jump ahead 6 bytes in code.

You have this reversed. “cp $nn” (compare) is a subtraction, but the results are thrown away. If a = $nn, then a − $nn = 0, so the z (zero) flag is set. If a < $nn, then a − $nn requires a carry, so the c (carry) flag is set.

What exactly do I have reversed? If you do not have the first 7 badges then [$D356] will not equal $7F and the z flag will not be set. "jp nz" means jump forward x bytes if the z flag is not set, so if you do not have 7 badges then it will continue with the door being locked and jump to the coordinate check.

Bah. Did I mention that I’m tired? I reread my post several times before submitting because I was afraid I had it reversed, and I did. Of course, that missing “not” elsewhere confused me, so I have an excuse…

Danny-E 33 wrote:
IIMarckus wrote:
Danny-E 33 wrote:

(now this is the code it would read if you do have exactly the first 7 badges)
Load hl with the address $D74C
Set bit 0 of the byte at address $D74C?
I don't know what ret means... I think some kind of "return" command?

Yes, ret (“return”) ends every called routine (well, most of them). “call $xxyy” pushes the current location onto the stack and starts execution at $xxyy; “ret” pops the last value from the stack and starts execution there, effectively returning you to where you were before the call.

Alright, that clears alot up. So is push just like call, except it doesn't begin executing at that new location, it only changes the value in the stack by loading it from bc, de, hl or af then continues executing the next command?

And likewise, pop is kind of like ret, except it doesn't start executing from the value in the stack, but instead it takes the value currently in the stack and puts it into bc, de, hl or af, right?

It’s easier to think of it this way: the current address being executed is actually represented by a register, pc (Program Counter). So “call $xxyy” is basically “push pc” followed by “ld pc, $xxyy”, and “ret” is equivalent to “pop pc”.

Danny-E 33 wrote:

And what does reti mean?

Return and enable interrupts.

Danny-E 33 wrote:

or rst?

Identical to call. The difference is that there are only a few valid addresses you can use with rst (because it refers to a vector table at the beginning of the ROM)—as a result, rst instructions are only one byte long instead of three.

#10 2012-07-18 16:43:03

Danny-E 33
Administrator
Registered: 2012-06-09
Post 65/1,022

Re: Pokemon Red: "Scripting"

IIMarckus wrote:

Bah. Did I mention that I’m tired? I reread my post several times before submitting because I was afraid I had it reversed, and I did. Of course, that missing “not” elsewhere confused me, so I have an excuse…

Haha, it's alright. Sorry for confusing you :P I'm the one that shoulda reread my post a couple more times before submitting.

Miksy91 wrote:

*All of the following definitions are taken from document "GameBoy Assembly Language Commands"

POP nn         - Pop two bytes off stack into register pair nn.
                  Increment Stack Pointer (SP) twice.

        nn = AF,BC,DE,HL



PUSH nn        - Push register pair nn onto stack.
                  Decrement Stack Pointer (SP) twice.

        nn = AF,BC,DE,HL

RETI           - Pop two bytes from stack & jump to that address
                  then enable interrupts.

RST n          - Push present address onto stack.
                  Jump to address $0000 + n.

        n = $00,$08,$10,$18,$20,$28,$30,$38



RETI is basically same as RET expect it enables interrupts after the instruction is executed. I'm not sure what this actually means though.
The start of ROM bank 0 (those addresses that can be loaded in n) contains several different instructions that can be called with RST n. In other words, I guess you could as well use call $00n (which would waste two bytes, CD n 00).

IIMarckus wrote:
Danny-E 33 wrote:

I don't know what ret means... I think some kind of "return" command?

Yes, ret (“return”) ends every called routine (well, most of them). “call $xxyy” pushes the current location onto the stack and starts execution at $xxyy; “ret” pops the last value from the stack and starts execution there, effectively returning you to where you were before the call.

Danny-E 33 wrote:

So is push just like call, except it doesn't begin executing at that new location, it only changes the value in the stack by loading it from bc, de, hl or af then continues executing the next command?

And likewise, pop is kind of like ret, except it doesn't start executing from the value in the stack, but instead it takes the value currently in the stack and puts it into bc, de, hl or af, right?

It’s easier to think of it this way: the current address being executed is actually represented by a register, pc (Program Counter). So “call $xxyy” is basically “push pc” followed by “ld pc, $xxyy”, and “ret” is equivalent to “pop pc”.

Danny-E 33 wrote:

And what does reti mean?

Return and enable interrupts.

Danny-E 33 wrote:

or rst?

Identical to call. The difference is that there are only a few valid addresses you can use with rst (because it refers to a vector table at the beginning of the ROM)—as a result, rst instructions are only one byte long instead of three.

Ah, ok. I think I really get it now. Thanks :)


Red Hack: Pokémon Prototype

Total number of registered users: 7000+
Total number of active users: ~12

Offline

Board footer

Powered by FluxBB