sfc: implementation of SA-1 BW-RAM protection (#1409)

This PR is a change to pass the [SA-1 RAM protection
test](https://github.com/absindx/SNES-TestRoms/tree/main/SA1RamProtectionTest).

---
242e2fd1a1b373c229818ce0b473bfa5aaf07f63

BW-RAM protection was not implemented to make Kirby's Dream Land 3 work.
[Reference: Near's post
(nesdev)](https://forums.nesdev.org/viewtopic.php?p=237733#p237733)

This commit implements the conditions under which BW-RAM protection
works as determined from hardware testing.
* BW-RAM Protection will not be reflected unless protection is enabled
on both SNES and SA-1.
  * KDL3 sets `CWEN=0`, but `SWEN=80`. not protected.
* `$2228 BWPA` is a register for the SNES CPU, but it also affects the
SA-1 protection area.

---
654f5f02cef6e390f63c9da39c970bf07446e2e0

Change the BW-RAM mapping range from $400000-$4FFFFF to $400000-$5FFFFF.
[Reference: SA-1 Hardware Behavior -
SnesLab](https://sneslab.net/wiki/SA-1_Hardware_Behavior#BW-RAM)

---
aa1da58d8bb5db1903b8faec668957eb2b6c414d

Initialize the following at SA-1 reset. (change `$2200 CCNT.RESB` 1 to
0)
* CPU data bank register
* CPU stop flag
* IO `$222A CIWP` register

NOTE: The timing of when these registers are reset is unknown because
they cannot be observed in a stopped SA-1 CPU.
I include todo as a reminder that there are many unknown behaviors. I'll
delete it if it's not needed.

KDL3 restarts the SA-1 CPU several times on the title screen.
Before this change, KDL3(JPN: Hoshi no Kirby 3, SHA-1:
`5038596a1ec450d8f1d7cc07759737bfd996e87f`) was not restarting properly:
```log
SA1  008294  sei                              A:0000 X:0000 Y:0000 S:01ff D:0000 B:00 nv1BdIzc
SA1  008295  clc                              A:0000 X:0000 Y:0000 S:01ff D:0000 B:00 nv1BdIzc
SA1  008296  xce                              A:0000 X:0000 Y:0000 S:01ff D:0000 B:00 nv1BdIzc
# (snip)
SA1  0082b1  lda #$ff                         A:0000 X:0000 Y:0000 S:01ff D:0000 B:00 nvMXdIZC
SA1  0082b3  sta $222a              [00222a]  A:00ff X:0000 Y:0000 S:01ff D:0000 B:00 NvMXdIzC # B:00 ... write to CIWP
# (snip)
SA1  0082cf  pea $4040              [004040]  A:3600 X:37ff Y:3800 S:37ff D:3600 B:00 nvmxdIzC
SA1  0082d2  plb                              A:3600 X:37ff Y:3800 S:37fd D:3600 B:00 nvmxdIzC
SA1  0082d3  plb                              A:3600 X:37ff Y:3800 S:37fe D:3600 B:40 nvmxdIzC
# (snip)
[Omitted: 3303247]
# reboot from SNES CPU (CCNT.RESB)
SA1  008294  sei                              A:0000 X:37ff Y:3800 S:37ff D:3600 B:40 nvmxdIZC
SA1  008295  clc                              A:0000 X:37ff Y:3800 S:37ff D:3600 B:40 nvmxdIZC
SA1  008296  xce                              A:0000 X:37ff Y:3800 S:37ff D:3600 B:40 nvmxdIZc
SA1  008297  sep #$20                         A:0000 X:37ff Y:3800 S:37ff D:3600 B:40 nvmxdIZc
# (snip)
SA1  0082b1  lda #$ff                         A:0000 X:37ff Y:3800 S:37ff D:3600 B:40 nvMxdIZc
SA1  0082b3  sta $222a              [40222a]  A:00ff X:37ff Y:3800 S:37ff D:3600 B:40 NvMxdIzc # B:40 ... write to incorrect address ($40222a = BW-RAM)
```
The data bank register `B` has not been reset and an access to a
different address is occurring.

Although not related to BW-RAM protection, other registers probably need
to be reset as well.
Further hardware testing is required.

---

These commits boot KDL3 with BW-RAM protection implemented.
このコミットが含まれているのは:
absindx 2024-02-29 23:08:18 +09:00 committed by GitHub
コミット 70f361094b
この署名に対応する既知のキーがデータベースに存在しません
GPGキーID: B5690EEEBB952194
3個のファイルの変更22行の追加9行の削除

ファイルの表示

@ -37,7 +37,8 @@ auto SA1::BWRAM::writeCPU(n24 address, n8 data) -> void {
address = sa1.io.sbm * 0x2000 + (address & 0x1fff);
}
if(!sa1.io.swen && (n18)address < 0x100 << sa1.io.bwp) return;
//note: BW-RAM protection works only when both SWEN and CWEN are disabled.
if(!sa1.io.swen && !sa1.io.cwen && (n18)address < 0x100 << sa1.io.bwp) return;
return write(address, data);
}
@ -53,11 +54,6 @@ auto SA1::BWRAM::readSA1(n24 address, n8 data) -> n8 {
}
}
//note: CWEN is not emulated, as it breaks Kirby's Dream Land 3:
//* BWPA = 02 (protect 400000-4003ff)
//* CWEN = 00 (writes disabled)
//KDL3 proceeds to write to 4001ax and 40032x which must succeed.
auto SA1::BWRAM::writeSA1(n24 address, n8 data) -> void {
if(sa1.io.sw46 == 0) {
//$40-43:0000-ffff x 32 projection
@ -75,6 +71,15 @@ auto SA1::BWRAM::readLinear(n24 address, n8 data) -> n8 {
}
auto SA1::BWRAM::writeLinear(n24 address, n8 data) -> void {
//note: BW-RAM protection works only when both SWEN and CWEN are disabled.
//this is required for Kirby's Dream Land 3 to work:
//* BWPA = 02 (protect 400000-4003ff)
//* SWEN = 80 (writes enabled)
//* CWEN = 00 (writes disabled)
//KDL3 proceeds to write to 4001ax and 40032x which must succeed.
//note: BWPA also affects SA-1 protection
if(!sa1.io.swen && !sa1.io.cwen && (n18)address < 0x100 << sa1.io.bwp) return;
return write(address, data);
}

ファイルの表示

@ -101,8 +101,16 @@ auto SA1::writeIOCPU(n24 address, n8 data) -> void {
//(CCNT) SA-1 control
case 0x2200:
if(io.sa1_resb && !data.bit(5)) {
//reset SA-1 CPU (PC bank set to 0x00)
//reset SA-1 CPU (PC bank and data bank set to 0x00, clear STP status)
r.pc.d = io.crv;
r.b = 0x00;
r.stp = false;
//todo: probably needs a SA-1 CPU reset
//reset r.s, r.e, r.wai ...
//reset io status
//todo: reset timing is unknown, CIWP is set to 0 at reset
io.ciwp = 0x00;
}
io.smeg = data.bit(0,3);

ファイルの表示

@ -37,7 +37,7 @@ auto SA1::read(n24 address) -> n8 {
}
if((address & 0x40e000) == 0x006000 //00-3f,80-bf:6000-7fff
|| (address & 0xf00000) == 0x400000 //40-4f:0000-ffff
|| (address & 0xe00000) == 0x400000 //40-5f:0000-ffff
|| (address & 0xf00000) == 0x600000 //60-6f:0000-ffff
) {
step();
@ -81,7 +81,7 @@ auto SA1::write(n24 address, n8 data) -> void {
}
if((address & 0x40e000) == 0x006000 //00-3f,80-bf:6000-7fff
|| (address & 0xf00000) == 0x400000 //40-4f:0000-ffff
|| (address & 0xe00000) == 0x400000 //40-5f:0000-ffff
|| (address & 0xf00000) == 0x600000 //60-6f:0000-ffff
) {
step();