Bingo. I got the multiplication to match the behaviour of real hardware. Writing to WRMPYB will:
- always clear RDMPY
- but only starts a new multiplication if the current multiplication is complete (> 8 cycles)
- update RDDIV with WRMPYB & WRMPYA if the current multiplication is complete or on its last cycle (> 7 cycles).
Consequently, writing at cycle 8 is the special case as the multiplcation is not started and RDDIV only gets updated once with WRMPYB & WRMPYA.
Let's move on to the division now.
Writing $4203 twice too fast gives erroneous result (not emulated)
Moderator: Moderators
Forum rules
- For making cartridges of your Super NES games, see Reproduction.
-
- Posts: 32
- Joined: Thu Jan 24, 2019 1:35 am
-
- Posts: 32
- Joined: Thu Jan 24, 2019 1:35 am
Re: Writing $4203 twice too fast gives erroneous result (not emulated)
Division is a bit more straight forward. Writing to WRDIVB:
- always writes WRDIV to RDMPY thus can alter/corrupt results when division is active
- but only starts a new division if division is complete (>16 cycles)
- always writes WRDIV to RDMPY thus can alter/corrupt results when division is active
- but only starts a new division if division is complete (>16 cycles)
Re: Writing $4203 twice too fast gives erroneous result (not emulated)
It would be greatly appreciated from those making test roms to make them colored pass/fail tests. It's just a lot easier than trying to keep track of screenshots when there are so many other test roms to collect and backtest.
- rainwarrior
- Posts: 8732
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Writing $4203 twice too fast gives erroneous result (not emulated)
These are exploratory test ROMs, not emulator verification tests. They're for testing a wide variety of inputs to gather information about what was going on.
Once we have better information about the effect and how it works, and how to emulate it, then it makes sense to make an emulator test ROM as well.
We need both of those things.
Once we have better information about the effect and how it works, and how to emulate it, then it makes sense to make an emulator test ROM as well.
We need both of those things.
Re: Writing $4203 twice too fast gives erroneous result (not emulated)
Thanks regiscaelus for that explanation. That made it easy for me to create a draft solution for my fork of bsnes, which I'll commit once I am confident in it and have made it less hacky.
Myself086: I am occasionally having a blank screen or very wrong colours in both the original bsnes (in accuracy mode) and my fork with your test ROM. I am not sure if this is an issue with the ROM or bsnes.
Code: Select all
diff --git a/src/cpu.cpp b/src/cpu.cpp
index ca9fb07..e2e9e62 100644
--- a/src/cpu.cpp
+++ b/src/cpu.cpp
@@ -502,8 +502,11 @@ void CPU::writeCPU(unsigned addr, uint8_t data) {
io.wrmpyb = data;
io.rddiv = io.wrmpyb << 8 | io.wrmpya;
- alu.mpyctr = 8; //perform multiplication over the next eight cycles
- alu.shift = io.wrmpyb;
+ if (!alu.mpylast) {
+ alu.mpyctr = 8; //perform multiplication over the next eight cycles
+ alu.shift = io.wrmpyb;
+ }
+
return;
case 0x4204: //WRDIVL
@@ -518,10 +521,11 @@ void CPU::writeCPU(unsigned addr, uint8_t data) {
io.rdmpy = io.wrdiva;
if(alu.mpyctr || alu.divctr) return;
- io.wrdivb = data;
-
- alu.divctr = 16; //perform division over the next sixteen cycles
- alu.shift = io.wrdivb << 16;
+ if (!alu.divlast) {
+ io.wrdivb = data;
+ alu.divctr = 16; //perform division over the next sixteen cycles
+ alu.shift = io.wrdivb << 16;
+ }
return;
case 0x4207: //HTIMEL
@@ -772,13 +776,19 @@ void CPU::scanline() {
void CPU::aluEdge() {
if(alu.mpyctr) {
--alu.mpyctr;
+ if (!alu.mpyctr)
+ alu.mpylast = 1;
if(io.rddiv & 1) io.rdmpy += alu.shift;
io.rddiv >>= 1;
alu.shift <<= 1;
}
+ else
+ alu.mpylast = 0;
if(alu.divctr) {
--alu.divctr;
+ if (!alu.divctr)
+ alu.divlast = 1;
io.rddiv <<= 1;
alu.shift >>= 1;
if(io.rdmpy >= alu.shift) {
@@ -786,6 +796,8 @@ void CPU::aluEdge() {
io.rddiv |= 1;
}
}
+ else
+ alu.divlast = 0;
}
void CPU::dmaEdge() {
diff --git a/src/cpu.hpp b/src/cpu.hpp
index f48f400..2d0752a 100644
--- a/src/cpu.hpp
+++ b/src/cpu.hpp
@@ -194,7 +194,9 @@ private:
struct ALU {
unsigned mpyctr = 0;
+ unsigned mpylast = 0;
unsigned divctr = 0;
+ unsigned divlast = 0;
unsigned shift = 0;
} alu;
Last edited by carmiker on Wed Aug 31, 2022 4:27 pm, edited 3 times in total.