News: 11 March 2016 - Forum Rules
Current Moderators - DarkSol, KingMike, MathOnNapkins, Azkadellia, Danke

Author Topic: R4300i ASM : Adding new instructions to game code  (Read 3443 times)

CrashingThunder

  • Jr. Member
  • **
  • Posts: 14
    • View Profile
R4300i ASM : Adding new instructions to game code
« on: December 09, 2014, 12:53:09 am »
I've been dabbling around with Paper Mario 64's engine lately. I found the particular code that makes enemies fall asleep for a particular amount of turns. Here is the part that sets the status type (sleep = 06) and the amount of turns (03).

Code: [Select]
SB       S1, 0x0210(S0)
BNEZ   V0, 0x80266008
SB       S2, 0x0211(S0)

When this code is run, S1 = 06, and S2 = 03, so the enemy falls asleep for three turns. What I want to happen is that they get a different status effect (other than 06) and for a different amount of turns.

But, therein lies the problem. The SB instruction doesn't store immediate values to memory. It stores values within registers, in this case S1 and S2. S1 and S2 are loaded somewhere waayy back in the instructions being executed, most likely from other registers, which are loaded from other registers. The point is that I can't just store the value 06 to memory. It has to be a register, right? I looked through the instruction list and couldn't find an SBI instruction or something (Store Byte Immediate).

So what I think I need to do is to throw an extra instruction in there like ADDIU      S1, R0, 0x07
If I do this before the code above, it'll store 07 instead of 6, but I can't just throw another instruction into the code because it's all a fixed size!  :banghead:

As a side thought : I don't want to do this if I don't have to, but could I also write a quick subroutine somewhere in memory that isn't accessed at any time that does the code mentioned above? I feel like that could get hairy really quick.
« Last Edit: December 09, 2014, 02:53:16 am by CrashingThunder »

weissvulf

  • Sr. Member
  • ****
  • Posts: 324
  • Good news! An anomaly solved the enigma.
    • View Profile
Re: R4300i ASM : Adding new instructions to game code
« Reply #1 on: December 09, 2014, 04:16:57 am »
I advise you to trace back further in the routine to the source of the 0x6 in s1 and edit that.  Chances are the 06 value is stored somewhere in the data as-is (probably in the attack definition) and can be edited before it's loaded into s1.

You could also do exactly what you mention without much difficulty. Just remove some existing op and replace it with a jump to an unused area of RAM. In that area make a small routine to check if s1 = 6. If it does, modify it to the value you want. When all is done, enact the op(s) removed for the jump, and jump back to where you left off.

Of course, that may turn all sleep effects in the game into the new status.
« Last Edit: December 09, 2014, 04:24:46 am by weissvulf »

Zoinkity

  • Hero Member
  • *****
  • Posts: 562
    • View Profile
Re: R4300i ASM : Adding new instructions to game code
« Reply #2 on: December 09, 2014, 11:28:19 am »
A subroutine would take more space than just freeing a single line of code someplace.
Here's a better idea:  since those two are aligned writes, use a SH and set an unused variable to both values.

Since I can't look at the code without knowing the address, check that AT isn't used for anything important at the time.  Replace # with the value you want.  Ignore the +s, don't know the current address.
Code: [Select]
2401##03 ADDIU AT,R0,##03
1440++++ BNEZ V0,80266008
A6010210 SH AT,0210 (S0)
This also would sidetrack any further use of the values.  You'll get into trouble if they alter them however.

Also, remember that if you're changing code at runtime that unless an emulator is in interpret mode you will have to refresh the ASM cache.  With Nemu, set a BP on the opcode and step through it once to refresh.  With others, savestate and reload from the state.

CrashingThunder

  • Jr. Member
  • **
  • Posts: 14
    • View Profile
Re: R4300i ASM : Adding new instructions to game code
« Reply #3 on: December 09, 2014, 12:59:11 pm »
Thank you for your replies. I'll try looking further back in the instructions before trying what Zoinkity said. But I have a followup question regarding that:

If I'm backtracing through instructions, how do I actually know those instructions were executed? What if I got into a particular section of the code from a branch elsewhere? I'm using Nemu64's debugger, and there isn't any sort of "backstep" option.

Also, if I were to go the "make my own subroutine" route, how could I put my own code into RAM like weiissvulf said? The ROM file doesn't contain the RAM -- that's not in the cartridge, but inside of the console (virtually, in this case). I would have to branch somewhere else in ROM that isn't being used. How do I know for sure an area in memory is never used?
« Last Edit: December 09, 2014, 01:13:20 pm by CrashingThunder »

weissvulf

  • Sr. Member
  • ****
  • Posts: 324
  • Good news! An anomaly solved the enigma.
    • View Profile
Re: R4300i ASM : Adding new instructions to game code
« Reply #4 on: December 09, 2014, 03:15:50 pm »
If I'm backtracing through instructions, how do I actually know those instructions were executed?

Sometimes it's just guesswork and trial and error. If you're lucky, you'll see something like LB into S1 close above where you're working.

If not, you can usually find the beginning of the current routine by looking backwards until you find a JR op.  The JR most often marks the end of the routine above, and thus the beginning of your current routine. You can put a break there, and trace downward until you see where the 06 comes into play.

If you are tracing down from the beginning of the routine, you want to stay within the current routine so if you should fast-skip through any JAL ops you come to.

if I were to go the "make my own subroutine" route, how could I put my own code into RAM like weiissvulf said? The ROM file doesn't contain the RAM
Pardon my sloppy phrasing. I've been working on the PS1 too long. I just meant "into memory". Anywhere the 64 can execute code should be fine.

How do I know for sure an area in memory is never used?
There may be better ways, but I would look for debugging text. In PS1, you can often find a chunk of this text by actually searching for 'debug' and the area contains messages like
Code: [Select]
Access Denied. : invalid offset value align.....Access Denied. : system busy..
In a pinch you can also overwrite one of the game's system error messages text that isn't likely to ever be displayed.

STARWIN

  • Sr. Member
  • ****
  • Posts: 449
    • View Profile
Re: R4300i ASM : Adding new instructions to game code
« Reply #5 on: December 09, 2014, 04:47:33 pm »
I think the common case is that a routine is entered on the same spot always, and all relevant branches (local jumps) are within the routine itself. Remember that if the routine is nasty, there may be branches upwards too..

I recommend not treating nearby parts of the routine as unknown territory. Ideally you solve/reverse-engineer either the routine itself, or at least the nearby parts of it (backtrack relevant register causality only). If you read the code instruction-by-instruction backwards, and write it in sensible language for yourself, you'll understand what it does. It can be a rather mechanical process, you can treat each register operation simply as a definition of the register content in the next op, much like basic math equations.

You can try assuming that there won't be nasty jumps.. and it'll work until there are such  :P just to get you started. But even they usually make sense. You can also read from the beginning of the routine and write down what it does, but then you may do extra work because you don't know which registers have a causal relationship to S1 S2.

Intuitively things become clear when you can write the register equation without any registers (leaving memory references), or with routine parameter registers only.

Values 06 and 03 here sound like they would either originate from immediate instructions or from memory. If it is anything more complicated, you are basically deriving accurate game mechanics from the code. If there is a mechanics FAQ for this game that is correct, it may then give an idea of what the code is probably doing.

The game probably uses registers and not immediates there for a reason. I don't recommend inserting unconditional commands like in the first post there if the code is more generic than just for sleep status.. you should be able to change 06 without inserting anything (which is always nice).

CrashingThunder

  • Jr. Member
  • **
  • Posts: 14
    • View Profile
Re: R4300i ASM : Adding new instructions to game code
« Reply #6 on: December 09, 2014, 07:42:11 pm »
Thank you for the multitude of replies, they are appreciated. I know that there is a way to do this without modifying instructions, because I have seen others modify similar data to what I am doing. I'm just trying to do it myself so I am more capable of solving different problems in the future.

This probably deserves another thread entirely, but I'll throw this question out for fun :

How would one go about decoding the structure of the levels in Paper Mario 64? Obviously, level data for N64 games aren't modified too much (the only big editor out there that I know of is an SM64 editor). I have little to no idea how I would go about deducing the structure of the level. I do have access to where the levels are in the ROM, however, so I would know where to look.

(I may be way off base on this) In other words, say there was a level that consisted of a flat floor, and a cube in the center. How is the cube stored in memory? My guess is that the game stores a bunch of polygons (probably squares, maybe triangles) to represent the cube. Each polygon would have a certain amount of datapoints, probably the 3D coordinates for each corner and a texture to draw and maybe some other stuff like whether or not it is solid.

I guess I'm answering my own question here...aren't I. Does my description of how the game would store level data sound right? Is there somebody out there that has detailed knowledge on model formats for N64 games?

STARWIN

  • Sr. Member
  • ****
  • Posts: 449
    • View Profile
Re: R4300i ASM : Adding new instructions to game code
« Reply #7 on: December 10, 2014, 06:39:48 am »
I don't know. But I would assume that the graphical representation is separate from the logical object itself, so that you wouldn't have to explicitly think about polygons when modifying a level. I would store an object list per level, each object having its origin coordinate and angle in the list. If things in the game world are always aligned somehow, then it would also be possible that a tilemap with altitude / cubemap is used.

Uhm.. ideally, if you know where the level data (and only it) is, you would set a range of breakpoints there and then initiate a level load. And ideally the routine that "decodes" the data triggers the breakpoint. But that's a lot of ifs. When you interact with an object in the game, there has to be a causal relationship between your keypress and the part of memory that knows that the object is there. And that part of memory eventually has a causal relationship with the level data (when the level is loaded, for example). The obvious problem is that there are so many instructions executed between almost anything, that doing some things manually is impractical.

Zoinkity

  • Hero Member
  • *****
  • Posts: 562
    • View Profile
Re: R4300i ASM : Adding new instructions to game code
« Reply #8 on: December 10, 2014, 12:05:23 pm »
Other "big" N64 editors with stable releases are (shameless plug) the Goldeneye Setup Editor, the F-Zero X Track Editor, and Banjo's Backpack.  I know there's also editors for some of the other Rare titles in various states of completeness.  There's several Zelda editors like Utility of Time but to be honest I'm not sure which is farthest along.

Stages will be composed of several types of data.  There will be some sort of enemy and event layout with scripting, though was that in the editor already? 
Besides what was already mentioned, you can look backwards from the characters to see how they're set using the setup.  If there's a table used to load them you can be certain they're calling them using indicies.  When it breaks loading a character, follow the code forward, scrolling forward to the next JR RA, setting a breakpoint, then stepping forward to see what called this function.  You may have to do this several times, but it works surprisingly well.

Geometry is a different matter.
I've not worked on this title so I don't know if it falls in the 2% that don't use display lists.  Examples of these would be Eurocom titles (generate them at runtime) and some sprite-based games (Nintama Rintarou) that set texrects.

~98% of all N64 titles will store geometry in display lists.  This is a type of microcode that is run through the RSP to generate RDP draw commands.  There's different types, and the different types use different values for their instructions as well as some different commands.  Some of these are RDP commands passed directly through without modification

That said, all draw commands are effectively the same.  You are always drawing triangles--even texrect draws two triangles from four points.  Basic operation is you're loading a pointer to vertices, loading an image (twice actually), then assembling triangles using indices into the vertices you loaded.

[edit]
It's using one of the F3DEX series.
For now, here's the RDP commands (minus the low-level ones that aren't really used)
Code: [Select]
E4 rdp_texrect
Draws text in rectangles, especially fonts.  Macro creating two triads.
64bit command.  First 32 bits set size of tile, second 32 bits image alignment.
Some microcodes require the lower halves to be preceeded by an RSP_half left/right cmd.
upper word
00FFF000 upper left x
00000FFF upper left y

lower word
07000000 tile
00FFF000 lower right x
00000FFF lower right y

command 2
upper word
FFFF0000 upper left s
0000FFFF upper left t

lower word
FFFF0000 change in s per change in x (dsdx, as in delta-s delta-x)
0000FFFF dtdy
-----------
E5 rdp_texrectflip
Mirrored version of rdp_texrect
upper word
00FFF000 lower right x
00000FFF lower right y

lower word
07000000 tile
00FFF000 upper left x
00000FFF upper left y

command 2
upper word
FFFF0000 upper left t
0000FFFF upper left s

lower word
FFFF0000 change in s per change in x (dsdx, as in delta-s delta-x)
0000FFFF dtdy

--------------------------
E6 rdp_loadsync
Called after any data request to allow processor time to load data.
No options

--------------------------
E7 rdp_pipesync
The pipe is used as a generic term for peripheral interface or co-processor activity.
Waits for data to be loaded from ROM or RAM, or waits for co-processor to clear.
Display lists will almost always start with this command to ensure all previous display lists are completely executed. 
No options

--------------------------
E8 rdp_tilesync
Called after requesting tile data load.  Waits for processor activity to end.
No options

--------------------------
E9 rdp_fullsync
Combined effect of all syncs.  Not common, actually.
No options

--------------------------
EA rdp_setkeygb
Sets green + blue key components; typically used with EB: rdp_setkeyr below
upper word
00FFF000 Water: Green
00000FFF Water: Blue

lower word
FF000000 Cloud: Green
00FF0000 Sky: Green
0000FF00 Cloud: Blue
000000FF Sky: Blue

--------------------------
EB rdp_setkeyr
Sets red key component; typically used with EA: rdp_setkeygb above
upper word

lower word
0FFF0000 Water: Red
0000FF00 Cloud: Red
000000FF Sky: Red

--------------------------
EC rdp_setconvert
All values are 9 bits; note that K2 spans both upper and lower word
upper word
003FE000 k0
00001FF0 k1
0000000F k2 (upper)

lower word
F8000000 k2 (lower)
07FC0000 k3
0003FE00 k4
000001FF k5

--------------------------
ED rdp_setscissor
upper word
00FFF000 upper left x
00000FFF upper left y

lower word
02000000 interlace
01000000 odd when interlaced
00FFF000 lower right x
00000FFF lower right y

--------------------------
EE rdp_setprimdepth
lower word
FFFF0000 depth
0000FFFF change in depth

--------------------------
EF rdp_setothermode
upper word
00FFFFFF uses options from lower word of setothermode_h
0x0 blendmask
0x0000000F
0x4 alpha dither
0x00000000 pattern
0x00000010 no pattern
0x00000020 noise
0x00000030 disable
0x6 rgb dither
0x00000000 magic square
0x00000040 bayer
0x00000080 noise (enable in Perfect Dark)
0x000000C0 disable
0x8 combine key
0x00000000 none
0x00000100 key
0x9 texture convert
0x00000000 convert
0x00000A00 filter convert
0x00000C00 filter
0xC texture filter
0x00000000 point
0x00002000 bi-level interpretation
0x00003000 average
0xE texture look-up table (lut)
0x00000000 none
0x00008000 rgba16
0x0000C000 ia16
0x10 texture lod
0x00000000 tile
0x00010000 lod
0x11 texture detail
0x00000000 clamp
0x00020000 sharpen
0x00040000 detail
0x13 texture perspective
0x00000000 none
0x00080000 perspective
0x14 cycle type
0x00000000 1cycle
0x00100000 2cycle
0x00200000 copy
0x00300000 fill
0x16 colour dither
0x00000000 disable (note: Perfect Dark does not use this flag!)
0x00400000 enable
0x17 pipeline mode
0x00000000 n primitive
0x00800000 1 primitive

lower word
FFFFFFFF uses these options from lower word of setothermode_l
alpha compare 0x00000000 none
0x00000001 threshold
0x00000003 dither
depth source 0x00000000 pixel
0x00000004 primitive
render mode 0x00000008 antialias enable
0x00000010 depth compare
0x00000020 depth update
0x00000040 image read
0x00000080 clear on converge

--------------------------
F0 rdp_loadtlut
Used to load texture look-up tables (palettes); technically same format as the other load types
upper word
00FFF000 x0 (# entries)
00000FFF y0

lower word
07000000 tile
00FFF000 count/x1 (size in bytes of palette)
00000FFF palette start/y1

-

F2 rdp_settilesize
Sets size of image to be mapped.  Best if it actually matches the image's proportions.
Can be used to subdivide an image (ie. font) into multiple tiles.
Screwing up the mapping aspect can seriously damage the tile's appearance.
width=(lrs-uls)/4 + 1
height=(lrt-ult)/4 + 1

upper word
00FFF000 upper left s
00000FFF upper left t

lower word
07000000 tile
00FFF000 lower right s
00000FFF lower right t

-

F3 rdp_loadblock
Used to load blocks of either image or palette data directly to tmem without tile treatment.
upper word
00FFF000 upper left s
00000FFF upper left t

lower word
07000000 tile
00FFF000 lower right s
00000FFF lower right t

-

F4 rdp_loadtile
width= (lrs-uls)/4 + 1
height= (lrt-ult)/4 + 1

upper word
00FFF000 upper-left S
00000FFF upper-left T

lower word
07000000 tile
00FFF000 lower-right S
00000FFF lower-right T

-

F5 rdp_settile
Sets image into a location in tmem assuming given attibutes.  Must be set once for RSP and again for RDP.
ie. F5600600 00FD8360 would load a 48x48 intensity+alpha image with 4bit pixel data and clamping the corners to the s/t given in the point data.
If palettes are loaded, you can set the palette bits to swap palettes at runtime.

upper word
format 0x00000000 rgba
0x00200000 yuv
0x00400000 ci
0x00600000 ia
0x00800000 i
size 0x00000000 4bit
0x00080000 8bit
0x00100000 16bit
0x00180000 32bit
0x0003FE00 line
0x000001FF tmem

lower word
07000000 tile
00F00000 palette
00080000 clamp t
00040000 mirror t
0003C000 mask t
00003C00 shift t
00000200 clamp s
00000100 mirror s
000000F0 mask s
0000000F shift s

-

F6 rdp_fillrect
This is predominantly used when mapping text or "2D" objects
colour is set either by rdp_setblendcolour or rdp_setfillcolour
upper word
00FFC000 lower right x
00003000 lr x fraction
00000FFC lower right y
00000003 lr y fraction

lower word
00FFC000 upper left x
00003000 ul x fraction
00000FFC upper left y
00000003 ul y fraction

-

F7 rdp_setfillcolour
Sets the fill colour.  Uses 16bit colour
lower word
0000F800 red
000007C0 green
0000003E blue
00000001 alpha

-

F8 rdp_setfogcolour
Sets fog colour.  Uses 32bit colour
upper word
0000FF00 minimum level
000000FF level

lower word
rrggbbaa red, green, blue, alpha components

-

F9 rdp_setblendcolour
Sets blend colour.  Similar to rdp_setfillcolour, except 32bit colour
Used by the hardware blended when option selected.
upper word
0000FF00 minimum level
000000FF level

lower word
rrggbbaa red, green, blue, alpha components

-

FA rdp_setprimcolour
Sets the foreground colour applied to generated triads. 
Blends into background (enviroment) colour.
Many fonts, for instance, use I images blended colour(prim)->alpha(env)
upper word
0000FF00 minimum level
000000FF level

lower word
rrggbbaa red, green, blue, alpha components

-

FB rdp_setenvcolour
Sets background colour applied to generated triads.
If a IA image is used, the black is the enviroment colour, the white the primary colour.
upper word
0000FF00 minimum level
000000FF level

lower word
rrggbbaa

-

FC rdp_setcombine
upper word
00F00000 a0
000F8000 c0
00007000 Aa0
00000E00 Ac0
000001E0 a1
0000001F c1

lower word
F0000000 b0
0F000000 b1
00E00000 Aa1
001C0000 Ac1
00038000 d0
00007000 Ab0
00000E00 Ad0
000001C0 d1
00000038 Ab1
00000007 Ad1

0 combined
1 texel0
2 texel1
3 primitive
4 shade
5 enviroment
6 center
scale
1
7 combined alpha
8 texel0 alpha
9 texel1 alpha
A primitive alpha
B shade alpha
C enviroment alpha
D LOD fraction
E primitive LOD fraction
F K5
1F 0

alpha combiner:
0 combined
LOD fraction
1 texel0
2 texel1
3 primitive
4 shade
5 enviroment
6 primitive LOD fraction
1
7 0

-

FD rdp_settextureimage
Sets a texture.  Can also set a palette, screwy enough.
upper word
format 0x00000000 rgba
0x00200000 yuv
0x00400000 ci
0x00600000 ia
0x00800000 i
depth 0x00000000 4bit
0x00080000 8bit
0x00100000 16bit
0x00180000 32bit
0x00000FFF width-1

lower word
0f000000 segment (like 05 used for offsets)
00ffffff address or offset in file

-

FE rdp_setdepthimage
Used for depth compare and tiled for level of detail.  Rarely used.

upper word
format 0x00000000 rgba
0x00200000 yuv
0x00400000 ci
0x00600000 ia
0x00800000 i
size 0x00000000 4bit
0x00080000 8bit
0x00100000 16bit
0x00180000 32bit
0x00000FFF width-1

lower word
0f000000 segment (like 05 used for offsets)
00ffffff address or offset in file

-

FF rdp_setcolourimage
format 0x00000000 rgba
0x00200000 yuv
0x00400000 ci
0x00600000 ia
0x00800000 i
size 0x00000000 4bit
0x00080000 8bit
0x00100000 16bit
0x00180000 32bit
0x00000FFF width

lower word
0f000000 segment (like 05 used for offsets)
00ffffff address or offset in file

endDL is DF00000000000000, your tri commands are 05 and 06, and vertices will be loaded with 01.
« Last Edit: December 11, 2014, 11:45:44 am by Zoinkity »

CrashingThunder

  • Jr. Member
  • **
  • Posts: 14
    • View Profile
Re: R4300i ASM : Adding new instructions to game code
« Reply #9 on: December 10, 2014, 09:28:21 pm »
Well, that seems immensely complicated. I can't say I didn't expect that, however. Lots of good information you guys gave me, though, so thank you for that. I'm trying to decide on an aspect of the game I want to focus on and get somewhere with. If you've seen this post, Luigi1er is doing some great work on Paper Mario 64: http://www.romhacking.net/forum/index.php?topic=17948.0 ...

You can see that he's doing a lot of work in a variety of areas. And then there's also Origami64 by Skellux, which came out recently : https://www.youtube.com/watch?v=OtrXti801aY

I'm a fair (but finite) ways behind either of these two people, so I'm trying to think of something in the game more doable for someone of my knowledge and skills that also hasn't been done yet.

Zoinkity

  • Hero Member
  • *****
  • Posts: 562
    • View Profile
Re: R4300i ASM : Adding new instructions to game code
« Reply #10 on: December 11, 2014, 12:11:40 pm »
To be fair it's only really mindnumbingly complicated if you want things to look right ;*)
(If you are interested in the other, terribly long bit on how to read vertices and draw triads just say so.)

For practical purposes you only need to read a subset to really get interesting stuff out.  Here's a sample script from a project earlier this year that formatted stuff so Blender's .x importer could load it.  The pertinent parts are DLparse() and the class DX8.  It was canibalized from another project aimed at a different microcode.

Actually, these can be rather helpful for tracking things down.  Images will be loaded with FD commands, and the lower 32bits have either an offset or address for the image.  So, you can
  • Find images+palettes this way to extract them, and even figure out what format they are.
  • With an image track down the start of the object/block that uses it.

There's other ways to do that though.
Here's a suggestion for a useful project.  So far Origami64 has been treating everything like one massive block of data (as far as I can tell).  In reality the game consists of a bunch of blocks of data that can be loaded independently.  If you can figure out where all the blocks are, that's step one to figuring out what they all are.
In general, similar kinds of data (like all characters, or all stage data, etc.) will have offsets in one place.  Even if they hardcode them you can still search for one and look for other JALs to the function loading them.

^This thing right up here was what initially lead to us being able to make the GE setup editor. 

I know it's a bit complicated by how they have these short blocks before the sound files that manage what other blocks load. 
Also, SubDrag's been looking for somebody to make sense of the SBN sound archive format.  Got sidetracked, so not much to start you with:
Code: [Select]
SBN is an archive for multiple sound samples.  It's header is 0x40 large:
0x0 4 b'SBN '
0x4 4 total size of archive following header
0x10 4 offset to table (0x40)
0x14 4 #entries in table
0x18 4 offset to data following table
0x1C 4 offset to timestamp(?--long string with hex below)
0x24 4 offset to INIT table

table format: 8 each
0x0 4 offset to data
0x4 4
F0000000 type
0FFFFFFF size

types:
1 BGM
2 SEF
3 BK
4 MSEQ

INIT header size 0x20
0x0 4 b'INIT'
0x4 4
0x8 2 offset to entries
0xA 2 size of entries
0xC 2 offset to tbl
0xE 2 size of tbl
0x10 2 offset to shorts
0x12 2 size of shorts

CrashingThunder

  • Jr. Member
  • **
  • Posts: 14
    • View Profile
Re: R4300i ASM : Adding new instructions to game code
« Reply #11 on: December 11, 2014, 09:30:59 pm »
What do you mean exactly, by the fact that Origami64 treats the entire game as one block of data? He knows where specific parts of the code are. Also, if I'm understanding you correctly, the main categorization of the ROM map has already been underway by Luigi1er (which is awesome -- I've made full use of this information) : Scratch that, apparently the file doesn't exist anymore. Well, there was a fair amount of information about where things were stored (by a level-by-level basis) but it seems he either deleted the file or it was relocated.

Regardless, I'll look into that DL parser at some point, but I feel I may be treading a little too deep with that kind of stuff. At least at this point. I plan on utilizing my extra free time during the winter break to work on this kind of stuff.