+  RHDN Forum Archive
|-+  Romhacking
| |-+  ROM Hacking Discussion
| | |-+  trying to find level data in "lode runner" nes
Pages: [1] 2
Author Topic: trying to find level data in "lode runner" nes  (Read 2 times)
poliver
Guest
« on: January 30, 2008, 08:13:20 am »

i can't find level data in "lode runner" for nes  Embarrassed i have found level data in savestate and in PPU. but there's no signs of it in the original rom, well i can't see it...  Sad what should i do next?  Undecided\

Disch
Guest
« Reply #1 on: January 30, 2008, 09:05:00 am »

What I usually do is I find where the level data is loaded in RAM (since you can find it in a savestate -- try just running the ROM in FCEUXD and use the memory viewer.  Scope out addresses $0000-07FF and look for it there).  Once I find it in RAM, I set write breakpoints on that area, then start the tracer and get the game to load a level again.

Once it hits the write breakpoint, I can examine the tracelog to see where it's loading the data from in ROM -- as well as decipher any compression or unpacking algorithm it's doing.
poliver
Guest
« Reply #2 on: January 30, 2008, 09:35:58 am »

Tools - Hex Editor - View NES Memory right?

is PPU RAM?
« Last Edit: January 30, 2008, 09:48:09 am by poliver »
KingMike
Guest
« Reply #3 on: January 30, 2008, 10:09:39 am »

You'd have to see how it gets transferred from ROM to CPU RAM to PPU RAM.

You'd need to use breakpoints for PPU RAM.
Then when it writes, see where it's coming from (scroll up a few lines, you'll probably see a LDA statement, with an offset it's reading from ($0000-07FF = system RAM, $6000-7FFF = cart RAM (if present, but Lode Runner is such an old game I don't know if it uses it), $8000-FFFF = ROM). If you find a RAM address, clear the old breakpoint and set a new one for that address, reset the game and repeat the process) (LDA statements will always reference CPU RAM, since the CPU cannot directly access PPU RAM)
Disch
Guest
« Reply #4 on: January 30, 2008, 10:27:41 am »

Quote from: poliver on January 30, 2008, 09:35:58 am
Tools - Hex Editor - View NES Memory right?

Yes

Quote
is PPU RAM?

No, the PPU is the graphics processor.  Which is completely unimportant in so far as finding level data goes.  What you need to find is where in CPU memory (in FCEUXD:  "NES Memory") the level data sits.  It would have to exist somewhere, because the game would need to access it every time it needs to examine a new tile on the map for collision or other purposes (like for instance, whenever the player or an enemy moves.  So basically -- all the time).

RAM is readable/writable "workspace" that games use for keeping track of stuff.  In a game like Lode Runner, where the map can constantly change by you digging, it would need to have the map in RAM so that it would write to it / modify it as you play.  On the NES, RAM exists at addresses $0000-07FF

ROM is read-only memory -- it cannot be changed by the game as it runs, it can only be read/referenced.  Everything in your .nes file aside from the header is ROM (hence why they're called ROMs).  On the NES, ROM [usually] exists at addresses $8000-FFFF.

The game will copy the level from ROM to RAM once when the level is loaded.  What I would do to find the level data -- is I try to find where in RAM the game is putting its levels.  Once I know where in RAM it is, I can use tracelogs and write breakpoints to isolate the game code that loads the levels -- from there I can see where in ROM it's loading them from.

Though this method does require a bit of advanced knowledge (have to be able to understand the code -- so you'd need at least minimal 6502 comprehension)



This is not the only method of discovering level data -- it's just the only one I'm good at  =P.  Other, more traditional methods involve corruption and stuff which generally involves a lot of trial and error.


Anyway I'm bored so I'll look at this game to see if I can find level data.


--- apparently while I was typing KingMike replied ---

I don't mean to step on his toes here -- but like I say, the PPU and PPU RAM are completely unimportant for level data.  You do not need to find where the game is drawing tiles to the PPU unless you want to change how tiles are drawn (which is not what you're trying to do, from what I gather).

Stick to the CPU.  Everything you want to do is local to the CPU -- put the PPU out of your mind.



EDIT-

Yow -- looks like the level data is compressed and/or bitpacked to shit.  This will be a hard one to figure out for a beginner project.

- Level data is written to $0200-0387  (I think it stops at $0387) in RAM
- dunno where it's loaded from yet
- $C711 seems to be the start of the level 1 loading routine.

I'm analyzing it now.  More to come
« Last Edit: January 30, 2008, 11:10:47 am by Disch »
poliver
Guest
« Reply #5 on: January 30, 2008, 11:24:00 am »

wow...

 :'( why do all games that i touch are with some kinda crap that i can't handle Cheesy :laugh: :'(  :banghead:  Embarrassed
well, at least learning and understanding new stuff is enjoyable Cheesy
Disch
Guest
« Reply #6 on: January 30, 2008, 12:30:37 pm »

heh.. .yeah you picked a toughie.

I finally figured it out, I think.  I was thrown off a little bit because everything is bitpacked and there are no pointers.  Apparently the game loads every single level up to the level you're on to find the starting point.  Kind of a huge waste of CPU time, but that's probably why you have to wait a few seconds for each level to start.

Anyway level data starts at offset 0x02A88.  Though it's compressed with a pretty intricate RLE/go back and write over yourself/fill rows with crap/etc/etc block system -- and like I say everything it bitpacked, and there is no pointer table... so it will be a complete nightmare to try and edit any of it without a level editor... since to edit anything you'd have to de-bitpack every level, decompress the level you want to edit, then recompress the level, then re-bitpack every level.

On top of that, I don't know how it figures where to put the "goal" ladder once you collect all the gold.  There doesn't appear to be any indication of it in the level data unless I'm missing something...  maybe it has a special tile ID or something....

Anyway I'll outline the compression format and junk in a doc and then will submit it to the site.  More to come.

EDIT - oh blah -- yeah the goal is in the level data, I just didn't see it.  nm
« Last Edit: January 30, 2008, 12:51:40 pm by Disch »
poliver
Guest
« Reply #7 on: January 30, 2008, 01:04:43 pm »

Quote
de-bitpack every level, decompress the level you want to edit, then recompress the level, then re-bitpack every level

how to do it? what's a bitpack, some kinda compression format?

Quote
Anyway I'll outline the compression format and junk in a doc and then will submit it to the site.  More to come.

Yeay. i just recently started learning C Cheesy so my next goal is to figure out how to make an editor.
Disch
Guest
« Reply #8 on: January 30, 2008, 02:43:07 pm »

Hopefully this should answer all your questions:

http://disch.arc-nova.org/lodelevel.txt

Submitting to site now.
Neil
Guest
« Reply #9 on: January 30, 2008, 02:54:35 pm »

Approved
poliver
Guest
« Reply #10 on: January 30, 2008, 04:31:08 pm »

Whoa, it will take some time to understand this before i can use it. Shocked Thanks!!! :crazy: :beer:
Disch
Guest
« Reply #11 on: January 30, 2008, 05:38:23 pm »

I was half tempted to make an editor of my own just so I could call it "Lode Funner", because that'd be hilariously awesome.

But I was quickly reminded of how freaking boring editor creation is.  I wouldn't mind writing a decompressor/recompressor though -- that's the fun part  =D
Disch
Guest
« Reply #12 on: January 31, 2008, 11:27:30 pm »

UPDATE:

I fucked up.  I only documented half of block type 3  >_<

here's the actual routine (add $C000 to addresses on the left side):

Code:
; here if first fetched 2 bits were == 3

0000073A: 2060C8 JSR $C860   ; fetch another bit
0000073D: F00E BEQ $0E     ; if set
0000073F: A000 LDY #$00       ; loop 1C times
00000741: 2044C8 JSR $C844      ; fetch 3 bits
00000744: 9126 STA ($26),Y    ; output to ($26)
00000746: C8 INY
00000747: C01C CPY #$1C       ; increment and repeat
00000749: D0F6 BNE $F6        ; 3 new bits fetched each time
0000074B: F074 BEQ $74        ; $C7C1 when done
                                    ; if first fetched bit was clear
0000074D: A000 LDY #$00
0000074F: 202FC8 JSR $C82F   ; fetch 4 sets of 3 bits, store at B3,B4,B5,B6
00000752: C004 CPY #$04
00000754: D0F9 BNE $F9
00000756: A000 LDY #$00
00000758: 204EC8 JSR $C84E   ; fetch 2 bits
0000075B: AA TAX         ; use those 2 bits to index that LUT
0000075C: B5B3 LDA $B3,X
0000075E: 9126 STA ($26),Y ; output indexed data
00000760: C8 INY
00000761: C01C CPY #$1C    ; loop 1C times
00000763: D0F3 BNE $F3     ; each loop, fetch another 2 bits
00000765: F05A BEQ $5A     ; $C7C1 when done

An extra control bit is fetched at the start and it only behaves as it does in my doc if that bit is clear!  If that bit is set it's a different thing completely that I didn't document yet.  Sorry!

At any rate I will fix that and update shortly.

EDIT -- blah -- I even fucked up in this post!  corrected

EDITAGAIN:

http://disch.arc-nova.org/lodelevel.txt

updated v1.1 with correction

submitted to site.
« Last Edit: January 31, 2008, 11:50:51 pm by Disch »
Disch
Guest
« Reply #13 on: February 01, 2008, 02:22:18 pm »

badump

don't know whether or not this is a "worthy" bump, but I felt like showing off this screenshot:



Loading/editing/saving works.  But there are a few more things I want to get working before I release.

Weeeee
poliver
Guest
« Reply #14 on: February 01, 2008, 02:40:30 pm »

Weeeeee Shocked  :thumbsup: That's good work... I wanna make harddd levelzzzz, harder than championshit lode runner.

But, i also want to make a lode runner editor myself, not for the public maybe. I have to train my nes and programming skills!  Cheesy
Pages: [1] 2  


Powered by SMF 1.1.4 | SMF © 2006-2007, Simple Machines LLC