Page 7 of 23
Re: Need guidance with nes to snes.
Posted: Fri Mar 12, 2021 2:27 pm
by Myself086
creaothceann wrote: ↑Fri Mar 12, 2021 12:47 pm
Maybe he should get it working with emulation mode first?
No, here's why...
While emulation mode helps with better timing accuracy, it doesn't fix the entire timing problem.
Opcodes such as TXS, PLP and BRK become more accurate but they are quite rare and easy to fix.
Illegal opcodes are NOT supported by emulation mode.
The biggest problem for me with emulation mode is losing the program bank when an interrupt happens which makes the project hard to manage when you need more than 64kb of code.
Re: Need guidance with nes to snes.
Posted: Fri Mar 12, 2021 6:31 pm
by infidelity
Well it wasnt the irq that was causing my stack issue. Turns out it deals with my "P" status.
During my reset vector loop, the nmi never fires at the same exact spot in the loop. The last moment before the first NMI fires, it pushes the P status to the stack, and when the NMI first fires, it does PHP and it matches against what was previously set within the stack.
The second time is where it gets altered. Example. The reset vector loop will reach its last moment before NMI, the P status at that point is 30, so that gets placed in the stack. Now the NMI fires for the second time, and now the P status shows itself as 34, and that gets pushed to the stack, so now the stack shows 34,30.
And the issue I had on the last page of this thread, was because the P status wasnt the same as it was at the last moment of the reset vector loop.
So I wrote a routine to fix that error, to copy the correct P status, and place it over the incorrect one.
Code: Select all
;$c000 start of nmi
php
pha
txa
pha
tya
pha
lda $4210
rep #$18
tsx
inx
inx
inx
inx
lda $0000,x ;load p status from stack
inx
sta $0000,x ;replace incorrect p status
sep #$30
Re: Need guidance with nes to snes.
Posted: Fri Mar 12, 2021 6:58 pm
by dougeff
I think what you mean to say is that an interrupt does a PHP and the RTI does an PLP, and that the changes you made to the processor flags during the interrupt don't carry outside the NMI code to the main code. Right?
However, now that I think about it... which flag would you need to change? No, what you wrote doesn't make sense to me, nor does your solution.
Edit... by the way the bit changing in the status flags (you said 30 vs 34) is the IRQ disable flag. The instructions SEI and CLI affect this flag. Also the REP and SEP instructions affect it.
...
Re: Need guidance with nes to snes.
Posted: Fri Mar 12, 2021 8:36 pm
by Myself086
34 vs 30 is normal, interrupts will set the interrupt flag just after pushing P. If the first instruction within NMI code is PHP, the stack may look as follow: 34 30
Re: Need guidance with nes to snes.
Posted: Sat Mar 13, 2021 4:55 am
by infidelity
Myself086 wrote: ↑Fri Mar 12, 2021 8:36 pm
34 vs 30 is normal, interrupts will set the interrupt flag just after pushing P. If the first instruction within NMI code is PHP, the stack may look as follow: 34 30
I understand what you're writing, but what doesnt make sense is why the irq was being triggered for the 3rd interrupt, but not my NMI? Cause the original game in working on, that irq doesnt get activated until the MMC3 $E001 says so.
I guess I'll remove that code, and log down every conversion I've done with the snes bits
Re: Need guidance with nes to snes.
Posted: Sat Mar 13, 2021 6:55 am
by Myself086
Is it another case of using TRB/TSB for IRQ?
Are you accidentally acknowledging NMI during IRQ?
This game activates IRQ with a STA $E000,X where X is equal to 1.
Re: Need guidance with nes to snes.
Posted: Sat Mar 13, 2021 7:18 am
by dougeff
I disagree that the status flag changing is "normal". Nothing should affect the IRQ disable flag except for SEI, CLI, SEP, REP, or PLP instructions.
Something is not right, and you should investigate that, rather than a workaround solution.
Running a trace log, and advancing one frame at a time should help you pinpoint exactly when the flag is changing.
* I stand corrected. From the WDC manual, chapter on Interrupts:
"In addition to pushing the status and program counter information onto the stack, the d decimal flag in
the status register is cleared (except on the 6502), returning arithmetic to binary mode. The i interrupt disable flag is set, preventing further interrupts until your interrupt-service routine resets it"
Re: Need guidance with nes to snes.
Posted: Sat Mar 13, 2021 8:39 am
by Myself086
Here are the values I get for P for the first few NMI on FCEU:
34 24
34 20
B4 A0
36 22
34 20
34 20
34 20
The P value on the right is pushed by NMI while the one on the left is pushed by PHP.
When NMI happens, the CPU does the following:
- Push PC
- Push P (with B flag clear on 6502)
- Set I
- Jump to NMI code
Then the first instruction in NMI's code is PHP (with B flag set on 6502)
It just so happens that the interrupt flag was originally set when the first NMI happened but is cleared for future frames.
There's nothing to fix here, OP is getting the correct result and I disagree with the solution code to copy P.
Re: Need guidance with nes to snes.
Posted: Sat Mar 13, 2021 8:47 am
by infidelity
dougeff wrote: ↑Sat Mar 13, 2021 7:18 am
I disagree that the status flag changing is "normal". Nothing should affect the IRQ disable flag except for SEI, CLI, SEP, REP, or PLP instructions.
Something is not right, and you should investigate that, rather than a workaround solution.
Running a trace log, and advancing one frame at a time should help you pinpoint exactly when the flag is changing.
Yes i've been using trace logs on both the nes and bsnes, that is how i was seeing the issue with the P flag.
Myself086 wrote: ↑Sat Mar 13, 2021 8:39 am
Here are the values I get for P for the first few NMI on FCEU:
34 24
34 20
B4 A0
36 22
34 20
34 20
34 20
The P value on the right is pushed by NMI while the one on the left is pushed by PHP.
When NMI happens, the CPU does the following:
- Push PC
- Push P (with B flag clear on 6502)
- Set I
- Jump to NMI code
Then the first instruction in NMI's code is PHP (with B flag set on 6502)
It just so happens that the interrupt flag was originally set when the first NMI happened but is cleared for future frames.
There's nothing to fix here, OP is getting the correct result and I disagree with the solution code to copy P.
I've removed the code of mine forcing a value into the stack. Right now it looks like things that supposed to be loading very early on are doing so. But the game isn't crashing for me, which it should be in bsnes, i see my frame counter continuously going. I'm going to figure exactly where the issue is.
But right now i want to upload a list of changes that i've made, sorry it's in hex, i don't have time to write this all out.
Code: Select all
SNES INIT Has Already Been Setup Before This Point, Begin Port.
Set Stack To $1FF
$7E00 = C210 A2FF01 9A E210
$FE19 = A204 AD0220 10FB AD0220 30FB CA D0F3
$7E19 = A204 AD1242 10FB AD1242 30FB CA D0F3
$FE28 = AD0220
$7E28 = AD1242
$FE62 = A901 8D00A0 ;mmc3 mirroring
$7E62 = A901 4C67FE ;bypass mirroring for now
Set Stack To $1FF
$FEA5 = A2FF 9A
$7EA5 = 4C9BE8
C218 A2FF01 9A E230 4CA8FE
My Code To Adjust Stack (stack low byte may be in $17F/$1BF/$1FF)
$FEDD = B582 AA 9A
$FEDD = 4C48E2
B582 C230 18 690001 AA 9A A90000 E230 4CE1FE
Fit In Read of $4210 After Pushes At Start of NMI
$C006 = A5EA F00B
$4006 = 4C26EA
AD1042 E230 4C39EA
Clear Nametables (routine called twice via jsr, one with A920, other with A924)
$C3D5 = 8500 8601 8402 AD0220 A5FF 29FE 8D0020 A500 8D0620 A000 8C0620 A204 C920 B002 A602 A000 A501 8D0720 88 D0FA CA D0F7 A402 A500 C920 9012 6902 8D0620 A9C0 8D0620 A240 8C0720 CA D0FA A601 60
Clear Entire SNES VRAM
$43D5 = C218 9CFF1F A980 8D1521 A20000 8E1621 A9BF 8D0443 A20080 8E0243 A00080 8C0543 A901 8D0043 A918 8D0143 A901 8D0B42 EEFF1F ADFF1F C902 D0D6 9CFF1F E230 60
Set Stack To $1BF
$C50C = A2BF 9A
$450C = 4C14E8
C218 A2BF01 9A E230 4C0FC5
$FF Contains NES $2000 PPUCTRL, Values Used Are 00,08,0C,88,89,8A, Need To Set SNES Equivilants, Sprite Pattern Table Address Ignored, Since OAM Location Is Set In SNES INIT
$C50F = A5FF 8D0020
$450F = A5FF 4C1FE8
C900 F014 C908 F010 C90C F01E C988 F02C C989 F03A C98A F04D A980 1C0042 A901 1C1521 A903 1C0721 4C14C5 A980 1C0042 A901 0C1521 A903 1C0721 4C14C5 A980 0C0042 A901 1C1521 A903 1C0721 4C14C5 A980 0C0042 A901 1C1521 A902 1C0721 A901 1C0721 4C14C5 A980 0C0042 A901 1C1521 A902 0C0721 A901 1C0721 4C14C5
$FF Contains NES $2000 PPUCTRL, Values Used Are 00,08,0C,88,89,8A, Need To Set SNES Equivilants, Sprite Pattern Table Address Ignored, Since OAM Location Is Set In SNES INIT
$C054 = A5FF 2978 8D0020
$4054 = A5FF 2978 4CA6E8
C900 F014 C908 F010 C90C F01E C988 F02C C989 F03A C98A F04D A980 1C0042 A901 1C1521 A903 1C0721 4C5BC0 A980 1C0042 A901 0C1521 A903 1C0721 4C5BC0 A980 0C0042 A901 1C1521 A903 1C0721 4C5BC0 A980 0C0042 A901 1C1521 A902 1C0721 A901 1C0721 4C5BC0 A980 0C0042 A901 1C1521 A902 0C0721 A901 1C0721 4C5BC0
NES $2001 PPUMASK (Used For Rendering, values are always 00 or 18, 1#=bg on/off, #8=sprite on/off)
$C05B = A900 8D0120
$405B = 4C22E9
A910 1C2C21 A980 1C0021 4C5EC0
NES $2003 OAMADDR (Original Sprite DMA buffer located at $200-$2FF, Doing The Same For Port)
A Is 00 By This Point
$C060 = 8D0320 A902 8D1440
$405E = 9C0221 A902 8D0321
$FE Contains NES $2001 PPUMASK (Used For Rendering, values are always 00 or 18, 1#=bg on/off, #8=sprite on/off)
$C0C4 = A5FE 8D0120
$40C4 = A5FE 4C2FE9
D00D A910 1C2C21 A980 1C0021 4CC9C0 A910 0C2C21 A980 0C0021 4CC9C0
NES $2000 PPUCTRL, Values Used Are 00,08,0C,88,89,8A, Need To Set SNES Equivilants, Sprite Pattern Table Address Ignored, Since OAM Location Is Set In SNES INIT
$C0C9 = A567 2903 05FF 8D0020
$40C9 = A567 2903 05FF 4C4BE9
C900 F014 C908 F010 C90C F01E C988 F02C C989 F03A C98A F04D A980 1C0042 A901 1C1521 A903 1C0721 4CD2C0 A980 1C0042 A901 0C1521 A903 1C0721 4CD2C0 A980 0C0042 A901 1C1521 A903 1C0721 4CD2C0 A980 0C0042 A901 1C1521 A902 1C0721 A901 1C0721 4CD2C0 A980 0C0042 A901 1C1521 A902 0C0721 A901 1C0721 4CD2C0
MMC3 IRQ $C000/$C001/$E000/$E001 Setup. Need SNES Equivilant (These Correct For SNES?)
$C0D2 = A55C 8D00C0 8D01C0 A69B 9D00E0 F00C A65D BD18C3 859C BD24C3 859D
$40D2 = 4CD7E9
A55C 8D0942 8D0A42 A59B D00C A910 1C0042 A980 0C0042 8011 A990 0C0042 A65D BD18C3 859C BD24C3 859D 4CEDC0
MMC3 IRQ (1 of 12 IRQ's, 1st one is not active)
$C30E = 8D00E0 68 A8 68 AA 68 28 40
$430E = 4C1EEA 68 A8 68 AA 68 28 40
A980 1C1142 4C11C3
Edit - Making progress again, made it to the primary graphics load routine the game does, sets up the bank in $A000-$BFFF. Going to see how this is done in the original game, and then I believe I need to come up with a Load Long routine to get those gfx from the different banks.
Re: Need guidance with nes to snes.
Posted: Sat Mar 13, 2021 9:44 am
by dougeff
I edited my previous incorrect post.
Re: Need guidance with nes to snes.
Posted: Sat Mar 13, 2021 9:57 am
by infidelity
I keep getting my irq vector loading over and over, ugh, not sure why. I have a routine that makes A 16 bit, and when it comes time to load A as 0000, I get hit with an irq interupt, and I'm unable to get back to my routine, it starts pushing to the stack while I'm in 16bit mode, and then the irq is loading things as 16 bit, just a mess.
Re: Need guidance with nes to snes.
Posted: Sat Mar 13, 2021 10:29 am
by Myself086
You have to acknowledge IRQ by reading $4211, otherwise clearing the interrupt flag will trigger the same IRQ immediately.
This can happen if you do REP #$24.
Re: Need guidance with nes to snes.
Posted: Sat Mar 13, 2021 10:50 am
by infidelity
Hmm. I dont have any readability of $4211, where should I place the read?
Edit - I placed a read at the only irq that is loaded for the time being, and I think I'm ok. My port and the original rom are now at the same location, phew! Onward with figuring out the loading from other banks.
Edit 2 - Disassembling the original games routine that stores the chr into the ppu from 0000-1FFF. Just relieved the original rom and my port all match up to this point!
Re: Need guidance with nes to snes.
Posted: Sun Mar 14, 2021 1:46 pm
by infidelity
Hmm, having issues where my bg 1 tilemap location keeps getting removed even though I'm no touching it.
I have massive routines that check for the way the games original mirroring Nametable is, and I reset/set bits to the $2107 registers #2 #1 bits, aka #0-#3 to determine 32x32 64x32 32x64 64x64.
Now, I have 1# set very early on for $2107 so that my tilemap location starts at $2000 in vram, but it keeps changing to $4000 cause of my reset set bits indo to $2107, with TRB/TSB 0C/1C opcodes, and I'm not touching the 1# bit.
Very very confusing.

Re: Need guidance with nes to snes.
Posted: Sun Mar 14, 2021 2:13 pm
by Revenant
TSB and TRB cannot be used to modify write-only registers. (It looks like this has been mentioned at least twice in this thread already...)