Points of Required Attention™
Please chime in on a proposed restructuring of the ROM hacking sections.
Views: 88,486,538
Main | FAQ | Uploader | IRC chat | Radio | Memberlist | Active users | Latest posts | Calendar | Stats | Online users | Search 04-26-24 09:31 AM
Guest: Register | Login

0 users currently in ROM Hacking | 2 guests | 2 bots

Main - ROM Hacking - I've come accross a few interesting 6502 ASM things... New thread | New reply


Jigglysaint
Posted on 09-04-08 05:11 AM Link | Quote | ID: 89836


Red Paragoomba
Level: 20

Posts: 28/62
EXP: 38539
Next: 3900

Since: 04-04-07

Last post: 4617 days
Last view: 2354 days
So I've been hacking the Guardian Legend...again, and I've noticed a few odd things that seem to not make any sense. The first is that for a specific spot in the rom, the pointers that lead to data all lead to the last byte of the previous code. So basically the pointers lead to an RTS, but the data the pointer is getting is one byte to the right of it.

The second oddity is that there are pointers that are defined, but the code that defines them runs right into the list without an RTS to signify the end of the code. Say for example that we have the code, followed by a JSR xx xx, but then I see a $47 $C0 followed by the pointer list. I've seen this happen with the Z80, but not with the 6502. In fact, $47 is considered future expansion.

So does anbody know what's going on with this?

Sliver X
Posted on 09-04-08 06:33 AM Link | Quote | ID: 89842


Paragoomba
Level: 21

Posts: 62/66
EXP: 42453
Next: 7490

Since: 02-26-07
From: WV

Last post: 5488 days
Last view: 5344 days
Posted by Jigglysaint
So I've been hacking the Guardian Legend...again, and I've noticed a few odd things that seem to not make any sense. The first is that for a specific spot in the rom, the pointers that lead to data all lead to the last byte of the previous code. So basically the pointers lead to an RTS, but the data the pointer is getting is one byte to the right of it.


Sure it's not doing something like an LDA, X? What's the status of X and Y when a pointer is read? Is either #$01?



The second oddity is that there are pointers that are defined, but the code that defines them runs right into the list without an RTS to signify the end of the code. Say for example that we have the code, followed by a JSR xx xx, but then I see a $47 $C0 followed by the pointer list. I've seen this happen with the Z80, but not with the 6502. In fact, $47 is considered future expansion.


Most likely $47 and $C0 are some kind of data, not opcodes. FCEUXD's code/data logger would easily show which it is without debugging.



____________________
Arc-Nova.org: More Chiptunes Than Your Mother Can Handle

NetSplit
Posted on 09-04-08 07:04 AM Link | Quote | ID: 89843


Level: 32

Posts: 115/178
EXP: 188030
Next: 18412

Since: 02-26-07

Last post: 2217 days
Last view: 2142 days
Assuming the pointers point to code, they are likely being pushed to the stack and then used with an RTS. RTS works by pulling the top two bytes from the stack and jumping to that address plus one. I used to know a bit about the reasoning for that sort of setup, but I've since forgotten. The RTS method is an important method for jumping to the proper routine; for example, if you have several weapons and need to get to the code for the right one, putting the address minus one on the stack and doing RTS is an effective method for getting there.

I don't know what to tell you about the other thing. In the event that you haven't simply read the code wrong, it's certainly possible to do JSRs that don't need to be returned from. It's possible that the game wants the address, in which case you could do a JSR and a couple of PLA instructions, followed by adding 1 to the pair if need be. One would need to examine the code, primarily after the JSR, to understand what it's doing.

smkdan
Posted on 09-04-08 07:50 AM Link | Quote | ID: 89845


Ninji
Level: 36

Posts: 151/238
EXP: 288647
Next: 19463

Since: 05-26-07

Last post: 4062 days
Last view: 4011 days

It's possible that the game wants the address, in which case you could do a JSR and a couple of PLA instructions, followed by adding 1 to the pair if need be. One would need to examine the code, primarily after the JSR, to understand what it's doing.


I know SMW does this a fair bit and that metroid disassembly on RHDN does this too.

CODE_00C593:        A5 71         LDA RAM_MarioAnimation    
CODE_00C595: 22 DF 86 00 JSL.L ExecutePtr

AnimationSeqPtr: 68 CC .dw ResetAni ; 0 - Reset
29 D1 .dw PowerDownAni ; 1 - Power down
47 D1 .dw MushroomAni ; 2 - Mushroom power up
5F D1 .dw CapeAni ; 3 - Cape power up
6F D1 .dw FlowerAni ; 4 - Flower power up
97 D1 .dw DoorPipeAni ; 5 - Door/Horizontal pipe exit
03 D2 .dw VertPipeAni ; 6 - Vertical pipe exit
87 D2 .dw PipeCannonAni ; 7 - Shot out of diagonal pipe
FD C7 .dw YoshiWingsAni ; 8 - Yoshi wings exit
B6 D0 .dw MarioDeathAni ; 9 - Mario Death
70 C8 .dw EnterCastleAni ; A - Enter Castle
B5 C5 .dw UnknownAniB ; B - freeze forever
E7 C6 .dw UnknownAniC ; C - random movement??
92 C5 .dw Return00C592 ; D - freeze forever


By placing pointer table right after the JSL/JSR, the routine that is being 'called' can pull the return address off the stack, add 1 and treat it as a pointer to the jump table which in this case is indexed by the value in A. This may be relevant considering you said that there's a pointer list after the JSR in the game.

Trax
Posted on 09-04-08 09:26 AM Link | Quote | ID: 89850


Yellow Stalfos
Level: 71

Posts: 490/1145
EXP: 3035781
Next: 131333

Since: 07-06-07
From: Québec

Last post: 3627 days
Last view: 2879 days
Exactly. I've seen that a few times, it's possible that a JSR doesn't come back to where it was called, because the routine it points to pulls a byte from the stack two times and jumps to the address using the two bytes. But there's no way you can tell until you know the ROM well. There are even blocks of code that end with BNE or BEQ...

The first oddity looks like an indirect address fetch. It could be that, just next of the RTS, there's some data table, and the offset variable is known to be always more than 0. It's made this way sometimes when the variable values are not zero-based...

Jigglysaint
Posted on 09-06-08 04:51 AM Link | Quote | ID: 89957


Red Paragoomba
Level: 20

Posts: 29/62
EXP: 38539
Next: 3900

Since: 04-04-07

Last post: 4617 days
Last view: 2354 days
Ahh that would explain it then. It's pretty much a creative use of the RTS to exploit it's function. I've seen JSR's before, followed by a list of pointers. The two bytes inbetween are most likely a pointer to the first in the list, which in this case is the "No Use" option. So in this case, the JSR must actually work as a JMP, but the RTS is the pointer in which to return. Basically a way to make an indirect JMP, but to save space. This case does not need to use an X or Y value, nor does it need to access a large array of pointers. Both examples are actually directly connected, as the pointers in the list lead to the RTS.

optomon
Posted on 09-06-08 06:34 AM Link | Quote | ID: 89965


Leever
Level: 33

Posts: 108/198
EXP: 220473
Next: 8706

Since: 03-05-07
From: Vancouver, WA

Last post: 2457 days
Last view: 2045 days
I'll admit, I still don't understand the logic of a lot of coding techniques I've come across in games or why they work the way they do. I just know what they do. I couldn't tell you how a stack works or even what a stack is. Is this pretty much how everyone does stuff?

Trax
Posted on 09-06-08 08:23 AM Link | Quote | ID: 89974


Yellow Stalfos
Level: 71

Posts: 499/1145
EXP: 3035781
Next: 131333

Since: 07-06-07
From: Québec

Last post: 3627 days
Last view: 2879 days
Everyone must start at the very beginning, anyways. But doing everything in the black doesn't help. When you don't know how something works, you can hardly make changes to it without breaking everything. So the exact uderstanding comes handy when you want to actually hack the code and modify the game's behavior...

A stack is exactly what it's called. Like a stack of plates. But instead of plates, it's bytes. You push values on the top, and take back the values later. It's a system of the type "first in, last out". When you add a plate on the stack, you must put it on top, you can't "slide" it in between other plates. And when you want to take a plate from the stack, you have to take the one on the top...

optomon
Posted on 09-06-08 09:48 AM (rev. 2 of 09-06-08 09:50 AM) Link | Quote | ID: 89987


Leever
Level: 33

Posts: 109/198
EXP: 220473
Next: 8706

Since: 03-05-07
From: Vancouver, WA

Last post: 2457 days
Last view: 2045 days
The plate analogy is good, but it doesn't tell me exactly what it is. Is it just a register (or something) used to temporarily store bytes when you need them? So if an RTS is sneaking the original location of the address right after the JSR location from the stack... would a single PHA or PLA before the RTS corrupt the return address that would be pulled from the stack?

EDIT: While we're on the subject of Guardian Legend, what are you doing to the game exactly Jigglysaint? If anyone's interested in a Guardian Legend hack it is definitely me.

Kawa
Posted on 09-06-08 09:54 AM Link | Quote | ID: 89988


CHIKKN NI A BAAZZKIT!!!
80's Cheerilee is best pony
Level: 138

Posts: 1193/5344
EXP: 30944726
Next: 718255

Since: 02-20-07
From: The Netherlands

Last post: 4498 days
Last view: 2633 days
Stack's usually a part of regular memory. Often enough it starts at the highest possible address and works down. There's usually a matching register (marked SP for Stack Pointer) that determines how deep the stack currently goes.

I prefer the stack of papers analogy, but plates work too.

____________________
Wife make lunch - Shampoo
Opera - give it a spin
Spare some of your free time?
<GreyMaria> I walked around the Lake so many goddamn times that my sex drive was brutally murdered
Kawa rocks — byuu

Jigglysaint
Posted on 09-06-08 09:29 PM Link | Quote | ID: 90005


Red Paragoomba
Level: 20

Posts: 30/62
EXP: 38539
Next: 3900

Since: 04-04-07

Last post: 4617 days
Last view: 2354 days
Posted by optomon
The plate analogy is good, but it doesn't tell me exactly what it is. Is it just a register (or something) used to temporarily store bytes when you need them? So if an RTS is sneaking the original location of the address right after the JSR location from the stack... would a single PHA or PLA before the RTS corrupt the return address that would be pulled from the stack?

EDIT: While we're on the subject of Guardian Legend, what are you doing to the game exactly Jigglysaint? If anyone's interested in a Guardian Legend hack it is definitely me.


Well truth be told I did create a hack a while ago, but I never got around to finishing it. The overall labyrnth is done, and all items are obtainable, but other room interiors were not added. That's a shame because I wanted to do some creative things with the interiors. Currently I am checking to see how things are coded so I can made some changes to things like weapons and corridor seals. So far I made the Saber weapon spin arround instead of stay straight(except in corridors), and I've discovered how the game handles the 4th seal. The only problem is there is little to no space to add new code, and even so, the passwords would not be able to hold any additional information, such as new upgrades. Seriously though, if anybody is interested in making a TGL hack, contact me because I've got almost all the data, save that for the Corridors.

Hamtaro126
Posted on 09-06-08 10:00 PM Link | Quote | ID: 90006


Cheep-cheep
Level: 33

Posts: 88/194
EXP: 212837
Next: 16342

Since: 05-02-07
From: Shelton, WA

Last post: 2472 days
Last view: 2315 days
Posted by smkdan

It's possible that the game wants the address, in which case you could do a JSR and a couple of PLA instructions, followed by adding 1 to the pair if need be. One would need to examine the code, primarily after the JSR, to understand what it's doing.


I know SMW does this a fair bit and that metroid disassembly on RHDN does this too.

CODE_00C593:        A5 71         LDA RAM_MarioAnimation    
CODE_00C595: 22 DF 86 00 JSL.L ExecutePtr

AnimationSeqPtr: 68 CC .dw ResetAni ; 0 - Reset
29 D1 .dw PowerDownAni ; 1 - Power down
47 D1 .dw MushroomAni ; 2 - Mushroom power up
5F D1 .dw CapeAni ; 3 - Cape power up
6F D1 .dw FlowerAni ; 4 - Flower power up
97 D1 .dw DoorPipeAni ; 5 - Door/Horizontal pipe exit
03 D2 .dw VertPipeAni ; 6 - Vertical pipe exit
87 D2 .dw PipeCannonAni ; 7 - Shot out of diagonal pipe
FD C7 .dw YoshiWingsAni ; 8 - Yoshi wings exit
B6 D0 .dw MarioDeathAni ; 9 - Mario Death
70 C8 .dw EnterCastleAni ; A - Enter Castle
B5 C5 .dw UnknownAniB ; B - freeze forever
E7 C6 .dw UnknownAniC ; C - random movement??
92 C5 .dw Return00C592 ; D - freeze forever


By placing pointer table right after the JSL/JSR, the routine that is being 'called' can pull the return address off the stack, add 1 and treat it as a pointer to the jump table which in this case is indexed by the value in A. This may be relevant considering you said that there's a pointer list after the JSR in the game.


Super Mario Brothers 1 does this too, It has already been disassembled by Doppleganger of NESDEV forums. And it is in Romhacking.Net under the documents section with the name SMBDIS.

____________________
Mah boi, romhacking is what all true warriors strive for!

I wonder what's for dinner?

Trax
Posted on 09-07-08 03:22 AM Link | Quote | ID: 90029


Yellow Stalfos
Level: 71

Posts: 507/1145
EXP: 3035781
Next: 131333

Since: 07-06-07
From: Québec

Last post: 3627 days
Last view: 2879 days
The stack is userful for functions embedding. It's a way the program "remembers" what it was doing when another function is called. Like Kawa said, it's a part of memory. On the NES, it goes from 0x1FF down to 0x100 (correct me if I'm wrong). Suppose you have functions A B C. In pseudo-pseudo-code, it would go like that:

- Execute A.
- Halfway in A, I must do B, so I need to remember my current position in the program, so I can come back later.
- Push current position to the stack.
- Execute B.
- Halfway in B, I must do C, so I push my position on the stack again.
- Execute C.
- When C exits, pull back the last position and go on.
- Pull and continue with B function.
- When B exits, pull back again.
- Go on with A.
- Etc...

In plain language, here's how JSR works:

- Add 3 to the program counter
- Push the least significant byte of the current PC (Program Counter) on the stack
- Push the most significant byte of the current PC (Program Counter) on the stack
- Jump to the address stated by the operand.

Example:
E212: 20 34FC    JSR $FC34
- Push the value E2 on the stack
- Push the value 15 on the stack
- Jump to $FC34

And how RTS works:

- Pull value from stack and set it as the most significant byte of the PC
- Pull value from stack and set it as the least significant byte of the PC
- Go on with the resulting PC

When the $FC34 function hits a RTS, the PC is set to $E215 and the program goes on...


Main - ROM Hacking - I've come accross a few interesting 6502 ASM things... New thread | New reply

Acmlmboard 2.1+4δ (2023-01-15)
© 2005-2023 Acmlm, blackhole89, Xkeeper et al.

Page rendered in 0.026 seconds. (341KB of memory used)
MySQL - queries: 87, rows: 120/120, time: 0.018 seconds.