What's new

Nes Core Bug?

Zenathdark

New member
Could somone maybe tak a look at my 6502 core? I am trying to run SMB1, but it is always ending in a loop somewhere :plain:

I have made a Log, with some debug info in it, containing the registers opcodes , and at which PC they where executed.

I am fairly sure that i am loading the ROM correctly into memory, because SMB1 should not contain a mapper, right? So i am just loading in the program code in at 0x8000, and not including the header. And I am "Swapping" in the CHR-ROM in my Ppu Memory at 0x0000 - 0x2000.

So I think that somewhere in the my 6502 instructions core, lies an error somewhere. It should not be hard to track down, using the Debug Log provided :bouncy:

But since I am not a hardcore 6502 ASM buff, I find it a little tricky to know if I am emulating the instructions correct.

Maybe someone can help? :)
 

Exophase

Emulator Developer
Could somone maybe tak a look at my 6502 core? I am trying to run SMB1, but it is always ending in a loop somewhere :plain:

I have made a Log, with some debug info in it, containing the registers opcodes , and at which PC they where executed.

I am fairly sure that i am loading the ROM correctly into memory, because SMB1 should not contain a mapper, right? So i am just loading in the program code in at 0x8000, and not including the header. And I am "Swapping" in the CHR-ROM in my Ppu Memory at 0x0000 - 0x2000.

So I think that somewhere in the my 6502 instructions core, lies an error somewhere. It should not be hard to track down, using the Debug Log provided :bouncy:

But since I am not a hardcore 6502 ASM buff, I find it a little tricky to know if I am emulating the instructions correct.

Maybe someone can help? :)
First, what documentation are you using? I recommend this:

http://www.romhacking.net/docs/65xx-Processor-Data.zip

I'm not proven proficient in 6502 (and I don't use C#...) but I'll tell you what I think is wrong:

- tsx/txs should transfer between s and x, not stack and x.
- Your v flag emulation for adc imm is incorrect, it doesn't merely mirror the c flag.. rather, v flag means that there's an inconsistency between the sign of the sources and the sign of the result. For the other forms it seems you don't have v at all. I see you do CheckNZV, but there's no way that you can determine the v flag just from the answer.
- I can't follow what you're doing with the memory addressing, it looks like you're setting particular variables instead of memory locations. In which case I think you might be severely misunderstanding what the address modes mean.

Honestly that last one is so severe that I stopped looking very closely. You should explain how you think the address modes work, because I might be missing some kind of weird C# magic. 65xx has some complex addressing modes, the indirect ones in particular can take a bit of time to wrap your head around if you're not used to this kind of platform.

Anyway, my primary advice to you is this: start small! Don't try to run Super Mario Bros right off the bat. Look for some simple demos, especially demos where the source code is available. This should give you labels and hopefully enough comments to be able to clearly figure out what's going on. And if you don't have a good debugger, do one. As a last resort, pull out another NES emulator that has a debugger and follow yours along with it until they disagree. Most emulators have debuggers in their source but don't ship with them enabled so you might have to specially compile one.

EDIT: I talked to someone and it seemed you might be using "properties" to implement the address modes. I wouldn't know because you're not including all of the relevant source. Next time you should upload everything.
 
Last edited:
OP
Z

Zenathdark

New member
Ok, First this is only the instruction set, C# allows one to split up a class in several classes. In another codefile, i have declared the variables, i will include it here.

I will explain how i understand the addressing modes =]

Immediate = OP NN = NN is the value assigned to register

ZeroPage = OP NN = NN is a memory address containing the value

ZeroPage,X = OP NN = NN + X, is a memory Address containing the value

ZeroPage,Y = OP NN = NN + Y ----------------------------------------------

Absolute = OP NNNN = NNNN is a 16bit address in memory containing the value

AbsoluteX = OP NNNN = NNNN + X ------------------------------------------------

AbsoluteY = OP NNNN = NNNN + Y ------------------------------------------------

IndirectX = OP NN = (HB)NN + X, and (LB)NN + X + 1 is 16 bit address in mem

IndirectY = OP NN = (HB)NN, and (LB)NN + 1 = address + Y = is a 16 bit address

And when optaining the Opcode, one have to shift the bytes, because of the "low-endian". So in the ROM file, the Opcode is = OP 54 AA. You have to do a Instruction = (Opcode & 0x00FF00) >> 8 | (Opcode & 0x0000FF) << 8;

Isn't this somewhat correct? :)

I am using Everynes Documentation for the opcodes.

And I am including the Register declerations.

PS. I am aware of how the Cpu and Ppu memory, and memory map look like, but am trying to make it easier to read in code, and the when the NES is writing to the Ppu memory, I direct it to the appropiate "value". I.E 0x2000 - 02FFF is the name tables, but instead of making an array[0x1000] i am making 4 * nameTable[0x3FF], then when NES writes to Ppu[0x2000] i direct it to nameTable1.
 
Last edited:
OP
Z

Zenathdark

New member
OH.. and by the way, a lot of the variables i assign to is to is not variables, it is 'Accessor methods', and yes, it is C# magick :evil:

It is like a function you use to get and set properties in a class:


Classic:

int _Y;

public void setY(int value)
{
_Y = value
}

public int getY()
{
return _Y;
}

C# :

public Y
{
get {return _Y}
set {Y = value}
}

It's like.... Magick... hehe :bouncy:
 

Cyberman

Moderator
Moderator
In simple terms you should be very wary of 'magic', as in reality there is no such thing (magicians use deception think of it that way). C# is not a standard for a reason.

In any case you should avoid things that obfuscate what is happening and if you do, you might consider commenting it. I use doxygen a lot. When I use properties I explain what they really are and how it's supposed to work. It makes even someone unfamiliar with the language you are using able to decipher what you are doing.

Cyb
 

Exophase

Emulator Developer
Yeah, I realized that you could be doing something like that (of course I never would have really known w/o confirmation). It seems to go against the spirit of why such a feature is there, especially since you aren't using it for things like AbsoluteAddress, but you're the C# programmer so I'll let you decide that one...

Anyway, new things I'm noticing:
- Making the stack and memory different entities is asking for trouble. The stack is aliased to memory, so you can access it via normal memory calls (and you need to if you want to do something more sophisticated than push/pull with the memory).
- Similarly, you don't seem to correspond the flags with the P register at any point. Reading and writing the P register has to keep the flag values consistent. With that in mind, it's not worth it to give the flags that are only set/destroyed directly their own variable - you're better off setting/clearing them in P directly.

Still need more code. Like the part where you actually fetch the opcode.
 
OP
Z

Zenathdark

New member
In simple terms you should be very wary of 'magic', as in reality there is no such thing (magicians use deception think of it that way).

I know. Accessor methods it is nothing more than code reduction and readability.

Howevever, I have understood it like Accessors are used for getting and setting properties of a the class. So you can treat them as variables of a class instead of methods. While it still is, kind of method.

C# is not a standard for a reason.

Wasn't C# declared and ECMA Standard 5 years ago?

It seems to go against the spirit of why such a feature is there, especially since you aren't using it for things like AbsoluteAddress, but you're the C# programmer so I'll let you decide that one...

As for not using the Accessor methods for that one, is that it is not going to an internal part of the class. The reason it is declared here is... Let's just call it "Fast Prototyping"... ;-)

The function fetching the opcode declared in Cpu.cs
 
Last edited:

Exophase

Emulator Developer
I know. Accessor methods it is nothing more than code reduction and readability.

They're called properties you know, right? I'm not seeing how it improves readibility when it introduces an ambiguity (you don't know whether or not something's a variable or a method anymore)... I think that it's just another feature to make the language appear more versatile (and confusing). Amount of code reduced is close to nothing. I'm pretty disgusted by various sources saying that it's important and integral to the language. In the world of semantic sugar this one is a couple sprinkles.

As for not using the Accessor methods for that one, is that it is not going to an internal part of the class. The reason it is declared here is... Let's just call it "Fast Prototyping"... ;-)

Okay, I won't try to understand your complex rules for deciding how to write what boils down to the same thing ;P

The function fetching the opcode declared in Cpu.cs

Which I see you just now edited in, sneaky! Anyway, as I suspected, you don't seem to be handling two byte opcodes, only one and three byte ones. Anything with an immediate or zero page operand will be 2 byte.
 
Last edited:
OP
Z

Zenathdark

New member
They're called properties you know, right?

I think of it this way:

Outside A class: Variable, Function
Inside A class: Property, Method

The Get/Set methods are Not properties, they are methods that return or set the properties inside a class.

In the world of semantic sugar this one is a couple sprinkles.

And i'm a sucker for sweet sweet sugar ;-)

Okay, I won't try to understand your complex rules for deciding how to write what boils down to the same thing ;P

And you don't have too :), But the code you see is not well designed, it is prototyping.

Anyway, as I suspected, you don't seem to be handling two byte opcodes, only one and three byte ones. Anything with an immediate or zero page operand will be 2 byte.

I am handling the the 2 byte opcodes? In the HandleFullOpcode() it determines the opcode in a switch, and executes the method for handling either two or three bytes.

It really should..... :)
 

Exophase

Emulator Developer
I think of it this way:

Outside A class: Variable, Function
Inside A class: Property, Method

The Get/Set methods are Not properties, they are methods that return or set the properties inside a class.

They're properties. The designers of the language say so. http://msdn2.microsoft.com/en-us/library/Aa288470(VS.71).aspx

I think your definitions are something you've made up because I've never heard anyone use them. Nothing about properties enforces that they behave like variables. For instance, you could "call" it several times in a row and get a different value back. Accessing variables directly should not imply side-effects.

And although some people use "function" incorrectly when they mean method, a method is a method regardless of whether it's called internally or externally.

And i'm a sucker for sweet sweet sugar ;-)

Just don't get a cavity :O

I am handling the the 2 byte opcodes? In the HandleFullOpcode() it determines the opcode in a switch, and executes the method for handling either two or three bytes.

It really should..... :)

What I meant is that you're not handling them by loading only two bytes, even though you make this distinction between one byte and non-one byte opcodes. Although this might work (since you're incrementing the PC separately for them) it's quite inconsistent and wasteful. You'd may as well make the loading/PC incrementing part of all of the instructions, rather than going through the trouble of loading to an up to 24bit opcode variable and then decoding that. You're just adding more intermediate work to do and undo something.

Also, I meant to say, your definition for push/pop is very misleading. Usually that includes actually transferring the stack value and not just modifying the stack pointer.

One other thing: You need to have wraparound for the 16bit indirect addressing.

By the way, I really feel like I should reiterate: don't try running any real games without implementing EVERY CPU feature. This especially includes things like computation flags...
 
Last edited:
OP
Z

Zenathdark

New member
I think your definitions are something you've made up because I've never heard anyone use them.

Maybe I just misunderstood, what i have read? i am not trying to trick you, although magick is cool.

Anyway you are right about the properties, i can see they call variables inside classes 'fields'. And the Get / Set methods apparently belong to the property.

By the way, I really feel like I should reiterate: don't try running any real games without implementing EVERY CPU feature. This especially includes things like computation flags...

I understand :), but if we put aside that I am not squeesing the emu for effeciency, then according to the log, the opcodes that it executes are not dependant on the cpu features the emu lack, which is P,V and S.

Oh and by the way, the S, it is the Stack Pointer right?
So when making a artificial Stack and pointing to it with the SP like in Stack[SP], would that not be the same functionallity as the 6502, S provides?

You make it clear that the stack should not be seperated from the CpuMemory, but isn't it possible to do it like this?
 

Exophase

Emulator Developer
I understand :), but if we put aside that I am not squeesing the emu for effeciency, then according to the log, the opcodes that it executes are not dependant on the cpu features the emu lack, which is P,V and S.

I listed several problems. Without proper P implementation interrupts and breakpoints will probably not work right, and without interrupts and breakpoints games won't work in general. I'm not going to look through an instruction log (which is not the way to approach getting an emulator to just start working) when I know you're doing several things wrong.

Oh and by the way, the S, it is the Stack Pointer right?
So when making a artificial Stack and pointing to it with the SP like in Stack[SP], would that not be the same functionallity as the 6502, S provides?

You make it clear that the stack should not be seperated from the CpuMemory, but isn't it possible to do it like this?

No, it isn't possible. Consider that S = 0xFF:

lda #$10 ; a = 0x10
pha ; memory[0x1FF] = a
ldx $1FF ; x = memory[0x1FF] = 0x10.. but not in your version
 
OP
Z

Zenathdark

New member
lda #$10 ; a = 0x10
pha ; memory[0x1FF] = a
ldx $1FF ; x = memory[0x1FF] = 0x10.. but not in your version

I see.

I listed several problems. Without proper P implementation interrupts and breakpoints will probably not work right, and without interrupts and breakpoints games won't work in general.

Okay, I think i understand now. What I was trying to accomplish was to get the game to work partially, and by looking in the Log finding out where it breaks, fixing that, trying again, find the break, fix it.... and so forth...

You say, that it is impossible to get this to work, unless i have implemented every feature more or less correct, and I understand that.

But one thing I don't get is why the game can break, if it does not try to execute an opcode that is not implemented.
 

Exophase

Emulator Developer
I see.



Okay, I think i understand now. What I was trying to accomplish was to get the game to work partially, and by looking in the Log finding out where it breaks, fixing that, trying again, find the break, fix it.... and so forth...

You say, that it is impossible to get this to work, unless i have implemented every feature more or less correct, and I understand that.

But one thing I don't get is why the game can break, if it does not try to execute an opcode that is not implemented.

I don't know if the things I've mentioned are what's breaking it or not (remember, I mentioned more than just those things you aren't implementing or aren't implementing correctly). It just isn't worth looking through the log for it. The biggest problem with your approach is you don't know what the game is really supposed to be doing if it's working correctly (aside from showing the right things on the screen, but you don't get that until most of the work is done). So it's hard to tell when it's working "correctly" or not. You really need to have something where you can predict the correct behavior. Unless you want to spend months reverse engineering Super Mario Bros I recommend using something already documented and very simple.
 
OP
Z

Zenathdark

New member
Ok, and by documented and simple i assume you suggest that i:

A: Find A game/demo with Source code and Doc's
B: Load the game, and watch step by step it is behaving according to its source + doc
C: When everything is behaving as expected, step up to a more complex demo.

Thank you very much for your time, and advice. I can now continue writing the emu.
 

Exophase

Emulator Developer
Ok, and by documented and simple i assume you suggest that i:

A: Find A game/demo with Source code and Doc's
B: Load the game, and watch step by step it is behaving according to its source + doc
C: When everything is behaving as expected, step up to a more complex demo.

Thank you very much for your time, and advice. I can now continue writing the emu.

Yeah, that's it exactly. Good luck.
 

Top