Author [EN] [PL] [ES] [PT] [IT] [DE] [FR] [NL] [TR] [SR] [AR] [RU] [ID] Topic: Theou Aegis' Rookie Guide To 6502 ASM Reading  (Read 18043 times)

0 Members and 1 Guest are viewing this topic.

Offline Inccubus

  • Wannabe Great Old One
  • Master Hunter
  • *****
  • Posts: 3265
  • Gender: Male
  • Warrior
  • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. SuperOld Dungeonite: Members who have been around since the oldOLD days. Permanent Resident: Seems to always be around to post/reply.
    • Awards
  • Favorite Game: Vampire Killer (MSX)
  • Likes:
Re: Theou Aegis' Rookie Guide To 6502 ASM Reading
« Reply #15 on: August 25, 2012, 11:34:20 PM »
0
Hells yeah!!  ;D
That's like the most important thing that the CV3 hacking community needs.
Having control of how the stages are laid out and how long they are will allow a lot of creative stage design for new hacks.
"Stuff and things."

Offline TheouAegis

  • Amateur Auteur of GMvania
  • Master Hunter
  • *****
  • Posts: 1860
  • Gender: Male
  • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. The Great Defender will always defend the object of his or her fandom. Hack Master makes creations out of CV parts. (S)he makes Dr. Frankenstein proud.
    • GMvania Developer's Blog
    • Awards
  • Likes:
Re: Theou Aegis' Rookie Guide To 6502 ASM Reading
« Reply #16 on: August 26, 2012, 07:49:57 AM »
0
Ugh. I have my work cut out for me today...

So it turns out the tile maps aren't predefined in the ROM. That's a good thing, since it keeps ROM size very, very low. Unfortunately, that means I have to study the stage generation script and figure out how the tile maps are generated. I hain't excited about it because at the same time the name tables and PPU are being written to and they just cause more numbers to get tossed around. OH well, I already have my theory on how it's done (a very small, specific subset of tiles), so it shouldn't be too rough .
Your mom has had more floppies put in her than a Commodore 64!


Follow my lack of progress on my game at my blog:
http://gmvania.blogspot.com

Offline TheouAegis

  • Amateur Auteur of GMvania
  • Master Hunter
  • *****
  • Posts: 1860
  • Gender: Male
  • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. The Great Defender will always defend the object of his or her fandom. Hack Master makes creations out of CV parts. (S)he makes Dr. Frankenstein proud.
    • GMvania Developer's Blog
    • Awards
  • Likes:
Re: Theou Aegis' Rookie Guide To 6502 ASM Reading
« Reply #17 on: August 27, 2012, 05:58:47 AM »
0
Ok, I really do have multiple threads about the same thing. :D

Like Ippolito Rosellini to Jean-Francois Champollion and like Champollion to Thomas Young, building upon the efforts of those before me, I think I have stumbled on part of the level map for CV3.

When I woke up this morning I looked at my screen and noticed a pattern in the hex editor that looked vaguely familiar, so I went back to my notes and saw a similar pattern there. Delving further, I looked in the PRG-ROM for what I assumed was a RAM offset that I was looking at. I traced that PRG-ROM address back to its corresponding address in the ROM and noticed I had that same address in my notes -- the scrolling definitions for vertical stages!

This in and of itself isn't that great of a discovery because there's one significant problem: Konami didn't code a simple level map, it's more like a cyphered treasure map. I still need to decipher it. The problem is how rooms are laid out. You have three variables: stage, block, and room. When you walk through a door, block gets increased by 1. When you beat a boss then walk down the next stairs, stage gets increased. The room variable isn't so simple. If you walk UP stairs, room gets increased by 1. If you walk through a door, it gets set according to some variable that gets loaded into the memory, which in turn also sets another variable that I have yet to figure out what it does. If you walk DOWN stairs, room gets decreased by 1, but if room was already 0 it gets set to 1. Problem is, many rooms with downward stairs aren't set like that and so that little function isn't needed most of the time, I think. And I still haven't figured out how that stair in the Black Forest warps you from block 1 to block 2.

So what this all means is the values stored at the specific addresses holding the vertical scroll values, which themselves appear to be in a sequential format, aren't referenced sequentially but instead by a roundabout means which suggests that the actual level map is handled similarly. I found another map right above the vertical scroll map that I will have to look at this week.
Your mom has had more floppies put in her than a Commodore 64!


Follow my lack of progress on my game at my blog:
http://gmvania.blogspot.com

Offline Inccubus

  • Wannabe Great Old One
  • Master Hunter
  • *****
  • Posts: 3265
  • Gender: Male
  • Warrior
  • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. SuperOld Dungeonite: Members who have been around since the oldOLD days. Permanent Resident: Seems to always be around to post/reply.
    • Awards
  • Favorite Game: Vampire Killer (MSX)
  • Likes:
Re: Theou Aegis' Rookie Guide To 6502 ASM Reading
« Reply #18 on: August 27, 2012, 07:11:19 AM »
0
I'm fairly confident that the funky forest stairs are hard coded since there's nothing else like them anywhere in the rest of the game that I know of.

On the subject of the convoluted shit-storm they decided to use for level layouts... That is exactly why no one has ever done a really extensive hack of CV3. There was one hack for CV1 that was able to mess with the layouts a little, but that's the farthest anyone ever got to my knowledge.
"Stuff and things."

Offline TheouAegis

  • Amateur Auteur of GMvania
  • Master Hunter
  • *****
  • Posts: 1860
  • Gender: Male
  • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. The Great Defender will always defend the object of his or her fandom. Hack Master makes creations out of CV parts. (S)he makes Dr. Frankenstein proud.
    • GMvania Developer's Blog
    • Awards
  • Likes:
Re: Theou Aegis' Rookie Guide To 6502 ASM Reading
« Reply #19 on: September 01, 2012, 01:26:03 PM »
0
Almost done cracking the doors. It took me a while because it wasn't registering in my mind what RAM addresses $0053 and $0054 were. Once I figured out that was view_xview, I cracked the door code. The author of reVamp said you can't change which side of the room the doors are on. Not true. It's as simple as 0 for left and 1 for right. I changed the door in Stage 1-01:0 (starting room) to the left side of the room.

Before you get too giddy with anticipation, it's not quite so simple. Konami stunted game modding by making their code somewhat efficient. There are a very limited number of doors allowed. And you can't have doors on both sides of the room, only on one side. This isn't Simon's Quest.
Your mom has had more floppies put in her than a Commodore 64!


Follow my lack of progress on my game at my blog:
http://gmvania.blogspot.com

Offline Inccubus

  • Wannabe Great Old One
  • Master Hunter
  • *****
  • Posts: 3265
  • Gender: Male
  • Warrior
  • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. SuperOld Dungeonite: Members who have been around since the oldOLD days. Permanent Resident: Seems to always be around to post/reply.
    • Awards
  • Favorite Game: Vampire Killer (MSX)
  • Likes:
Re: Theou Aegis' Rookie Guide To 6502 ASM Reading
« Reply #20 on: September 01, 2012, 09:12:34 PM »
0
It's not surprising that it's set up like that. After all if it wasn't there would be no need for the duplicate rooms in the City Clocktower. BTW, I call it the 'City Clocktower' because it isn't the traditional one within the castle and it's on the outskirts of the town. That never made sense to me. Why would you build a clocktower OUTSIDE your city limits?

Anyway, good job on that, dude. The more actual code you figure out, the better your engine will be. Right now I'm developing a platformer engine based on a document I found that details the physics code of SMB1 & SMB3. I hope to pretty much blow every other GM SMB Engine outta the water with this, plus I'll probably end up using it for many of my own projects, too.
« Last Edit: September 01, 2012, 09:15:33 PM by Inccubus »
"Stuff and things."

Offline TheouAegis

  • Amateur Auteur of GMvania
  • Master Hunter
  • *****
  • Posts: 1860
  • Gender: Male
  • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. The Great Defender will always defend the object of his or her fandom. Hack Master makes creations out of CV parts. (S)he makes Dr. Frankenstein proud.
    • GMvania Developer's Blog
    • Awards
  • Likes:
Theou Aegis' Rookie Guide To 6502 ASM Reading, Parte Trois
« Reply #21 on: September 01, 2012, 11:30:58 PM »
0
In the last lesson, we isolated the Trevor's horizontal and vertical movement codes. We will pick up where we left off -- isolating changes in address $0520.

Disable all breakpoints and run the game so Trevor finishes his jump. Change the $041C ECRW- breakpoint to instead watch $0520. Delete the conditions, since they won't apply to $0520. Enable the breakpoint and make Trevor jump. The debugger immediately shows the following result:

Code: [Select]
0E:98E6:9D 20 05  STA $0520,X @ $0520 = #$00
0E:98E9:FE D8 05  INC $05D8,X @ $05D8 = #$09
0E:98EC:60        RTS

That's a bit short and doesn't tell us much. Well, not yet. First, look at the registers. The Accumulator is set to #$FB, X is #$00 and Y is #$09.

First, let's analyze the Accumulator. Its value is greater than #$80. The Negative bit in the status register isn't set currently, but we know that #$FB is either 251 or -5, depending on whether it's handled as an unsigned or signed byte. However, even if it's treated as an unsigned byte, the Negative bit should still be set. It's not, so that means something important happened just prior to $98E6 was handled.

There is another clue that something significant just occurred. The Y register is set. We can expect the X register to be set (even though here it isn't) because that typically handles RAM offsets for instances (Trevor is X:#$00, enemy 1 is X:#$01, enemy 2 is X:#$02, and so on). The Y register is typically only set when temporarily housing accumulator values or handling offsets in the PRG-ROM.

We need to see more of the PRG-ROM if we want to find any significant code that lead up to this breakpoint. Scrolling up through the debugger to the next RTS call reveals the following:

Code: [Select]
0E:98C6:AD 65 05  LDA $0565 = #$08
0E:98C9:C9 26     CMP #$26
0E:98CB:F0 CC     BEQ $9899
0E:98CD:A2 00     LDX #$00
0E:98CF:A9 00     LDA #$00
0E:98D1:9D 37 05  STA $0537,X @ $0537 = #$00
0E:98D4:9D DB 04  STA $04DB,X @ $04DB = #$00
0E:98D7:BC D8 05  LDY $05D8,X @ $05D8 = #$09
0E:98DA:BD C1 05  LDA $05C1,X @ $05C1 = #$00
0E:98DD:D0 1C     BNE $98FB
0E:98DF:B9 7B 98  LDA $987B,Y @ $9884 = #$FB
0E:98E2:C9 81     CMP #$81
0E:98E4:F0 07     BEQ $98ED
0E:98E6:9D 20 05  STA $0520,X @ $0520 = #$00
0E:98E9:FE D8 05  INC $05D8,X @ $05D8 = #$09
0E:98EC:60        RTS

(NOTE: If you get a code that instead contains the routine STA $006B, it means you are in a vertical room. Move to a horizontal room and then try again.)

The first few lines is a simple comparison checking if $0565=#$26. We won't worry about it here, but this checks if Trevor's sprite is his knocked-back sprite (for when he's wounded). The next few lines simply set X to refer to Trevor's offsets and then initialize a few RAM addresses.

The Y register gets set to the value of $05D8. For now it's an obscure byte that gets increased at the end of this subroutine. You'll eventually find out it's the fall height counter used to determine if Trevor lands nimbly or awkwardly (characterized by a momentary stun upon landing).

The next line checks an unknown address, $05C1, and skips the rest of this code if the byte has been set. This is actually a very important address and we will return to it later. Anything that causes the game to skip an entire segment of code is probably worth looking into.

Now we're where we want to be. Notice the next line refers to an address located in the PRG-ROM with the Y register as an offset. We still don't know why Y is set to 9, but that's not important right now. These types of calls tell us a lot of relevant information beyond the scope of our current task, so let's analyze the one at hand.

LDA $987B,Y @ $9884 = #$FB

This code sets the Accumulator to the value at $9884 in the current bank, which is #$FB. This means $9884 doesn't actually contain any routine calls, it just stores a constant. How many other addresses around it store constants? According to this line, the list of this particular class of constants starts at $987B. The next line in the routine checks if the value loaded into the Accumulator is #$81, so we should look at the PRG-ROM range starting from $987B for any address with the value #$81.

Code: [Select]
0E:987B:80        UNDEFINED
0E:987C:FA        UNDEFINED
0E:987D:FA        UNDEFINED
0E:987E:FA        UNDEFINED
0E:987F:FA        UNDEFINED
0E:9880:FA        UNDEFINED
0E:9881:FB        UNDEFINED
0E:9882:FB        UNDEFINED
0E:9883:FB        UNDEFINED
0E:9884:FB        UNDEFINED
0E:9885:FB        UNDEFINED
0E:9886:FD FD FD  SBC $FDFD,X @ $FDFD = #$B1
0E:9889:FD FD FE  SBC $FEFD,X @ $FEFD = #$B6
0E:988C:FE FE FF  INC $FFFE,X @ $FFFE = #$F5
0E:988F:FF        UNDEFINED
0E:9890:FF        UNDEFINED
0E:9891:FF        UNDEFINED
0E:9892:00        BRK
0E:9893:FF        UNDEFINED
0E:9894:00        BRK
0E:9895:00        BRK
0E:9896:00        BRK
0E:9897:00        BRK
0E:9898:81

Whew! That's a big list and much of it is just repeated values. You're about to learn why I've called some of Konami's coding very inefficient.

If you actually measure out Trevor's movement in the game when he jumps, you'll discover his y-coordinate changes by -5, then -3, then -2, then -1, then 0, then -1, then 0 again, then it essentially reverses. Looking at $9884, we in fact see that same pattern. We've just discovered Trevor's vspeed for when he jumps. You'll notice there is no gravity or complex trigonometric function to calculate his vspeed. It's just a simple array of constants taking up a big (relatively speaking) chunk of memory.

There is one more useful tidbit we can garner from this section of code. Hold your mouse over the empty grey bar on the far left side of the Debugger near $987C. At the bottom you will see the word "Offset". The large hexadecimal number after that is the identical ROM address. In other words, if you want to permanently change Trevor's jumping pattern, that is the address in the ROM you would need to edit (but don't edit $987B or $9898, as the game uses those as specific markers).

The fall height gets increased at the end of the subroutine, which we can surmise will be applied to the Y register in order to increase the PRG-ROM offset for Trevor's vspeed. Click Run to skip ahead to the next reference of $0520. It's the vertical movement subroutine. We've already dealt with that, so click Run once again. As expected, it's the code we just analyzed. So now we know how Trevor jumps.

But what about that address we neglected earlier, $05C1? Let Trevor finish his jump routine, then change the breakpoint to watch for $05C1. Now make Trevor jump again.

Code: [Select]
0E:9624:A9 08     LDA #$08
0E:9626:8D 65 05  STA $0565 = #$08
0E:9629:A5 2A     LDA $002A = #$80
0E:962B:85 10     STA $0010 = #$80
0E:962D:A2 00     LDX #$00
0E:962F:A9 16     LDA #$16
0E:9631:9D 00 04  STA $0400,X @ $0400 = #$16
0E:9634:A9 00     LDA #$00
0E:9636:9D C1 05  STA $05C1,X @ $05C1 = #$01
0E:9639:A9 09     LDA #$09
0E:963B:9D D8 05  STA $05D8,X @ $05D8 = #$07
0E:963E:A5 10     LDA $0010 = #$80
0E:9640:4A        LSR
0E:9641:B0 08     BCS $964B
0E:9643:4A        LSR
0E:9644:B0 10     BCS $9656
0E:9646:A9 00     LDA #$00
0E:9648:A8        TAY
0E:9649:F0 14     BEQ $965F
0E:964B:A9 00     LDA #$00
0E:964D:9D A8 04  STA $04A8,X @ $04A8 = #$00
0E:9650:A9 01     LDA #$01
0E:9652:A0 00     LDY #$00
0E:9654:F0 09     BEQ $965F
0E:9656:A9 01     LDA #$01
0E:9658:9D A8 04  STA $04A8,X @ $04A8 = #$00
0E:965B:A9 FF     LDA #$FF
0E:965D:A0 00     LDY #$00
0E:965F:9D F2 04  STA $04F2,X @ $04F2 = #$00
0E:9662:98        TYA
0E:9663:9D 09 05  STA $0509,X @ $0509 = #$00
0E:9666:60        RTS

I went ahead and scrolled up into the earlier code for education's sake. At $9636 the game clears $05C1. The next line sets $05D8, which I said was the fall height, to #$09.

The next line loads the value of $0010 into the Accumulator. That's a kind of Zero Page reference I call Hacker Hell. Some addresses in the Zero Page store useful values, such as timers, hearts, score, and whatnot. Byte $0010 is not one of those useful addresses. It's still a useful address, just not out of context. No matter where you are in the PRG-ROM, some addresses in the Zero Page will hold the same value, but not this one. When dealing with the Zero Page, it's helpful to have a notepad handy so you can keep track of which values are loaded into it. Sometimes a PRG-ROM offset is loaded into the Zero Page, while other times it's something specific like the current instance's bounding box.

Back on track, we know what happens when $05C1 is #$00. We want to know when it changes and what happens in such cases. Change the breakpoint to $05C1 EC-W- and then run the game until the next breakpoint. Eventually you should reach this point:

Code: [Select]
0E:98ED:A9 00     LDA #$00
0E:98EF:9D 20 05  STA $0520,X @ $0520 = #$00
0E:98F2:DE D8 05  DEC $05D8,X @ $05D8 = #$1C
0E:98F5:A9 01     LDA #$01
0E:98F7:9D C1 05  STA $05C1,X @ $05C1 = #$00
0E:98FA:60        RTS

Short, sweet, and to the point. This is a great subroutine! Wait a second, though. Some of it looks a little familiar. Once again we're amending $05D8, but whereas last time the code increased it, this time it decreased it. Also, the address at the start of the subroutine looks familiar. If we scroll up a little farther, we'll find the branch call that sent us to this subroutine:

Code: [Select]
0E:98DF:B9 7B 98  LDA $987B,Y @ $9898 = #$81
0E:98E2:C9 81     CMP #$81
0E:98E4:F0 07     BEQ $98ED

That's the branching conditional from our very first code when we were tracing $0520! Now we know what the purpose of that #$81 was -- to set $05C1. Remember that first routine branched out if $05C1 was set, so change the breakpoint back to $05C1 ECRW- and click Run to jump straight to said conditional. Click Step Into a couple times to follow the branch.

Code: [Select]
0E:98FB:B9 7B 98  LDA $987B,Y @ $9897 = #$00
0E:98FE:C9 80     CMP #$80
0E:9900:F0 0C     BEQ $990E
0E:9902:DE D8 05  DEC $05D8,X @ $05D8 = #$1C
0E:9905:49 FF     EOR #$FF
0E:9907:18        CLC
0E:9908:69 01     ADC #$01
0E:990A:9D 20 05  STA $0520,X @ $0520 = #$00
0E:990D:60        RTS

This is a nice little subroutine for learning. We have our vspeed reference offset first. This time it branches on #$80. Looking back at Trevor's vspeed list, that's at $987B, or when $05D8 equals #$00. Said variable gets decreased, so we know eventually it will indeed likely reach #$00.

Now Konami does something fun. Well, it's fun if you don't know squat about working with bytes. They take Trevor's vspeed and EOR it with $FF. In other words, they invert it. Since his vspeed according to that array is always negative, this makes it positive. However, the result is 1 off from what you'd expect -- #$FB^#$FF does not equal #$05, but #$04. So they add #$01. This is how you retrieve the absolute value of a signed byte, but in this case it's just a straight inversion of vspeed. (Learning how to find the absolute value, though, helped immensely in cracking collision subroutines).



That's it for today's lesson.
Your mom has had more floppies put in her than a Commodore 64!


Follow my lack of progress on my game at my blog:
http://gmvania.blogspot.com

Offline TheouAegis

  • Amateur Auteur of GMvania
  • Master Hunter
  • *****
  • Posts: 1860
  • Gender: Male
  • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. The Great Defender will always defend the object of his or her fandom. Hack Master makes creations out of CV parts. (S)he makes Dr. Frankenstein proud.
    • GMvania Developer's Blog
    • Awards
  • Likes:
Re: Theou Aegis' Rookie Guide To 6502 ASM Reading
« Reply #22 on: September 02, 2012, 09:30:49 PM »
0
^
^
^
^

Enjoy the nice third part of my ASM reading/cracking tutorial above.

That said, I'm closer to cracking the room map. It's still very convoluted and driving me nuts. So many variables crammed so close together. Some look like RAM offsets and then end up being compressed data points. Other times it's not only a RAM offset but compressed data points as well. Figuring out those compressed data points is a significant part of the construct, though. And of course it all depends on four (I upped the count last night) tiny little variables:

Stage
Block
Subroom
Screen

Some codes will literally lead you through four different RAM offsets based on each of those.

LDA stage
ASL
TAY
LDA offset1,y
STA offset1a
INY
LDA offset1,y
STA offset1b
LDA block
ASL
TAY
LDA (offset1a),y
STA offset2a
INY
LDA (offset1a),y
STA offset2b
LDA subroom
ASL
TAY
LDA (offset2a),y
STA offset3a
INY
LDA (offset2a),y
STA offset3b
LDY screen
INY
INY
LDA (offset3a),y


In the words of Egon Spengler:
"Your mother!"
Your mom has had more floppies put in her than a Commodore 64!


Follow my lack of progress on my game at my blog:
http://gmvania.blogspot.com

Offline Inccubus

  • Wannabe Great Old One
  • Master Hunter
  • *****
  • Posts: 3265
  • Gender: Male
  • Warrior
  • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. SuperOld Dungeonite: Members who have been around since the oldOLD days. Permanent Resident: Seems to always be around to post/reply.
    • Awards
  • Favorite Game: Vampire Killer (MSX)
  • Likes:
Re: Theou Aegis' Rookie Guide To 6502 ASM Reading
« Reply #23 on: September 03, 2012, 12:46:51 PM »
0
LOL. And that is why we've never had realyy good CV hacks, only good fangames. ;)
"Stuff and things."

Offline TheouAegis

  • Amateur Auteur of GMvania
  • Master Hunter
  • *****
  • Posts: 1860
  • Gender: Male
  • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. The Great Defender will always defend the object of his or her fandom. Hack Master makes creations out of CV parts. (S)he makes Dr. Frankenstein proud.
    • GMvania Developer's Blog
    • Awards
  • Likes:
Adventures in NES Hacking (or How I Learned to Love the PC)
« Reply #24 on: September 05, 2012, 07:04:27 PM »
0
Adventures In NES Hacking
or How I Learned to Love the PC


Ok. The solids definitions are located at address XXXX. How did it get to that address? Let's scroll up. ... Hm. It's based on a single variable. Do I have a note for that one yet? ... Damn, no. Ok, let's scroll up and look for that variable getting set. Ok, dead-end. Search the RAM for the nearest reference to that dead-end. ... Success! Let's see where that address takes me. ... Crap, JSR hell. Fine, let's follow that JSR. ... Le'see, variables, variables, more variables. None of them the one I want. Ok then, breakpoint time! Set the breakpoint for that variable to get writ. And... run. Ok, gotta get to a new room. Walk up the stairs. Doo dee doo de doo. Yay! Variable writ! Hm. What lead up to that value? Ok, load the value from an offset RAM address. ... Wait. ...
LDA stage.
ASL.
TAY.

... Crap.

LDA SomeBigNumber,Y
STA $000A.

Oh hell no.

INY
LDA SomeBigNumber,Y.
STA $000B.

Oh god no, please no.

LDA block
ASL
TAY.
LDA $000A,Y.

Fffff---.

STA $0008.
LDA $000A,Y.

FFFFFUUUUUUUUU----!

STA $0009.
LDA room

YOUR MOTHER!

ASL
TAY
LDA $0008,Y

*cries*

BMI distantOffset

Huh? Ooh! Progress! Let's goto this offset now... ... ...

LDA stage
ASL
TYA

FUCK YOU AND YOUR WEE DOGGY TOO!
*makes dinner*
« Last Edit: September 05, 2012, 07:06:11 PM by TheouAegis »
Your mom has had more floppies put in her than a Commodore 64!


Follow my lack of progress on my game at my blog:
http://gmvania.blogspot.com

Offline Inccubus

  • Wannabe Great Old One
  • Master Hunter
  • *****
  • Posts: 3265
  • Gender: Male
  • Warrior
  • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. SuperOld Dungeonite: Members who have been around since the oldOLD days. Permanent Resident: Seems to always be around to post/reply.
    • Awards
  • Favorite Game: Vampire Killer (MSX)
  • Likes:
Re: Theou Aegis' Rookie Guide To 6502 ASM Reading
« Reply #25 on: September 06, 2012, 03:17:39 AM »
0
O_O

And that's why I never found the tile properties for the title screen.
"Stuff and things."

Offline TheouAegis

  • Amateur Auteur of GMvania
  • Master Hunter
  • *****
  • Posts: 1860
  • Gender: Male
  • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. The Great Defender will always defend the object of his or her fandom. Hack Master makes creations out of CV parts. (S)he makes Dr. Frankenstein proud.
    • GMvania Developer's Blog
    • Awards
  • Likes:
Re: Theou Aegis' Rookie Guide To 6502 ASM Reading
« Reply #26 on: September 06, 2012, 09:49:50 AM »
0
I did eventually figure out what said-variable was. I had to go to NESdev wiki to figure it out.

When a value is copied/stored to addresses $D000 thru $D003 or $E000 thru $E003 or $2007 or some other odd values that are unusually high, those are PPU references. $D000 thru $D003 are for the left side of the PPU (typically sprites), while $E000 thru $E003 are for the right side of the PPU, typically background tiles.

So yeah, figured out I was looking at the CHR select values. You can change those in reVamp.
Your mom has had more floppies put in her than a Commodore 64!


Follow my lack of progress on my game at my blog:
http://gmvania.blogspot.com

Offline Inccubus

  • Wannabe Great Old One
  • Master Hunter
  • *****
  • Posts: 3265
  • Gender: Male
  • Warrior
  • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. SuperOld Dungeonite: Members who have been around since the oldOLD days. Permanent Resident: Seems to always be around to post/reply.
    • Awards
  • Favorite Game: Vampire Killer (MSX)
  • Likes:
Re: Theou Aegis' Rookie Guide To 6502 ASM Reading
« Reply #27 on: September 06, 2012, 10:20:09 AM »
0
Nice. Good info to have.
"Stuff and things."

Offline TheouAegis

  • Amateur Auteur of GMvania
  • Master Hunter
  • *****
  • Posts: 1860
  • Gender: Male
  • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. The Great Defender will always defend the object of his or her fandom. Hack Master makes creations out of CV parts. (S)he makes Dr. Frankenstein proud.
    • GMvania Developer's Blog
    • Awards
  • Likes:
Re: Theou Aegis' Rookie Guide To 6502 ASM Reading
« Reply #28 on: September 09, 2012, 05:04:54 PM »
0
Another useful feature in FCEUX is the Trace Logger. When you're using the Debugger, you might have a hunch that some particular RAM address is responsible for some outcome, but when you try to set a break point for that address, you either get too many results or you're forced to scroll through page after page of jumps and branches. That's where the Trace Logger can help out. It has other uses, but it can make looking at pages of code much easier because it will only list the PRG-ROM addresses that are actually handled. Your mind won't go numb from all the extra code on the screen -- what you see in the trace log is the only code you actually need.

Load up the Debugger and set a break point to pause the code roughly where you want it. If you are going through a lot of breaks with that particular address, typically you want to find the first break after sprites get updated (easy to do if you have something that actually changes sprites or position every step on the screen at the time). Now load up the Trace Logger. Click the radio for logging to a file. Click the Browse button and choose a location and name for the file. Click Start Logging. Go back to the Debugger and click Run. The Trace Logger will record up to 10000 lines of code or until the next break point. When you reach the break point, click Stop Logging. Locate the log file you created and open it in a word processor other than NotePad. You can now view all the code that was processed without the clutter of the code that was branched or jumped over. Look through the log file and hopefully the code you want will be in it. If you don't want the registers included on the right side, you can turn those off in the Trace Logger before recording. Personally I like having that information readily accessible.

Sample Trace Log (actual code)
Code: [Select]
$936C:A9 02     LDA #$02                   A:00 X:16 Y:00 S:F3 P:nvUbdiZc
$936E:85 62     STA $0062 = #$02           A:02 X:16 Y:00 S:F3 P:nvUbdizc
$9370:AC 65 05  LDY $0565 = #$08           A:02 X:16 Y:00 S:F3 P:nvUbdizc
$9373:20 14 E8  JSR $E814                  A:02 X:16 Y:08 S:F3 P:nvUbdizc
$E814:C8        INY                        A:02 X:16 Y:08 S:F1 P:nvUbdizc
$E815:68        PLA                        A:02 X:16 Y:09 S:F1 P:nvUbdizc
$E816:85 00     STA $0000 = #$9C           A:75 X:16 Y:09 S:F2 P:nvUbdizc
$E818:68        PLA                        A:75 X:16 Y:09 S:F2 P:nvUbdizc
$E819:85 01     STA $0001 = #$F3           A:93 X:16 Y:09 S:F3 P:NvUbdizc
$E81B:B1 00     LDA ($00),Y @ $937E = #$77 A:93 X:16 Y:09 S:F3 P:NvUbdizc
$E81D:85 02     STA $0002 = #$31           A:77 X:16 Y:09 S:F3 P:nvUbdizc
$E81F:C8        INY                        A:77 X:16 Y:09 S:F3 P:nvUbdizc
$E820:B1 00     LDA ($00),Y @ $937F = #$97 A:77 X:16 Y:0A S:F3 P:nvUbdizc
$E822:85 03     STA $0003 = #$F5           A:97 X:16 Y:0A S:F3 P:NvUbdizc
$E824:6C 02 00  JMP ($0002) = $9777        A:97 X:16 Y:0A S:F3 P:NvUbdizc
$9777:A5 28     LDA $0028 = #$00           A:97 X:16 Y:0A S:F3 P:NvUbdizc
$9779:29 40     AND #$40                   A:00 X:16 Y:0A S:F3 P:nvUbdiZc
$977B:F0 26     BEQ $97A3                  A:00 X:16 Y:0A S:F3 P:nvUbdiZc
$97A3:20 95 83  JSR $8395                  A:00 X:16 Y:0A S:F3 P:nvUbdiZc
$8395:A5 7D     LDA $007D = #$00           A:00 X:16 Y:0A S:F1 P:nvUbdiZc
$8397:D0 0F     BNE $83A8                  A:00 X:16 Y:0A S:F1 P:nvUbdiZc
$8399:A2 F8     LDX #$F8                   A:00 X:16 Y:0A S:F1 P:nvUbdiZc
$839B:A9 00     LDA #$00                   A:00 X:F8 Y:0A S:F1 P:NvUbdizc
$839D:20 DE FC  JSR $FCDE                  A:00 X:F8 Y:0A S:F1 P:nvUbdiZc

And yes, that mess of code was actually useful for me. I was trying to figure out how to get to $8395, which is only when Trevor jumps. The break point was on $0565 ($565==#8). Since I didn't know which break point actually branched to where I needed to be, I started it farther back (you'll notice this excerpt doesn't start with a $0565 break point) then just stepped through the code until I got to $839D (which leads to a generic code checking for collisions with solid tiles). My previous attempts at tracing it got me nowhere because I kept overlooking all that relative addressing from $E814 onward.
« Last Edit: September 09, 2012, 05:13:26 PM by TheouAegis »
Your mom has had more floppies put in her than a Commodore 64!


Follow my lack of progress on my game at my blog:
http://gmvania.blogspot.com

Offline TheouAegis

  • Amateur Auteur of GMvania
  • Master Hunter
  • *****
  • Posts: 1860
  • Gender: Male
  • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. The Great Defender will always defend the object of his or her fandom. Hack Master makes creations out of CV parts. (S)he makes Dr. Frankenstein proud.
    • GMvania Developer's Blog
    • Awards
  • Likes:
Re: Theou Aegis' Rookie Guide To 6502 ASM Reading
« Reply #29 on: September 25, 2012, 10:49:46 PM »
0
I may have mentioned this earlier in this thread, but I feel I cannot stress enough the importance of pattern recognition when reading ASM, either as convenient acronyms or straight byte values. The important thing to remember is all address references in an NES game's ROM are indirect, even when by definition they're direct references. To clarify, in ASM a direct reference would be something like:

0E:8122 JSR $B332

What this looks like it's saying is "jump to the subroutine at address $B332 in bank 0x0E" and that is indeed what it is saying, but only insofar as the RAM is concerned. This does you little good when you're trying to work with the ROM unless the current RAM bank is 0x02 (the RAM addresses in bank 0x02 correspond directly to the same ROM addresses).

First you need to figure out which ROM address corresponds to 0x0E:B332. The easiest way is to locate it in the Debugger, hold the mouse to the left of the 0E, and look at the ROM offset that pops up at the bottom of the Debugger. Or you take the bank and multiply it by $4000, subtract $8000, then add the RAM address (in other words, [bank-2] * $4000 + address). However, NES games have a header in the ROM 16 bytes long, so you will need to add $10 to find the real ROM address.

Now, going back to what I said about pattern recognition. Suppose you're skimming through the byte values of the ROM and you see something like this:
0x029290 02 02 02 02 02 02 01 01 01 02 06 01 01 02 02 02
0x0292A0 02 02 06 10 0A 02 02 20 03 02 01 02 02 02 02 02
0x0292B0 06 06 7F 02 02 02 02 02 02 02 02 02 02 02 CC 92
0x0292C0 D4 92 E0 92 EA 92 F4 92 FA 92 02 93 08 93 16 93
0x0292D0 F4 9A F8 9A 06 9B 0C 9B 12 9B 1A 9B 20 93 22 93
0x0292E0 2A 93 2E 93 30 93 36 93 3C 93 42 93 48 93 4E 93
0x0292F0 54 93 58 93 5A 93 5E 93 64 93 68 93 6E 93 72 93

Odds are your eyes were drawn immediately to the string of repeating $02 values. Without analyzing the surrounding values and without looking up the referring ASM that maps to those bytes, we can at least surmise that the first half of this code snippet is a definition table. In other words, Each of those $02 or $01 or $06 most likely defines a specific variable.

That's one form of pattern recognition that's useful in reading ASM, but there is an even more important form. Look at the second half of that code snippet. Do you see the pattern there? Every other byte is $92 or $93 or $9A or $9B, while the bytes in between are different but with each one greater than the previous. Being able to spot these kinds of patterns will making ROM hacking much easier. These are what I refer to as map tables or index tables. Each pair of bytes is actually a direct RAM reference, used to redirect the CPU to a different address in the RAM.

But this code wasn't read from the RAM, it was read from the ROM. To see where each index maps to, you'll need to calculate the ROM offset. You can take a shortcut in this situation, though. The addresses referenced in a map table will almost always be within $1000 bytes from the current ROM address. If you pay close attention, you'll notice in this particular situation, the ROM address contains $92 just like some of the values in the map table. That's a good sign that this map table doesn't reference very far ahead.

Reading a map table is actually quite simple. Find the lowest byte that would be part of the map table. There are a lot of alternating $92, so locate the first occurrence of $92. Look farther back for a $91. There are none in this case, so the first occurrence of $92 is the very beginning of this map table. Look up the value of the byte immediately before it. In this case, it's $CC. This means the map points to RAM address $92CC of the same bank (I don't think you can cross-reference banks, except for bank 0F, which is always loaded).

To find out which bank that actually is, divide the current ROM address by $4000. The result is $A, so the current bank is 0x0A. This is one of those special banks that lets you basically read the RAM addresses as though they were ROM addresses (offset by $20000 of course). Therefore the map indexes us to $292CC. But wait! You need to account for the ROM header, so add $10. Therefore, the first index in the map table points us to $292DC. As it turns out, that address is within this same snippet of code (which one would logically expect). Looking at that value and the values around it, clearly $292DC is the beginning of another map table indexing to $29330.

Every game handles map tables differently. Figuring out how the programmers cross-indexed their map tables will greatly help you locate valuable data in a ROM.
« Last Edit: September 25, 2012, 10:51:54 PM by TheouAegis »
Your mom has had more floppies put in her than a Commodore 64!


Follow my lack of progress on my game at my blog:
http://gmvania.blogspot.com

Tags: