Cydrak disassembled the test.
Code: Select all
8f4af0 mov $f0, #$4a ; set timings (modified per test)
8f81f1 mov $f1, #$81 ; enable IPL, timer 0
8f00fa mov $fa, #$00 ; set timer 0
8f0100 mov $00, #$01
8f0001 mov $01, #$00 ; $0000 = 1
e4fd lda $fd ; reset ticks
e800 lda #$00
8d00 ldy #$00
f8fdf0fc -; ldx $fd; beq - ; wait on timer tick
7a00f8fdf0fa -; adw $00; ldx $fd; beq - ; count loops to next tick
8f0af0 mov $f0, #$0a ; restore default timings
daf6 stw $f6 ; post loop results and sync S-CPU
8f55f4 mov $f4, #$55
e8dd64f4d0fc lda #$dd; -; cmp $f4; bne -
5fc0ff jmp $ffc0 ; return to IPL
Here are the expected ranges.
Code: Select all
; TEST loops
; $0a $0a8f <= X < $0ac6
; $1a $0656 <= X < $0677
; $2a $0384 <= X < $0397
; $3a $01dd <= X < $01e6
; $4a $07eb <= X < $0814
; $5a $0548 <= X < $0563
; $6a $032a <= X < $033b
; $7a $01c2 <= X < $01cb
; $ca $032b <= X < $033c
; $da $02a4 <= X < $02b1
; $ea $01fa <= X < $0205
; $fa $0151 <= X < $0158
The problem turned out to be that I missed the (8) footnote on 6d. I probably missed the (9) footnote on 11 as well. It's a little tricky reading this PDF. Here is a crude fix:
Code: Select all
auto SPC700::instructionDirectReadWord(fpw op) -> void {
uint8 address = fetch();
uint16 data = load(address + 0);
if(op == &SPC700::algorithmLDW) load(address + 0);
else idle();
data |= load(address + 1) << 8;
YA = alu(YA, data);
}
(the other MOVW is in DirectWriteWord.)
But anyway, all the tests pass now, hooray!
> Excessive C++ cleverness has bitten you in the back. This code is failing to distinguish between an argument of 0 and no argument, and turning accesses to address 0 (which is RAM) into internal accesses.
Unfortunately, that's not correct.
if(!addr) is testing the explicit operator bool() const of maybe<uint16>, which returns true if the maybe has a value in it, false if it's nothing. It won't see an address of zero until executing *addr to get the underlying value.
> Also, you've changed the order things happen in read() and write(). Before you were doing the read/write and then advancing the timers, now you're advancing the timers and then doing the read/write.
Yeah, we had $2137/$4201 to confirm that difference on the CPU side. It probably exists on the SMP side too, but this new emulation code makes this very difficult. And I'm not even sure when the reads happen when the divider is not set to 0 (or effectively 2 cycles.)
> Remember that the S-DSP outputs a clock to the S-SMP and the S-SMP divides that clock and outputs it back to the S-DSP--it's a mutual interaction.
Ah well. It's not like we're gonna be emulating the chance of crashing with this register anyway :/
> Changing the subject, I just noticed that in higan you're initializing the S-DSP ENDX to random(0), which means that Magical Drop will never work if randomization is disabled. Surely it should be random(0xff) instead (that's what I've done in bsnes-classic).
There's no option to disable randomization currently. I'll keep that in mind though.
It seems you know about the oddities with that title's game over screen. We can make a separate topic to work through that if you'd like. I'm very interested in what's going on there. But again, we'll need to confirm things before I'll make changes, and this one's probably not gonna have an "easy mode" like the SMP courtesy of Overload, heheh.