Super Mario Bros. starts in invalid world
Moderator: Moderators
Super Mario Bros. starts in invalid world
Hallo all,
years ago I made first experience in NES emulation. I managed to write an emulator which was capable of emulating simple no-mapper games correctly. Only problem was that SMB always started in the first water world.
Now, for about a week, I'm having my second go on it.
I built a new emulator from scratch, now working my way around all the mistakes I made on my first attempt.
It works really well, and I even got the PPU scrolling working just like it is described in Brad Taylor's PPU document.
All no-mapper games seem to work great.
Except SMB. It still has the same issue, though this time you don't start in first water world, but in a castle. And you are able to swim in there ;D
After starting emulation, the status bar shows "WORLD" 1-1 correctly for 1 frame (or a bit more), but then it immediately switches to someting like P-1. P being any weird symbol.
Still, the game intro is correctly playing in 1-1.
Any ideas what could cause this problem?
Thanks!
years ago I made first experience in NES emulation. I managed to write an emulator which was capable of emulating simple no-mapper games correctly. Only problem was that SMB always started in the first water world.
Now, for about a week, I'm having my second go on it.
I built a new emulator from scratch, now working my way around all the mistakes I made on my first attempt.
It works really well, and I even got the PPU scrolling working just like it is described in Brad Taylor's PPU document.
All no-mapper games seem to work great.
Except SMB. It still has the same issue, though this time you don't start in first water world, but in a castle. And you are able to swim in there ;D
After starting emulation, the status bar shows "WORLD" 1-1 correctly for 1 frame (or a bit more), but then it immediately switches to someting like P-1. P being any weird symbol.
Still, the game intro is correctly playing in 1-1.
Any ideas what could cause this problem?
Thanks!
That's incredible!
Indeed, when I use another rom of SMB, the problem doesn't occur.
Thanks for that hint!
But I still think there must be an issue with my emulator, because
the SMB rom that starts in the wrong world, works very fine with NESticle95. So NESticle95 must do something right, that my emulator doesn't.
Another symptom is, that - in my emulator - the background of world 1-1 is black instead of a light blue.
Indeed, when I use another rom of SMB, the problem doesn't occur.
Thanks for that hint!
But I still think there must be an issue with my emulator, because
the SMB rom that starts in the wrong world, works very fine with NESticle95. So NESticle95 must do something right, that my emulator doesn't.
Another symptom is, that - in my emulator - the background of world 1-1 is black instead of a light blue.
Nesticle is inaccurate. It was good for its time, but it was obsolete as soon as LoopyNES was released. Knowledge of how the NES actually works has advanced since then. It takes four lines of assembly language for a program to determine whether it is running on an NES or on Nesticle. The boot sequence of LJ65 incorporates code like the following:The Lord wrote:But I still think there must be an issue with my emulator, because
the SMB rom that starts in the wrong world, works very fine with NESticle95. So NESticle95 must do something right, that my emulator doesn't.
Code: Select all
vwait2:
bit $2002
bpl vwait2
bit $2002
bmi is_running_on_nesticle
It has entirely to do with whether you are initializing RAM to 00 or FF. If you initialize to 00, the bad dump of SMB1 works, and if you initialize to FF, it starts at 0-1.
Of course, you can always use the Continue feature (A+Start) and start at 1-1 regardless.
Of course, you can always use the Continue feature (A+Start) and start at 1-1 regardless.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
Nice. You are completely right. Initializing the RAM to 0 did the trick.Dwedit wrote:It has entirely to do with whether you are initializing RAM to 00 or FF. If you initialize to 00, the bad dump of SMB1 works, and if you initialize to FF, it starts at 0-1.
Of course, you can always use the Continue feature (A+Start) and start at 1-1 regardless.
Didn't know the NES clears its RAM.
Yes I though so. My point was, that Nesticle managed to execute SMB right. So that made me conclude that my emulator must have a bug that Nesticle doesn't have. And it had, as Dwedit made me realize.tepples wrote:Nesticle is inaccurate.
It doesn't. If a game relies on any RAM it didn't initialize, it's badly programed (except if it's for generating random numbers, like Dwedit mentioned FF does).The Lord wrote:Didn't know the NES clears its RAM.
Why can't Nesticle be the one with the bug? As tepples said, Nesticle is very old and many new things have been discovered about the NES since the last version of it. You should completely disregard what Nesticle does if you are aiming for accuracy, because you are trying to emulate a NES, not Nesticle. The emulators tepples mentioned (Nintendulator and Nestopia) are the most accurate nowadays.So that made me conclude that my emulator must have a bug that Nesticle doesn't have.
Initializing the RAM to something other than 0 isn't a bug. The contents of RAM on start up shouldn't matter, because no well programmed game will rely on uninitialized RAM.And it had, as Dwedit made me realize.
Don't make your emulator less accurate just to support a crappy hack or a bad dump. The ROM has a bug, not your emulator.
Actually if you load it from the PowerPak, the RAM will probably be in an entirely pre-determined state by the time your program starts. I wonder if that messes up the Excitebike music variations or something like that.tepples wrote: If you want to be sure, benchmark it against an NES with a PowerPak.
People who have tested on hardware say that the RAM contains mostly $FFs, but this behaviour isn't constant enough for you to count on it. This is one of those things that change with the phase of the moon and you simply can't replicate exactly. So I guess you can do whatever you want with the RAM, it shouldn't matter.essial wrote:I've been eyeing these posts.. Would it be right to initialize ram to FF, or should it be initialized to random values throughout?
I don't think it would be anywhere near white-noise style random on the real system (I haven't checked though, but you can see it when you don't clear the nametable memory). FCEU I noticed seems start out with some pattern of eight 00s then eight FFs. kinda helps for checking if people cleared RAM or not in their programs
In my NES programs I do the exact opposite of clearing RAM: I fill it with "random" values myself. I do this to make sure I haven't used any variable without initializing it properly. Of course I have to change the seed a few times to in order to detect if something is wrong with a new piece of logic. It doesn't catch everything, but it helps. I don't plan on leaving the code that randomizes RAM on the release versions though, this is just for debugging.
I always found clearing RAM an evil thing, because although it might save you some specific initializations it will make it easier for you to forget to initialize something. Say you have a routine that happens to work when it reads a zero from RAM. You forgot to clear that variable, but the routine will work because you cleared the whole memory before. So you tested the routine and have considered it works, and you decide to use it in other parts of the program. But if this particular byte happens to be changed by this very routine or by some other code, the other times this routine is called it might not work. That's a very hard bug to find, as you don't even have that routine in mind because you tested it before and it worked fine. This is why I consider clearing RAM evil. I initialize before I use it, always.
I always found clearing RAM an evil thing, because although it might save you some specific initializations it will make it easier for you to forget to initialize something. Say you have a routine that happens to work when it reads a zero from RAM. You forgot to clear that variable, but the routine will work because you cleared the whole memory before. So you tested the routine and have considered it works, and you decide to use it in other parts of the program. But if this particular byte happens to be changed by this very routine or by some other code, the other times this routine is called it might not work. That's a very hard bug to find, as you don't even have that routine in mind because you tested it before and it worked fine. This is why I consider clearing RAM evil. I initialize before I use it, always.
- cpow
- NESICIDE developer
- Posts: 1097
- Joined: Mon Oct 13, 2008 7:55 pm
- Location: Minneapolis, MN
- Contact:
I used to just leave the RAM contents alone but then I noticed that uninitialized it was typically CDCDCDCD values which just looked aesthetically wrong to me. So I now set it to zeros.Memblers wrote:I don't think it would be anywhere near white-noise style random on the real system (I haven't checked though, but you can see it when you don't clear the nametable memory). FCEU I noticed seems start out with some pattern of eight 00s then eight FFs. kinda helps for checking if people cleared RAM or not in their programs