Hello guys,
After lots of work I now seem to be kind of stuck in trying to emulate Super Mario Bros. The problem is that I'm stuck at the menu. I can never enter the real game, it is not responding to key presses! Now that I implemented sprite0 hit and scrolling, after waiting a while Mario starts "moving by himself", like it should, but I can never really start a game to play by pressing start!
I pass all the 11 Nestress first PPU tests. When I run a sprite0 hit basic test, it only fails with code "4" (4) Should miss when background rendering is off), but so fails JNes emulator... And it perfectly runs SMB1, so this shouldn't be related.
Also, pacman's screen has a yellow "something" in the top-left part of the screen (please check out the screenshot). I don't know if there's some odd bug in scrolling/sprite0 but I just can't figure it out... Do you guys have any suggestions or something like that? I'm really stuck
*Edit: All right, this pacman "bug" is ok, I was using JNes and it's JNes fault...*
Thanks a lot for your patiente guys!
miguelfsp wrote:
Also, pacman's screen has a yellow "something" in the top-left part of the screen (please check out the screenshot). I don't know if there's some odd bug in scrolling/sprite0 but I just can't figure it out... Do you guys have any suggestions or something like that? I'm really stuck
When you encounter something like that, the first thing you should try is to see if other "good" emulators behave the same way (in which case 99.995% of the time that behavior is correct). In this case the answer is yes.
Oh, you're right, sorry! I was convinced that it was wrong. Just tried with nintendulator and works the same way... I guess my emulator is better than jnes then
But still can't figure out the SMB1 messed up menu... It simply does not respond to keys (and yes, the main standart controller is implemented and works fine in all the other games). You got any suggestions or something? :/
What are you returning when the game reads more than 8 bits from the controller?
In most cases, if there's some garbage in the top left corner of the screen (usually hidden because NTSC doesn't show the top 8 to 16 scanlines), it's because the game initializes the sprite OAM with all 0s, which gets interpreted as "put sprite tile 0 at x=0 y=0".
(The correct way to "disable" a sprite is to set its Y position to F0 or beyond.)
I'm returning "1". Is this correct? I just made some experiments (returning 0, etc...) and still doesn't work.
Reading address 0x4016 (controller 2 at 0x4017 is "unconnected").
Code:
private int n = 0;
public byte Read()
{
byte retval;
retval = (n < 8) ? Convert.ToByte(state[n]) : (byte)1;
n++;
return retval;
}
So I don't know... maybe the issue is somewhere else? NesStress menu didn't work, till I implemented sprite hit 0 detection and scrolling. Btw an ODD thing: I fully pass nestest BUT when I test the CPU with NESTRESS, in the last "page" of CPU tests.... my emulation
crashes at some point (in STACK ADDR) it never writes anything, because it tries to read from address "$5569", which raises an exception... I don't understand whats wrong here with the CPU AND I don't think that the problems are connected because this issue only happens in Nestress, but maybe you can associate both problems, I don't know.
Thanks Drag, but this time it seems that pacman is really programmed like that (don't ask me why...). I was comparing with JNes and it seems that JNes is wrong.
Thank you for your anwsers.
Your controllers aren't implemented properly. That's all there is to it.
Well... I beleive you... But what is wrong?
http://wiki.nesdev.com/w/index.php/Standard_controllerWhen reading from $4016, in the first 8 bytes I return the state of each key, then I return 1... Till I have a write in $4016 (=0), where I set n = 0 and in the next read everything starts again. Isn't it supposed to be like this?
Your writes to $4016 are wrong. You have to write 1 before writing 0.
I did!
Code:
public void Write(byte value)
{
if ((value & 1) == 0)
{
latch = false;
n = 0;
}
else
latch = true;
}
It has to write 1 before 0.
Still not working...
I guess something really messed up is going on...
Code:
bool one = false;
public void Write(byte value)
{
if ((value & 1) == 0)
{
if (one)
{
latch = false;
n = 0;
one = false;
}
}
else
{
latch = true;
one = true;
}
}
miguelfsp wrote:
Still not working... :( I guess something really messed up is going on...
I don't mean to dishearten you, but comments like "I guess something really messed up is going on"
when you're the author of the emulator do not give the impression that you necessarily understand the code you're writing. :-/
Maybe step back and explain using pseudo-code how you're doing doing your controller stuff, from the main part of your emulator all the way down to the register emulation? More often than not you can't just paste some arbitrary C/C++ code into a forum and have everyone understand how it's being used -- "here's a function, what's wrong with it" "Um, I dunno, why don't you tell us how you're using this function?" :-)
koitsu, thing is, I don't know if it's not working because of the controller - because all the other games that I tested work great (Donkey Kong, Mario Bros, nestest menu, Nestress menu, etc...), only SMB doesn't work.
When the CPU tries to read from $4016, I call the read function in the controller, when it tries to write to $4016, I call the write function.
When a key is up/down, I change the state[8] array to reflect the state of the key press. When I read from $4016, I sequencially read that array, till I read 8 bytes. Then it will always return "1". To "restart" and to return the key values again, you must write 1 to the controller, and then 0. Thats what the write function does.
$4017 second controller IS NOT implemented
I say there's something messed up going on, because of what I wrote about Nestress in my reply to blarggs a few posts above (please check it and tell me what you think :/), so perhaps, its possible that the issue is not exacly on the controller itself, but maybe, possible some other completely remote thing is affecting the correct behaviour of the game itself being emulator.
Quoting myself:
Quote:
So I don't know... maybe the issue is somewhere else? NesStress menu didn't work, till I implemented sprite hit 0 detection and scrolling. Btw an ODD thing: I fully pass nestest BUT when I test the CPU with NESTRESS, in the last "page" of CPU tests.... my emulation crashes at some point (in STACK ADDR) it never writes anything, because it tries to read from address "$5569", which raises an exception... I don't understand whats wrong here with the CPU AND I don't think that the problems are connected because this issue only happens in Nestress, but maybe you can associate both problems, I don't know.
Thank you very much for your anwsers!
Mae sure all bits return 0 like they would if those data bits wouldn't be used. It OR's bits 0 and 1 together.
From doppleganger's disassembly:
Code:
;$00 - temp joypad bit
ReadJoypads:
lda #$01 ;reset and clear strobe of joypad ports
sta JOYPAD_PORT
lsr
tax ;start with joypad 1's port
sta JOYPAD_PORT
jsr ReadPortBits
inx ;increment for joypad 2's port
ReadPortBits: ldy #$08
PortLoop: pha ;push previous bit onto stack
lda JOYPAD_PORT,x ;read current bit on joypad port
sta $00 ;check d1 and d0 of port output
lsr ;this is necessary on the old
ora $00 ;famicom systems in japan
lsr
pla ;read bits from stack
rol ;rotate bit from carry flag
dey
bne PortLoop ;count down bits left
sta SavedJoypadBits,x ;save controller status here always
pha
and #%00110000 ;check for select or start
and JoypadBitMask,x ;if neither saved state nor current state
beq Save8Bits ;have any of these two set, branch
pla
and #%11001111 ;otherwise store without select
sta SavedJoypadBits,x ;or start bits and leave
rts
Save8Bits: pla
sta JoypadBitMask,x ;save with all bits in another place and leave
rts
Thank you 3gengames, all the other bits read from 4016 return 0 (only the 1st bit is set/clear), is that what you mean?
Now, in an act of "dispair" I managed to enter the game by doing this:
Code:
if (address == 0x4016)
return this.console.controller.Read();
else if (address == 0x4017)
return this.console.controller.Read();
By reading address 0x4016 and 0x4017 from the same controller... AND returning the value "4" (0x0100) after 8 reads
Code:
retval = (n < 8) ? Convert.ToByte(state[n]) : (byte)4;
If I do this, SMB gets fixed, but ALL the other games controls stop working... :/
I also just realized that my ppu scrolling completely sucks...
Don't hack in fixes. Just work on getting the behavior right. You return only 1 bit right? And you or with $40 for each return byte for open bus, right?
Uh, no? What do you mean? When I return the value from the controller I "or" that 8 bit value with 0x40? I wasn't doing that. Just added it now, but still doesn't fix SMB.
His hack is useful to show that it's likely not something else (like sprites) that's broken, that it probably is with the controller. Now he can change his code back to before the hack and have a better idea of where to focus effort.
Don't worry about the 0x40 until later. But odds are if you try paper boy, it won't work because you don't emulate that. But also, SMB always had problems using different controllers/switching controllers. But still, is there any more program for reading the $4016 register?
Hi again guys. This keeps getting better and better ... But somehow I got it working...
What did I change? Well... After 8 bytes I now return 4 (100b in binary) and when reading, I read the same controller from $4016 and $4017. I don't know what I changed but that "hack" put my controls to work in all the games...
It really pisses me off getting stuff working without understanding what's going on but ok.
@3gengames I'm also oring with 0x40 but it has no effect on SMB, anyway thank you for alerting me to that. In the future when I start testing other games I doubt I'd ever figure that out if I had a bug!
Quote:
But still, is there any more program for reading the $4016 register?
What do you mean?
Thank you very much for you anwsers guys. If you want to comment on this "solution" please feel free. Still can't really understand why this would work as the documentation doesn't talk about this...
This SMB seems kinda hard to get it working... My scrolling is kinda crappy and sprites in super mario bros are being drawn too much to the left then they should (what the hell?) and in other games everything works good!
That oring with $40 fixes PB because of open bus. Instead of doing it just for $4016+17 reads, you should probably do it with every address on your bus that is open bus to keep it easily working with other games in the future. But otherwise, did you return 0's or 1's as the main byte value after the controller is read? After the first 8 reads, a real controller will return all 1's.
miguelfsp wrote:
It really pisses me off getting stuff working without understanding what's going on but ok.
Your desire to have the games appearing to work outweighs your desire to understand what's happening. If you don't want hacks like that that will fail in the future and force you to revisit the issue all over again and have to review the material that's fresh in your mind right now, don't do them. Work methodically and figure out what the problem might be and test solutions. If you do random things like return 0x04, you're guaranteeing this undesirable outcome.
@3gengames
When a "key" is up, I return "1", when its down I return "0" in its corresponding order :/ After 8 bytes read I return 4 now... But before this hack returned 1.
@blargg
Well I just noticed that this "fix" makes pacman controls STOP WORKING (even thought in other games it works perfectly...).
But after testing and commenting the $4017 read (and returning 0x4), it starts working (and smb stops...). What an annoying problem... The difficulty of writing an emulator is not supposed to be implementing the controls :/...
Hey, maybe SMB requires TWO controls implemented in order to work, and as I'm using the same control for $4016 and for $4017 reads, in my "hack" it's messing up??? Well I'll try this tommorow. Now got to go to sleep as it's very late here in Portugal...
miguelfsp wrote:
Hey, maybe SMB requires TWO controls implemented in order to work, and as I'm using the same control for $4016 and for $4017 reads, in my "hack" it's messing up???
That would break it. I bet your original code would start the game if you pressed one of the directions. Ignore $4017 reads with regard to the controller.
It's too bad we don't have a controller test ROM. Checking that an emulator didn't treat it as having the same controller connected to both ports (or other state-dependence) would be a good test.
I just threw this together. It isn't exactly a test rom because it can't be "passed" or "failed", but it is a diagnostic. It displays lines of dots, which are big if the corresponding button is pressed. The 10 rows from top to bottom are port 1 D0,D1..D4 and then port 2 D0...D4. The reads are interleaved, port 1 first. It reads each port 32 times (the columns), so it's adequate for dumping SNES mouse packets, too. Only problem with it is that the display is so unformatted that it's basically useless without comparing to a known-good emulator or hardware. Source is included.
All right, fixed the bug by creating two controller instances, one of them is read by $4016, the other is read by reading $4017. I'm returning "1" after 8 reads now. Writes to $4016 are common, thought (I suppose that is the correct behaviour and there are no writes to $4017!).
Thank you for your rom, lidnariq, just tested it and 1 control is not affecting the other one (still haven't implemented the keys for the second one thought).
Also I I'm not yet checking if both left/right and up/down keys are pressed at the same time.
Thank you all for your help!
If you have MMC3 implemented, you can also try out Chu Chu Rocket as a test case for joypad emulation. For some reason, the game's joypad reading is broken on many emulators, but works fine on the more accurate emulators, and also works on the console.
And if you don't have MMC3 implemented, it's still uses only 32k of PRG all mapped sequentially, so you can pretend that it's NROM with screwed-up graphics. Just to test out the joypad input. When it works, it works. When it doesn't, the game thinks you're pressing a different button than what you are actually pressing.
All right thank you, I'll put that high on my to-do list. I'm currently trying to figure out MMC1 (still no mappers implemented).
miguelfsp wrote:
Hi again guys. This keeps getting better and better ... But somehow I got it working...
What did I change? Well... After 8 bytes I now return 4 (100b in binary) and when reading, I read the same controller from $4016 and $4017. I don't know what I changed but that "hack" put my controls to work in all the games...
for famicom controllers $4016.2 is microphone input(from wiki), is your rom famicom version?
I seem to recall SMB's menu wouldn't respond in some emulator I was using because the second controller's input was doing something because I had two controllers on my PC but when the second one is disconnected (its a PS1 adapter with 2 ports) it has some garbage input instead. I never investigated it but I do know that plugging in a second controller allowed the game to work. So perhaps player 2's input values were causing the game not to respond to player 1's input. I forget but there may have been other games I had issues with like that too. And it wasn't my own emulator, it was Nestopia, and it worked just fine if a valid 2nd controller was hooked up.