comprehensive SMB1 disassembly

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems.

Moderator: Moderators

User avatar
beneficii
Posts: 127
Joined: Tue Jul 12, 2005 4:37 pm

Post by beneficii »

doppelganger,

LOL, one more thing that could be an issue. At line 3525, I found something that could be an issue if you moved the code around. That dummy entry actually seemed like it was used. I found when I modularized it, I had the game freeze when there was looping. You should make sure that line 3525 references the code at line 3453 rather than putting a bare address. Adding the reference prevented the game from freezing. *

* The freezing occured in World 4-4.

Beyond this, there is probably not much else that is at issue. I'm writing a program the checks for non-label references to $8000-$FFFF range in the assembly source.
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

4-4? Does it also occur in 7-4?

To test all the data in the maze levels, you have to fail each checkpoint once then pass each section. Play the corresponding levels in Super Mario All-Stars to find the checkpoints.
User avatar
beneficii
Posts: 127
Joined: Tue Jul 12, 2005 4:37 pm

Post by beneficii »

tepples,

I'm just referring to his disassembly. I moved the code around, which caused problems with bare address references to the $8000-$ffff range, so I had to fix those.

doppelganger,

Another more complex one takes place at lines 645, 14421, and 14466. It's a bit more difficult to fix because the game does a weird piece of code. My solution was to comment out line 645, replace the SwimTileRepOffset on line 14421 with SwimTile+6, and add SwimTile: as a label to the beginning of line 14466. You may be able to come up with a better solution.

Anyway, here is the C source code to the program I wrote that checks for bare address references to the $8000-$ffff range (the 2 I recently posted were all it found aside from the bare address interrupt reference and the .org):

Code: Select all

#include <stdio.h>
#include <string.h>

#define MAX_SIZE    1001
#define MIN_CHECK   0x8000  /*in case checking FDS code*/
#define MAX_CHECK   0xffff  /*defaults to NES code type*/
#define CHARTEST(c) ((c==0) || (c==';'))

char *tonext(char *string) {
    while(isspace(*string))
        string++;
    return string;
}

int main(int argc, char **argv) {
char tokens[MAX_SIZE], token[MAX_SIZE];
char token2;
char *cur = NULL;
int linecount, othertoken, temp, cflag;
FILE *file = NULL;
    if(argc < 2) {
        printf("addrchk <asm-file>\n");
        return 0;
    }
    if(argc > 2) {
        printf("addrchk <asm-file>\n");
        perror("Too many parameters!\n");
        return 1;
    }
    file = fopen(argv[1], "rt");
    if(file==NULL) {
        perror("Error opening file!\n");
        return 2;
    }
    linecount = 0;
    while(!feof(file)&&!ferror(file)) {
        tokens[0] = token[0] = token2 = 0;
        cur = tokens;
        linecount++;
        if(fgets(cur, MAX_SIZE, file)==NULL) break;
        do {
            cflag = 1;
            cur = tonext(cur); /*get pointer to next non-whitespace*/
            if(CHARTEST(*cur)) break; /*if comment, end, whatever*/
            sscanf(cur, "%s", token);
            cur += temp = strlen(token); /*push pointer forward*/
            if(CHARTEST(token[temp-1])) break;
            cflag = 0;  /*passed all tests for line*/
        } while(token[temp-1]==':'||token[0]=='@'); /*while still label references*/
        if(cflag) continue;
        if(*tonext(cur)=='=') /*if assignment*/ cur = tonext(cur) + 1;
        do {
            cflag = 1;
            cur = tonext(cur);
            if(CHARTEST(*cur)) break;
            sscanf(cur, "%s", token);
            cur += temp = strlen(token);
            othertoken = 0;
            sscanf(token, "%c%X", &token2, &othertoken); /*get value if available*/
            if(token2!='$') continue; /*not hex address reference*/
            if((othertoken < MIN_CHECK) || (othertoken > MAX_CHECK)) continue;
            cflag = 0; /*passed all checks*/
            break;
        } while(token[temp-1]==','); /* while there is one more item to be read */
        if(cflag) continue;
        /*output if passed:*/
        printf("Line #%i:\n\t%s\n", linecount, tokens);
    }
    fclose(file);
    printf("%i rainu yonda\n", linecount);
    printf("Zubari owaru deshou!\n\n");
    return 0;
}

^_^
User avatar
beneficii
Posts: 127
Joined: Tue Jul 12, 2005 4:37 pm

Post by beneficii »

doppelganger,

Basically, I think that for now all the addressing issues making it difficult to modularize the disassembly have been found. I think from the way you wrote the disassembly, the program should have found every instance where there was a bare address that was 0x8000 < x < 0x10000.

So, good job! :D
doppelganger
Posts: 183
Joined: Tue Apr 05, 2005 7:30 pm

Post by doppelganger »

re: the loop command

I'm not sure, at this point, whether I commented the entry ".db $9645" as a dummy entry because it wasn't being used, or whether I did so because it didn't lead anywhere useful as far as the game was concerned...but I do see how that could cause problems in modularization. Fixed it.

re: the swim tile replacement offset

This isn't really a bug, per se, because it works perfectly fine for what I designed SMBDis for. However, seeing as how it will cause problems if the table is moved elsewhere, I went ahead and fixed it by simply modifying SwimTileRepOffset's definition. It will work fine as long as the player's graphics table isn't split up for whatever reason.

I don't really think the IRQ vector warrants fixing, since the game never uses IRQs.

Anyway, I fixed those two problems and uploaded it again. The link is still the same as it ever was.
Be whatever the situation demands.
User avatar
beneficii
Posts: 127
Joined: Tue Jul 12, 2005 4:37 pm

Post by beneficii »

doppelganger,

About the IRQ's and the ORG's, I understood those (they just appeared as output in the program). Basically, this was the program output:

Code: Select all

Line #645:
        SwimTileRepOffset     = $eeb5

Line #669:
               .org $8000

Line #3525:
              .dw $9645 ;dummy entry

Line #16351:
              .dw $fff0  ;unused

16352 rainu yonda
Zubari owaru deshou!
Basically, it just spits it out and lets you decide what to do with it. (On my 366MHz computer, with it compiled into a Win32 Console with MinGW, it took less than a second to run.)

Anyway, now I think we can be pretty confident that this is modularizeable! ^_^
doppelganger
Posts: 183
Joined: Tue Apr 05, 2005 7:30 pm

Post by doppelganger »

It should only be spitting out the ORG and the IRQ now that I updated it yesterday. That output looks like it was from before. I compiled your C code on Turbo C just now and ran it on smbdis.asm...it gave me this output...

Code: Select all

Line #670:
               .org $8000

Line #16352:
              .dw $fff0  ;unused
16352 rainu yonda
Zubari owaru deshou!
And with that, modularization is indeed possible! :-)
Be whatever the situation demands.
User avatar
beneficii
Posts: 127
Joined: Tue Jul 12, 2005 4:37 pm

Post by beneficii »

And a thorough testing of the new build of the (modularized) game reveals no errors (though the minus world looks different--it looks like it uses 8-4's swimming stage now).
doppelganger
Posts: 183
Joined: Tue Apr 05, 2005 7:30 pm

Post by doppelganger »

There's not much that can be done about that. Since I have yet to see exactly how you modularized it, I will have to assume you moved the levels' enemy and area data elsewhere, which would naturally cause the addresses to change...and since the game attempts to fetch data for world 36-1 in entry to the minus world (and finds it in one of the address tables), any address changes here may cause the minus world to be different.

However, considering the whole goddamned minus world is one big glitch, I'd say leave it be. :-P
Be whatever the situation demands.
User avatar
beneficii
Posts: 127
Joined: Tue Jul 12, 2005 4:37 pm

Post by beneficii »

doppelganger,

I was just bringing it up. It's not biggie.

Anyway, I guess now we should consider what we would do with this. LOL. ^_^
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

I can see a few goals ahead:
  1. Convert absolute addresses in $0000-$07FF to CA65 .res statements so that RAM can be modularized.
  2. Write a disassembler that takes the (copyrighted) ROM and spits out a modularized disassembly.
  3. Port it to UNROM/S*ROM/T*ROM. We'll have to decide what needs to be in the fixed bank and what needs to be in the switchable bank, so as to allow a hacker to add separate block types.
  4. Add features from SMB2J.
  5. Make a project to rewrite each module from scratch, like LAME.
User avatar
Hamtaro126
Posts: 783
Joined: Thu Jan 19, 2006 5:08 pm

Post by Hamtaro126 »

The following 3 are both requests (If it is Possible) and/or ideas that I might do myself with is someday:

1: Recreate it for the SNES

(There was one for the Super Mario ALL*STARS but can NOT make a
seperate rom out of it yet. This is so that it is a fresh project instead of
making a rip-off!)

2. Possibly RE-Makeit for the PC.

(Then must rename SMB to SUPER PC BROS or something it so no copyright infrigment could not happen)

3. Create a DISassembler (could either be 1st or last) I am going to request the creator of DISTELLA (see link below) to give me the source
so I can create a recompileable ASM generetor for NES instead of the ATARI VCS/2600 (the OLD 1BPP graphic screen supported console)

*both NES and ATARI VCS/2600 are 6502 and is supported by DASM

Distella (6502 Disassembler for Atari programming in DASM) website:

http://members.cox.net/rcolbert1/distella.htm

Sorry if being a little off topic, but I just need to make a new NES
disassembler that is going to help more ROMhackers and NES developers!

-Hamtaro126
doppelganger
Posts: 183
Joined: Tue Apr 05, 2005 7:30 pm

Post by doppelganger »

The short answer: No, we don't take requests here.
Be whatever the situation demands.
Bohan
Posts: 21
Joined: Sat Mar 24, 2007 7:09 am
Location: Taipei, Taiwan
Contact:

short answer

Post by Bohan »

doppelganger wrote:The short answer: No, we don't take requests here.
You know MARIO?
CartCollector
Posts: 122
Joined: Mon Oct 30, 2006 8:32 pm

Post by CartCollector »

2. Possibly RE-Makeit for the PC.

(Then must rename SMB to SUPER PC BROS or something it so no copyright infrigment could not happen)
Search for "Great Giana Sisters." Yup, no trouble with copyrights there!
You know MARIO?
Mario who? The R&B singer? Can't say that I do, sorry. :lol:
Post Reply