(Link to AcmlmWiki) Offline: thank ||bass
Register | Login
Views: 13,040,846
Main | Memberlist | Active users | Calendar | Chat | Online users
Ranks | FAQ | ACS | Stats | Color Chart | Search | Photo album
05-04-24 11:17 PM
0 users currently in ROM Hacking.
Acmlm's Board - I3 Archive - ROM Hacking - Learn to Code with the ASM 6502 (how-to) New poll | |
Add to favorites | Next newer thread | Next older thread
User Post
Ice Ranger

Grizzo








Since: 11-24-05

Last post: 6294 days
Last view: 6285 days
Posted on 04-02-06 09:54 PM Link | Quote
I wanted to have a document from people new to ASM coding to read that fell along the lines of what rockman made since that was where I started to learn the basics. For what I wrote below, nothing I read spelled it out simply, so I attempted to do so.

For everyone that knows how to do this type of stuff, could you make sure this is correct information and even add, because this is how I do it now (I don't know how to do bank swaps yet so that's the reason I wrote it the way I did).

Thinking about it now, maybe I should have put this over on datacrystal instead, but I figured it would get more use from being here.

-------------------------------------
Copied and pasted from Notepad
---------------------------------------------

So you want to learn how to re-code the NES?

Step 1: pick up a 6502 microprocessor guide (Zophar's)
Step 2: get FCEUXD SP (for the purpose of this guide) (sp's site)
Step 3: find an NES rom that you want to check out (not going to get that from me)
Step 4: Figure out the RAM values for anything you might want to manipulate (datacrystal)
Step 5: Here's where the actual guide begins.

Like everyone else, as soon as I saw Mario Adventure, I thought, "I've got to learn to do that!" Well, it takes time, as everyone else says, you can't do something like this overnight. Start small and work your way up.

First off $8000 through $FFFF is CPU memory (where the code is stored for the ROM). This is where the ASM changes happen. If there is not any blank space or unused space, well, you're probably not in much luck and will have to overwrite code, which isn't a problem if your code is the same or less number of bytes as the original.

In most cases, the original code optimized the space changing several values at a time. An example of this is seen in Zelda 2 with the health and magic in the meters - Both are treated with the same value, not seperate values. This is where the JSR (20 in hex) comes in handy. Replace the code where the routine you want to change is (Finding code can be done through snapping the debugger when your RAM address between $0000 and $0800 is triggered).

Using the RAM viewer, search for unused space in the CPU memory located at $8000 - $FFFF (eg. FFs). When you find the place that is where your address you want to place your new code (make sure there is enough space and that it isn't data used in the game), keep track of the address, write it down if necessasry. For example, if you find a series of FFs at $D39A (keep in mind you want to be in an area of the game where your changes will take effect - actual gameplay, not the title screen), whenever you create the JSR at the old location where there wasn't enough room for your code, use JSR $D39A : 20 9A D3 (the bytes for the address are reversed, you'll get used to it).

Alright, now just put your code at the location $D39A. How do you do that? Since it is between the $8000 and $FFFF in CPU memory, right clicking will take you to that location in the ROM. Do that. Type in your new code using the 6502 microprocessor information (look around in the ROM debugger if you don't understand how the microprocessor works, it'll make sense after awhile of plugging in your RAM addresses using snapping with the debugger). After the new code is placed, put a RTN (60) at the end of the routine. This will take you back to the location of the JSR and the address. If you didn't use all of the bytes in this area that would affect that area (this is where knowing a lot of how the 6502 works helps) put NOP (EA) [No Operation] in place of the rest of the code.

This has worked for me in almost every case.

EDIT - Corrected the wording.

EDIT 2 - To CPU memory, not PRG memory


(edited by Ice Ranger on 04-05-06 02:26 PM)
(edited by Ice Ranger on 04-06-06 10:39 AM)
C:/xkas bio.asm
Compiled ASM code








Since: 11-17-05

Last post: 6285 days
Last view: 6284 days
Posted on 04-02-06 10:16 PM Link | Quote
I have a question, let say I expended my ROM and I want ROM adress 0xA123 to jump to a code I inserted in the expended area, how can I do that? for the SNES I could just use a JSL, but this oppcode don't seem to exist on the NES
Ice Ranger

Grizzo








Since: 11-24-05

Last post: 6294 days
Last view: 6285 days
Posted on 04-02-06 10:20 PM Link | Quote
Honestly, I know nothing about SNES assembly except stuff that is the exactly the same as NES. I have never attempted to look into it at all.

EDIT: The only type of bank swapping I've done doesn't refer to code but graphics so I can't really help there at all.


(edited by Ice Ranger on 04-02-06 09:21 PM)
Disch

Red Cheep-cheep


 





Since: 12-10-05

Last post: 6564 days
Last view: 6564 days
Posted on 04-02-06 10:40 PM Link | Quote
Originally posted by Ice Ranger
Using the RAM viewer, search for unused space in $8000 - $FFFF




GRAAAAH.

ROM != RAM!!!!

</pet peeve>

$8000-FFFF on the NES is ROM -- not RAM. RAM is only at $0000-07FF (And often at $6000-7FFF)

"CPU space", "Memory", "addressing space" -- all acceptable terms.

"RAM" means something else entirely. Using the term falsly will make it difficult for the student to distinguish between real RAM and fake "RAM" when the time comes for it to be necessary for them to make that distinction.

Originally posted by Bio
I have a question, let say I expended my ROM and I want ROM adress 0xA123 to jump to a code I inserted in the expended area, how can I do that?


This is actually a pretty involved process. The exact way to do it depends on the mapper used. But generally, the idea is you have to swap in the desired bank (by writing to mapper regs), jump to your code... then when your code returns, swap back in the original bank (so that if the game uses that bank, the right bank will be there when it tries to access it). I can give further details if you tell me the game.


(edited by Disch on 04-02-06 09:42 PM)
C:/xkas bio.asm
Compiled ASM code








Since: 11-17-05

Last post: 6285 days
Last view: 6284 days
Posted on 04-02-06 10:46 PM Link | Quote
the game is SMB3, mapper 4, PRG0
Disch

Red Cheep-cheep


 





Since: 12-10-05

Last post: 6564 days
Last view: 6564 days
Posted on 04-02-06 10:58 PM Link | Quote
Obligatory Link

SMB3 I believe has the alternative swapping setup ($8000-9FFF, $E000-FFFF fixed -- $A000-BFFF, $C000-DFFF swappable -- 'S' bit of $8000 set). This means you have your choice of putting the new bank in either the $A000-BFFF area or the $C000-DFFF area. I can't say with certainty, but it seems to me like the game is more likely to need the $C000 block in place (I know SMB3 uses the DMC, which pulls sample bytes from the $C000 area). Anyway -- in short, you're probably safer swapping out the $A000 area.

Now this other code you will probably want to do from OUTSIDE the $A000 block. Swapping out the $A000 block with code that's IN the $A000 block will probably work, but it's harder to maintain and is more error prone.

Anyway, swapping with MMC3 is a two part process. First you set the swap mode with a write to $8000, then you write the page you want to swap to to $8001. So if you want to swap to page 4 (offset 0x08010 in the .nes file), you'd do something like the following:


LDA #$47
STA $8000 ; set swap mode to 8k @ $A000 ('S' bit set)
LDA #$04 ; page number -- page 4 in this example
STA $8001 ; swap!

JSR wherever_your_new_code_is


When that JSR returns, you'll probably want to swap $A000 back so that it has whatever was already in there before you messed with it... otherwise the game might jump there trying to do something and crash when you have it swapped to the wrong bank.


(edited by Disch on 04-02-06 09:58 PM)
JaSp

Shyguy








Since: 11-18-05
From: Paris, France

Last post: 6286 days
Last view: 6285 days
Posted on 04-03-06 12:28 PM Link | Quote
Here's the bank swapping routine from SMB3 explained by DahrkDaiz:
Originally posted by DahrkDaiz's notes
Bank swapping routine
$FC6F (0x3FC7F)
$FC6F:A9 46 LDA #$46
$FC71:8D 00 80 STA $8000 = #$00 ; Set up the $8000 register for $A000 swapping
$FC74:AD 1F 07 LDA $071F = #$00
$FC77:8D 01 80 STA $8001 = #$60 ; swap $A000 bank with value in 71F
$FC7A:A9 47 LDA #$47
$FC7C:8D 00 80 STA $8000 = #$00 ; Set up the $8000 register for $C000 swapping
$FC7F:AD 20 07 LDA $0720 = #$1A
$FC82:8D 01 80 STA $8001 = #$60 ; swap $A000 bank with value in 720
$FC85:60 RTS

You'll surely save a lot of bytes swapping with this routine (and trust me, bytes are very precious in NES hacking; well actually, not so precious if you expand the ROM of course )
Disch

Red Cheep-cheep


 





Since: 12-10-05

Last post: 6564 days
Last view: 6564 days
Posted on 04-03-06 01:49 PM Link | Quote
Doh! Yeah you're totally right. It's best to utilize an existing swapping routine if possible.

So then you'd just need something like...


LDA $071F
PHA ; back up existing page
LDA desired_page_number
STA $071F

JSR $FC6F ; jump to swap routine

JSR your_expanded_code

PLA
STA $071F ;restore previous page
JSR $FC6F


Putting something like that in its own routine and JSRing to it whenver you want to do a cutsom swap is probably a good idea. And it's still rather large, unfortunately =/.
DahrkDaiz

Nipper Plant
U wan hax Mario?!








Since: 11-17-05

Last post: 6286 days
Last view: 6285 days
Posted on 04-03-06 10:24 PM Link | Quote
Well since you are using SMB3, I recommend this method:

LDA #$46/47
STA $8000
LDA #$bank_number
STA $8001
JSR $Your_new_routine

at the END of your new routine, use THIS
JMP $FC6F

Do NOT use an RTS

What this will do is go to the existing bank swapping routine and put what was originally there and at the end of that routine, you'll be placed right smack where you first entered out of the original bank. It saves on time and space, a nifty work around I came up with.
beneficii

Broom Hatter


 





Since: 11-18-05

Last post: 6288 days
Last view: 6284 days
Posted on 04-04-06 02:52 PM Link | Quote
The way I ended up learning how to code with the ASM 6502, in case anyone's interested, was by using a resource that took you step by step in creating a simple maze game; this allowed you to see a real practical application of the code, allowed you to familiarize yourself with the code, and be encouraged that you can do stuff with the code. Of course, I expanded on the concept by adding collisions and sprite animation and even a little bit of sound when I made my BKG ROM:

http://nesdev.parodius.com/bkg.zip

I can't seem to find the resource anymore, but perhaps one of us could make a resource like that to help out newbs. IMO, there should be such resources for other systems as well.

Hang in there!
Add to favorites | Next newer thread | Next older thread
Acmlm's Board - I3 Archive - ROM Hacking - Learn to Code with the ASM 6502 (how-to) |


ABII

Acmlmboard 1.92.999, 9/17/2006
©2000-2006 Acmlm, Emuz, Blades, Xkeeper

Page rendered in 0.019 seconds; used 400.52 kB (max 492.43 kB)