mamedev / mame

MAME
https://www.mamedev.org/
Other
7.94k stars 1.98k forks source link

Z8530 emulation is not perfect #11607

Open colinleroy opened 11 months ago

colinleroy commented 11 months ago

MAME version

ecdce6505c499531ceb3c4b70c7d59db78e8125b

System information

Linux x86_64

INI configuration details

No response

Emulated system/software

apple2gs (r0, r1, r3)

Incorrect behaviour

It seems like the Z8530-based SCC serial ports in the Apple IIgs are more strict about how one accesses its configuration registers than MAME.

I recently developed a cc65 driver for this chip, and MAME helped me greatly in the process. Initial tests on real hardware showed that the driver worked, so I continued developing using MAME.

At some point the driver failed to work on the real hardware. After investigating, I figured out that the change breaking it was my implementing of choosing between the two channels.

For this, I was accessing SCCBREG,x with X=0 or X=1. It seems like it should be exactly the same as accessing SCCBREG or SCCAREG, but for the real hardware, it is not : the SCC doesn't seem to take its configuration into account, which leads (on my test software) to a hard lockup as soon as one tries to send one byte out.

I have uploaded a test case at https://www.colino.net/tmp/Z8530-tests.tar.gz

It is three versions of the same "telnet" client, compiled with minimal changes in the driver (which is included for clarity).

tests/working/telnet-iigs.dsk works both in MAME and on bare metal tests/indexed/telnet-iigs.dsk works in MAME, but locks up real hardware tests/slow-direct/telnet-iigs.dsk works both in MAME and on bare metal. I included it to verify whether the problem was a delay between both writes, or the indexed addressing.

To test with the provided disks images, configure a terminal client to 9600 8n1 on the other end of the serial cable; boot telnet-iigs.dsk, Use Open-Apple + S for direct serial communication (then Y or n for CRLF translation, it's irrelevant to the test). Type some keys on the IIgs (either MAME or real) and they appear on the other terminal client, and vice-versa. with the "indexed" version, the real IIgs locks up.

Expected behaviour

Change the Z8530 emulation so that it silently fails to take its configuration when accessed in indexed addressing mode?

Seriously I didn't even have any idea that this made a difference, apart for the extra CPU cycle. Knowledgeable people on an Apple II chat explained to me that the 65816 performs a double-read when loading in indexed mode (like lda $nnnn,X) and a read-write for sta $nnnn,x. This may well be the cause of that behaviour on real hardware.

Steps to reproduce

No response

Additional details

No response

rb6502 commented 11 months ago

The folks on the chat are correct. On the original 6502, accessing softswitches with absolute indexed addressing mode causes false reads/writes (I think it's a read then a write on writes, and a double-read on reads). This was fixed in the 65C02 and then put back in the 65816. Bill Mensch claimed he put it back because it affected the Disk II, but no such issues were ever observed on the enhanced IIe or IIc.

MAME's 65816 is a "known needs rewrite" thing; it's accurate at a "runs lots of software perfectly fine across IIgs, SNES, and Acorn Communicator" level but these kinds of sub-instruction behaviors aren't present. By contrast, our 6502 and 65C02 are cycle-perfect to real hardware and can be halted in the middle of an instruction with all state correct, but unlike those chips nobody's reverse-engineered a schematic from die photos of the '816. At least as far as I know.

ajrhacker commented 11 months ago

I also took a look at the 65816 datasheet, and this does seems to be a dummy read issue. Interestingly, these dummy reads are not supposed to be inserted for the absolute long indexed mode, and they can also be suppressed if the hardware observes the VDA and VPA lines more assiduously than Apple apparently did. (The original NMOS 6502 actually performs dummy writes of the original data for read-modify-write opcodes, but the CMOS versions changed all dummy cycles to be read cycles.)