lgblgblgb / xemu

Emulations (running on Linux/Unix/Windows/macOS, utilizing SDL2) of some - mainly - 8 bit machines, including the Commodore LCD, Commodore 65, and the MEGA65 as well.
https://github.com/lgblgblgb/xemu/wiki
GNU General Public License v2.0
208 stars 32 forks source link

MEGA65: fix FDC/SD buffer memory mappings #319

Closed lgblgblgb closed 2 years ago

lgblgblgb commented 2 years ago

Make MEGA65's FDC emulation more correct for memory mapping point of view:

  1. The buffer at $FFD6XXX is 4K in size, but unless in hypervisor mode, either only SD or FDC buffer can be seen there repeated (4K/512 = 8 times). The selection is done by $D689.7
  2. In hypervisor mode $FFD6XXX can be addressed freely to access any of the 4K (no repeated images) and FDC and SD buffers have distinct places: offset $C00 for FDC, and offset $E00 for SD (XXX=...).
  3. There is a special I/O mapped mode, when the the last 512 byte of the "legacy I/O map" shows an 512 byte buffer, unless 2K colour RAM option is used, which overrides it. Again, the $D689.7 bit selects which can be seen there.

Xemu/MEGA65 status

Plan

Do what it "should do" later maybe adjust to MEGA65 depending if it's really buggy here, how it is fixed, etc ...

lgblgblgb commented 2 years ago

Current code in Xemu (now for reading, writing is similar) for buffer access:

DEFINE_READER(disk_buffers_reader) {
#if 1
        return disk_buffers[GET_READER_OFFSET()];
#else
        if (in_hypervisor)
                return disk_buffers[GET_READER_OFFSET()];
        else
                return disk_buffers[(GET_WRITER_OFFSET() & 0x1FF) + ((sd_reg9 & 0x80) ? SD_BUFFER_POS : FD_BUFFER_POS)];
#endif
}

As it can be seen, about the right behaviour (according to MEGA65 doc) is implemented, however not that version is used currently!

For the I/O mapping:

                        if (vic_registers[0x30] & 1)
                                return colour_ram[addr - 0x3800];
                        if (XEMU_LIKELY(sd_status & SD_ST_MAPPED))
                                return sd_buffer[addr - 0x3E00];
                        return 0xFF;    // I/O exp is not supported

So, it's fixed that SD buffer can be mapped only into the I/O space.

lgblgblgb commented 2 years ago

I did the modification in Xemu, however disk buffer mapping into the I/O space (from $DE00, 512 bytes, when enabled with sd-ctrl command $81) is unclear how it supposed to work. Till now, Xemu always mapped the SD buffer only regardless of hypervisor mode or not or SD-ctrl reg 9 bit 7 status. It worked fine with hyppo, but surely, it makes impossible to write a program which intended to I/O map the FD disk buffer instead of the SD ... Note, Bit Shifter also had problems with this, on the hardware as well, though maybe not the very same kind of issue.

Now, with my Xemu modification to take in account bit 7 of SD-ctrl reg 9 (as it supposed to be?), breaks hyppo, if user space alters that reg 9, as it causes that hyppo happily think that the I/O mapped disk buffer still means SD, even if it's already FD, and just trying to do HDOS service SD communication with using the FD buffer actually ... So I'm not sure what's going on, how it supposed to work. Some possibilities:

  1. hyppo is buggy, and forgot to set reg 9 bit 7 to be sure, SD disk buffer is being used
  2. I should assume that in hypervisor mode, I/O mapping of the disk buffer always the SD buffer regardless of the reg 9 bit 7 status??
  3. vhdl is buggy ... and just hyppo relies on that, it is not even possible even in non-hypervisor mode to map the FD buffer
  4. something completely different ...
lgblgblgb commented 2 years ago

Solutions as workarounds:

  1. In hypervisor mode only SD-buffer can be I/O mapped
  2. In any mode, only SD-buffer can be I/O mapped

The safer method is the second, since this what Xemu did in the past, without too much noticed problem, even if it's not correct. Though this should be checked, and as I've written already, this is maybe buggy on MEGA65 itself, too (see the MEGA65 issue, mentioned).