From 5ed901f72007c3ac2384c0779dbb4574384c49e6 Mon Sep 17 00:00:00 2001 From: TomCh Date: Tue, 9 Nov 2021 21:04:57 +0000 Subject: [PATCH 1/4] Slot-independent HDD firmware (#996, PR #998) . Move the 'read block' command into the emulator - to mirror the write command . With emulated time to do the DMA for the r/w block command --- firmware/HDD/HDDRVR.BIN | Bin 256 -> 256 bytes firmware/HDD/hddrvr.a65 | 322 +++++++++++++++++++++------------------- resource/Hddrvr.bin | Bin 256 -> 256 bytes source/Disk.cpp | 10 +- source/Harddisk.cpp | 96 +++++++++--- source/Harddisk.h | 3 +- 6 files changed, 259 insertions(+), 172 deletions(-) diff --git a/firmware/HDD/HDDRVR.BIN b/firmware/HDD/HDDRVR.BIN index e5c8b10cd4f87153ba8acfc739c3a89f987c990f..6dba71433602115a07d5f3229a0dc2247a90f942 100644 GIT binary patch literal 256 zcmZ3fu##aV^Gcfw_7)o$B{tM%w7O+7ugGY1&t&kJ;jw^mqg$)f2_WGLBHVy{*H-5f zK*9w`c!2Q*I|c@e4M!y=IId)v+k9Yd(}BGW2kIIROyKZgI0lkhwUVLLxz(lBt<`-c zN2}{f##W~bdK(_;Bpxuh>%+(aG|U}nYeuW91xLkFhD8Z&3F(!tt@DDUdhnv z((2agzLKNWbtPk~lS2FP4a;>B4;U<3RN%wNA+gj6XzNmEpshe~DDz*4u~ zZwHpT_kIVt#AB(`NyZDz3OkMi-IS34bOgiN9|tA^?fCJ`6~R8{nz15bqpJtdeh_YT V2f921=&}oQVQxjx|Ld=F0RW*NbKU>| diff --git a/firmware/HDD/hddrvr.a65 b/firmware/HDD/hddrvr.a65 index 3cc089f7..7d69c053 100644 --- a/firmware/HDD/hddrvr.a65 +++ b/firmware/HDD/hddrvr.a65 @@ -26,7 +26,7 @@ ; ; Modified by Tom Charlesworth: -; . Updated so it can be assembled by ACME 0.96.4 +; . Updated so it can be assembled by ACME 0.97 ; . Fixed so that ProDOS entrypoint is $c70a (26 Dev 2007) (Bug #12723) ; . Modified to support Apple Oasis' entrypoint: $c761 (8 Sept 2012) (Feature #5557) ; . Added support for SmartPort entrypoint (20 Oct 2012) @@ -34,10 +34,11 @@ ; . GH#370 (Robert Hoem, 27 Oct 2016): ; . Added a check against open-apple during boot to route boot to slot 6 ; . This happens after the first two blocks are loaded from the HD. -; . GH#319: smartport return address wrong when crossing page +; . GH#319: SmartPort return address wrong when crossing page +; . GH#996: Make code slot-independent (so HDD controller card can go into any slot) +; . Moved the 512-byte block read into AppleWin's HDD emulation (to mirror the block write command) ; TODO: -; . Make code relocatable (so HDD controller card can go into any slot) -; . Remove support for Entrypoint_C746 (old AppleWin) & Entrypoint_C761 (Apple Oasis) +; . Remove support for Entrypoint_Cs46 (old AppleWin) & Entrypoint_Cs61 (Apple Oasis) ; - provide a utility to convert these to use Entrypoint_ProDOS ; . Check SmartPort: Is it OK to trash Y and $42,..,$47 ? ; @@ -47,31 +48,32 @@ !sl "hddrvr.labels" ; constants -hd_execute = $c0f0 -hd_error = $c0f1 -hd_command = $c0f2 -hd_unitnum = $c0f3 -hd_memblock = $c0f4 -hd_diskblock = $c0f6 -hd_nextbyte = $c0f8 +hd_execute = $c080 +hd_error = $c081 ; b7=busy, b0=error +hd_command = $c082 +hd_unitnum = $c083 +hd_memblock = $c084 +hd_diskblock = $c086 +;hd_nextbyte = $c088 ; legacy read-only port (still supported by AppleWin) command = $42 unitnum = $43 memblock = $44 diskblock = $46 -slot6 = $c600 +slot6 = $C600 OS = $0801 BUTTON0 = $C061 -; The Autoboot rom will call this. -; This is also the entry point for such things as IN#7 and PR#7 - -;; code -*= $c700 ; org $c700 +;====================================== !zone code +*= $0000 ; org $0000 - position-independent code, so doesn't matter (but the other fixed org positions need to be on the same page) + +; The Autoboot rom will call this. +; This is also the entry point for such things as IN#7 and PR#7 + start ; Autoboot and ProDOS look at the following few opcodes to detect block devices @@ -83,44 +85,23 @@ start lda #$3C bne Bootstrap -Entrypoint_ProDOS ; $c70a - ProDOS entrypoint +Entrypoint_ProDOS ; $Cn0A - ProDOS entrypoint sec bcs Entrypoint -Entrypoint_SmartPort ; $c70d - SmartPort entrypoint +Entrypoint_SmartPort ; $Cn0D - SmartPort entrypoint clc - -Entrypoint ; $c70e - entrypoint? - bcs cmdproc - bcc SmartPort -;; +Entrypoint ; $Cn0E - entrypoint? + bcs GetSlotInX ; C=1: GetSlotInX -> cmdproc -Bootstrap -; Lets check to see if there's an image ready - lda #$00 - sta hd_command - -; Slot 7, disk 1 - lda #$70 ; Slot# << 4 - sta hd_unitnum - lda hd_execute - -; error capturing code. Applewin is picky -; about code assigning data to registers and -; memory. The safest method is via I/O port - ror hd_error ; Post: C=0 or 1 - bcc hdboot - -; no image ready, boot diskette image instead -BootSlot6 - jmp slot6 + ; C=0: fall through to SmartPort... ;====================================== ; TODO: Is it OK to trash Y and $42,..,$47 ? -; Pre: C=0 -SmartPort +; Pre: C=0, X = Slot# << 4 +SmartPort ; SmartPort -> GetSlotInX -> cmdproc pla sta $46 adc #3 ; Pre: C=0, Post: C=0 or 1 @@ -136,24 +117,7 @@ SmartPort lda ($46),y ; cmd sta $42 iny - bne SmartPort2 -;====================================== -; 8 unused bytes - -*= $c746 ; org $c746 - -Entrypoint_C746 ; Old f/w 'cmdproc' entrypoint - ; Keep this for any DOSMaster HDD images created with old AppleWin HDD f/w. - ; DOSMaster hardcodes the entrypoint addr into its bootstrapping code: - ; - So DOSMaster images are tied to the HDD's controller's f/w - sec - bcs Entrypoint - -;====================================== - -; Pre: Y=2 -SmartPort2 lda ($46),y ; param_l sta $45 iny @@ -164,31 +128,76 @@ SmartPort2 lda ($45),y ; unit sta $43 iny + lda ($45),y ; memblock_l sta $44 iny - bne SmartPort3 + lda ($45),y ; memblock_h + pha + iny + + lda ($45),y ; diskblock_l + pha + iny + + bne SmartPort2 ;====================================== -; 1 unused byte - -*= $c761 ; org $c761 +; 2 unused bytes -Entrypoint_C761 ; Apple Oasis HDD controller entrypoint +@checkCs46 +*= $0046 ; org $0046 +!warn "Cs46 padding = ", * - @checkCs46 + +Entrypoint_Cs46 ; Old f/w 'cmdproc' entrypoint + ; Keep this for any DOSMaster HDD images created with old AppleWin HDD f/w. + ; DOSMaster hardcodes the entrypoint addr into its bootstrapping code: + ; - So DOSMaster images are tied to the HDD's controller's f/w + sec + bcs Entrypoint ; or directly to GetSlotInX + +;====================================== + +Bootstrap +; Lets check to see if there's an image ready +; Slot n, disk 1 + clc + bcc GetSlotInX ; Post: X = Slot# << 4 +Bootstrap2 + lda #$00 + sta hd_unitnum,x ; b7=0 => disk 1 + sta hd_command,x + lda hd_execute,x + ror hd_error,x ; Post: C=0 or 1 + bcc hdboot + +; no image ready, boot diskette image instead +BootSlot6 + jmp slot6 + +;====================================== +; 2 unused bytes + +@checkCs61 +*= $0061 ; org $0061 +!warn "Cs61 padding = ", * - @checkCs61 + +Entrypoint_Cs61 ; Apple Oasis HDD controller entrypoint ; Keep this for any DOSMaster HDD images created with Apple Oasis HDD f/w. ; DOSMaster hardcodes the entrypoint addr into its bootstrapping code: ; - So DOSMaster images are tied to the HDD's controller's f/w sec - bcs Entrypoint + bcs Entrypoint ; or directly to GetSlotInX ;====================================== ; image ready. Lets boot from it. -; we want to load block 1 from s7,d1 to $800 then jump there +; we want to load block 1 from disk 1 to $800 then jump there +; Pre: X = Slot# << 4 +; C = 0 hdboot - lda #$70 ; Slot# << 4 - sta unitnum lda #$0 + sta unitnum ; b7=0 => disk 1 sta memblock sta diskblock sta diskblock+1 @@ -196,101 +205,109 @@ hdboot sta memblock+1 lda #$1 sta command - jsr cmdproc + bne cmdproc +hdboot2 bcs BootSlot6 -goload - bit BUTTON0 ; button 0 pressed? + bit BUTTON0 ; button 0 pressed? bmi BootSlot6 -; X=device - ldx #$70 ; Slot# << 4 +; Pre: X = Slot# << 4 jmp OS -; entry point for ProDOS' block driver -; simple really. Copy the command from $42..$47 -; to our I/O ports then execute command -cmdproc - clc - lda $42 - sta hd_command - lda $43 - sta hd_unitnum - lda $44 - sta hd_memblock - lda $45 - sta hd_memblock+1 - lda $46 - sta hd_diskblock - lda $47 - sta hd_diskblock+1 - lda hd_execute - -; check for error - pha - lda command - cmp #1 - bne skipSread - jsr sread -skipSread - ror hd_error ; Post: C=0 or 1 - pla - rts - - -; if there's no error, then lets read the block into memory -; because Applewin is picky about memory management, here's what I did: -; on read, hd_nextbyte = buffer[0], therefore we'll read that byte 256 times (in which -; the emulated code increments the buffer by 1 on each read) to (memblock),y -; increment memblock+1 and read the second 256 bytes via hd_nextbyte. -; -; if I could figure out how to consistently get applewin to update it's memory regions all -; this code can be moved into the emulation code (although, this is how I'd build the hardware -; anyway...) - -sread - tya - pha - ldy #0 -loop1 - lda hd_nextbyte - sta (memblock),y - iny - bne loop1 - inc memblock+1 - ldy #0 -loop2 - lda hd_nextbyte - sta (memblock),y - iny - bne loop2 - dec memblock+1 ; restore memblock+1 ($45) to original value (for Epyx's California Games) - pla - tay - rts - ;====================================== -SmartPort3 - lda ($45),y ; memblock_h - pha - iny - lda ($45),y ; diskblock_l - pha - iny +SmartPort2 lda ($45),y ; diskblock_h sta $47 - + pla sta $46 pla sta $45 - - iny - bne cmdproc + + sec + ; fall through... ;====================================== -; 18 unused bytes + +; Pre: +; C=0 => via Bootstrap +; C=1 => via Entrypoint / SmartPort2 +; Post: +; X = Slot# << 4 +GetSlotInX + php + sei ; disable ints, in case an int handler races our $0000/RTS and stack accesses! + + ; NB. need RAM that's guaranteed to be both read & writeable: + ; . can't use $0200-$BFFF, due to eg. RAMRD=0/RAMWRT=1 combination + ; . can't use LC as ROM might be enabled. + ; So use ZP (specifically $0000) as whatever the state of ALTZP, both read & write will be to the same physical memory location. + lda $00 ; save $00 + ldx #$60 ; opcode RTS + stx $00 + jsr $0000 ; RTS immediately (NB. can't use $FF58, since LC RAM may be switched in) + sta $00 ; restore $00 + tsx + lda $0100,x ; $Cn + asl + asl + asl + asl + tax ; X=$n0 + + plp ; + restore int status + bcc Bootstrap2 + ; otherwise fall through for Entrypoint / SmartPort... + +;-------------------------------------- + +; entry point for ProDOS' block driver +; simple really. Copy the command from $42..$47 +; to our I/O ports then execute command + +; Pre: +; C=0 => via Bootstrap (hdboot) +; C=1 => via GetSlotInX (eg. Entrypoint / SmartPort2) +; X = Slot# << 4 +; Post: +; C = hd_error.b0 +; A = result of hd_execute +; X = Slot# << 4 +cmdproc + php + + lda command + sta hd_command,x + lda unitnum + sta hd_unitnum,x + lda memblock + sta hd_memblock,x + lda memblock+1 + sta hd_memblock+1,x + lda diskblock + sta hd_diskblock,x + lda diskblock+1 + sta hd_diskblock+1,x + lda hd_execute,x ; A = result of hd_execute (NB. instantaneous 512 byte r/w!) + +- rol hd_error,x ; b7=busy doing DMA? + bcs - + + plp ; restore C from start of cmdproc + bcs done + ror hd_error,x ; Post: C=0 or 1 + lda #0 + beq hdboot2 + +done + ror hd_error,x ; Post: C=0 or 1 + rts + +;====================================== + +; 33 unused bytes !zone data @@ -309,7 +326,10 @@ SmartPort3 ; datablock. This starts near the end of the firmware (at offset $FC) ;; data -*= $c7fc ; org $c7fc +@checkCsFC +*= $00FC ; org $00FC +!warn "CsFC padding = ", * - @checkCsFC + !word $7fff ; how many blocks are on the device. !byte $D7 ; specifics about the device (number of drives, read/write/format capability, etc) !byte %+(aG|U}nYeuW91xLkFhD8Z&3F(!tt@DDUdhnv z((2agzLKNWbtPk~lS2FP4a;>B4;U<3RN%wNA+gj6XzNmEpshe~DDz*4u~ zZwHpT_kIVt#AB(`NyZDz3OkMi-IS34bOgiN9|tA^?fCJ`6~R8{nz15bqpJtdeh_YT V2f921=&}oQVQxjx|Ld=F0RW*NbKU>| diff --git a/source/Disk.cpp b/source/Disk.cpp index 4aa084d3..8e7c3a7a 100644 --- a/source/Disk.cpp +++ b/source/Disk.cpp @@ -178,11 +178,17 @@ void Disk2InterfaceCard::LoadLastDiskImage(const int drive) char pathname[MAX_PATH]; std::string& regSection = RegGetConfigSlotSection(m_slot); - if (RegLoadString(regSection.c_str(), regKey.c_str(), TRUE, pathname, MAX_PATH, TEXT(""))) + if (RegLoadString(regSection.c_str(), regKey.c_str(), TRUE, pathname, MAX_PATH, TEXT("")) && (pathname[0] != 0)) { m_saveDiskImage = false; - InsertDisk(drive, pathname, IMAGE_USE_FILES_WRITE_PROTECT_STATUS, IMAGE_DONT_CREATE); + ImageError_e error = InsertDisk(drive, pathname, IMAGE_USE_FILES_WRITE_PROTECT_STATUS, IMAGE_DONT_CREATE); m_saveDiskImage = true; + + if (error != eIMAGE_ERROR_NONE) + { + NotifyInvalidImage(drive, pathname, error); + EjectDisk(drive); + } } } diff --git a/source/Harddisk.cpp b/source/Harddisk.cpp index cce0cfc2..896f38ab 100644 --- a/source/Harddisk.cpp +++ b/source/Harddisk.cpp @@ -125,6 +125,9 @@ HarddiskInterfaceCard::HarddiskInterfaceCard(UINT slot) : // . ProDOS will write to Command before switching drives m_command = 0; + // Interface busy doing DMA for r/w when current cycle is earlier than this cycle + m_notBusyCycle = 0; + m_saveDiskImage = true; // Save the DiskImage name to Registry // if created by user in Config->Disk, then MemInitializeIO() won't be called @@ -190,7 +193,20 @@ void HarddiskInterfaceCard::CleanupDrive(const int iDrive) void HarddiskInterfaceCard::NotifyInvalidImage(TCHAR* pszImageFilename) { - // TC: TO DO + // TC: TO DO - see Disk2InterfaceCard::NotifyInvalidImage() + + char szBuffer[MAX_PATH + 128]; + + StringCbPrintf( + szBuffer, + MAX_PATH + 128, + TEXT("Unable to open the file %s."), + pszImageFilename); + + GetFrame().FrameMessageBox( + szBuffer, + g_pAppTitle.c_str(), + MB_ICONEXCLAMATION | MB_SETFOREGROUND); } //=========================================================================== @@ -206,11 +222,17 @@ void HarddiskInterfaceCard::LoadLastDiskImage(const int drive) char pathname[MAX_PATH]; std::string& regSection = RegGetConfigSlotSection(m_slot); - if (RegLoadString(regSection.c_str(), regKey.c_str(), TRUE, pathname, MAX_PATH, TEXT(""))) + if (RegLoadString(regSection.c_str(), regKey.c_str(), TRUE, pathname, MAX_PATH, TEXT("")) && (pathname[0] != 0)) { m_saveDiskImage = false; - Insert(drive, pathname); + bool res = Insert(drive, pathname); m_saveDiskImage = true; + + if (!res) + { + NotifyInvalidImage(pathname); + CleanupDrive(drive); + } } } @@ -309,10 +331,10 @@ void HarddiskInterfaceCard::Destroy(void) //=========================================================================== // Pre: pathname likely to include path (but can also just be filename) -BOOL HarddiskInterfaceCard::Insert(const int iDrive, const std::string& pathname) +bool HarddiskInterfaceCard::Insert(const int iDrive, const std::string& pathname) { if (pathname.empty()) - return FALSE; + return false; if (m_hardDiskDrive[iDrive].m_imageloaded) Unplug(iDrive); @@ -429,8 +451,8 @@ bool HarddiskInterfaceCard::IsDriveUnplugged(const int iDrive) //=========================================================================== #define DEVICE_OK 0x00 -#define DEVICE_UNKNOWN_ERROR 0x28 #define DEVICE_IO_ERROR 0x27 +#define DEVICE_NOT_CONNECTED 0x28 // No device detected/connected BYTE __stdcall HarddiskInterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles) { @@ -438,6 +460,9 @@ BYTE __stdcall HarddiskInterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BY HarddiskInterfaceCard* pCard = (HarddiskInterfaceCard*)MemGetSlotParameters(slot); HardDiskDrive* pHDD = &(pCard->m_hardDiskDrive[pCard->m_unitNum >> 7]); // bit7 = drive select + CpuCalcCycles(nExecutedCycles); + const UINT CYCLES_FOR_DMA_RW_BLOCK = HD_BLOCK_SIZE; + BYTE r = DEVICE_OK; pHDD->m_status_next = DISK_STATUS_READ; @@ -466,7 +491,31 @@ BYTE __stdcall HarddiskInterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BY { pHDD->m_error = 0; r = 0; + pCard->m_notBusyCycle = g_nCumulativeCycles + (UINT64)CYCLES_FOR_DMA_RW_BLOCK; pHDD->m_buf_ptr = 0; + + // Apple II's MMU could be setup so that read & write memory is different, + // so can't use 'mem' (like we can for HDD block writes) + const UINT PAGE_SIZE = 256; + WORD dstAddr = pHDD->m_memblock; + UINT remaining = HD_BLOCK_SIZE; + BYTE* pSrc = pHDD->m_buf; + + while (remaining) + { + memdirty[dstAddr >> 8] = 0xFF; + LPBYTE page = memwrite[dstAddr >> 8]; + + // handle both page-aligned & non-page aligned destinations + UINT size = PAGE_SIZE - (dstAddr & 0xff); + if (size > remaining) size = remaining; // clip the last memcpy for the unaligned case + + memcpy(page + (dstAddr & 0xff), pSrc, size); + pSrc += size; + dstAddr += size; + + remaining -= size; + } } else { @@ -501,7 +550,7 @@ BYTE __stdcall HarddiskInterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BY } } - memmove(pHDD->m_buf, mem+pHDD->m_memblock, HD_BLOCK_SIZE); + memcpy(pHDD->m_buf, mem + pHDD->m_memblock, HD_BLOCK_SIZE); if (bRes) bRes = ImageWriteBlock(pHDD->m_imagehandle, pHDD->m_diskblock, pHDD->m_buf); @@ -510,6 +559,7 @@ BYTE __stdcall HarddiskInterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BY { pHDD->m_error = 0; r = 0; + pCard->m_notBusyCycle = g_nCumulativeCycles + (UINT64)CYCLES_FOR_DMA_RW_BLOCK; } else { @@ -527,16 +577,19 @@ BYTE __stdcall HarddiskInterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BY { pHDD->m_status_next = DISK_STATUS_OFF; pHDD->m_error = 1; - r = DEVICE_UNKNOWN_ERROR; + r = DEVICE_NOT_CONNECTED; // GH#452 } break; case 0x1: // m_error - pHDD->m_status_next = DISK_STATUS_OFF; // TODO: FIXME: ??? YELLOW ??? WARNING - if (pHDD->m_error) - { - _ASSERT(pHDD->m_error & 1); - pHDD->m_error |= 1; // Firmware requires that b0=1 for an error - } + if (pHDD->m_error & 0x7f) + pHDD->m_error = 1; // Firmware requires that b0=1 for an error + else + pHDD->m_error = 0; + + if (g_nCumulativeCycles <= pCard->m_notBusyCycle) + pHDD->m_error |= 0x80; // Firmware requires that b7=1 for busy (eg. busy doing r/w DMA operation) + else + pHDD->m_status_next = DISK_STATUS_OFF; // TODO: FIXME: ??? YELLOW ??? WARNING r = pHDD->m_error; break; @@ -558,7 +611,7 @@ BYTE __stdcall HarddiskInterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BY case 0x7: r = (BYTE)(pHDD->m_diskblock & 0xFF00 >> 8); break; - case 0x8: + case 0x8: // Legacy: continue to support this I/O port for old HDD firmware r = pHDD->m_buf[pHDD->m_buf_ptr]; if (pHDD->m_buf_ptr < sizeof(pHDD->m_buf)-1) pHDD->m_buf_ptr++; @@ -649,8 +702,10 @@ bool HarddiskInterfaceCard::ImageSwap(void) //=========================================================================== // Unit version history: -// 2: Updated $Csnn firmware to fix GH#319 -static const UINT kUNIT_VERSION = 2; +// 2: Updated $C7nn firmware to fix GH#319 +// 3: Updated $Csnn firmware to fix GH#996 (now slot-independent code) +// Added: Not Busy Cycle +static const UINT kUNIT_VERSION = 3; #define SS_YAML_VALUE_CARD_HDD "Generic HDD" @@ -667,6 +722,7 @@ static const UINT kUNIT_VERSION = 2; #define SS_YAML_KEY_STATUS_PREV "Status Prev" #define SS_YAML_KEY_BUF_PTR "Buffer Offset" #define SS_YAML_KEY_BUF "Buffer" +#define SS_YAML_KEY_NOT_BUSY_CYCLE "Not Busy Cycle" std::string HarddiskInterfaceCard::GetSnapshotCardName(void) { @@ -700,6 +756,7 @@ void HarddiskInterfaceCard::SaveSnapshot(YamlSaveHelper& yamlSaveHelper) YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE); yamlSaveHelper.Save("%s: %d # b7=unit\n", SS_YAML_KEY_CURRENT_UNIT, m_unitNum); yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_COMMAND, m_command); + yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_NOT_BUSY_CYCLE, m_notBusyCycle); SaveSnapshotHDDUnit(yamlSaveHelper, HARDDISK_1); SaveSnapshotHDDUnit(yamlSaveHelper, HARDDISK_2); @@ -777,12 +834,15 @@ bool HarddiskInterfaceCard::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT sl if (version < 1 || version > kUNIT_VERSION) throw std::string("Card: wrong version"); - if (version == 1 && (regs.pc >> 8) == (0xC0|slot)) + if (version <= 2 && (regs.pc >> 8) == (0xC0|slot)) throw std::string("HDD card: 6502 is running old HDD firmware"); m_unitNum = yamlLoadHelper.LoadUint(SS_YAML_KEY_CURRENT_UNIT); // b7=unit m_command = yamlLoadHelper.LoadUint(SS_YAML_KEY_COMMAND); + if (version >= 3) + m_notBusyCycle = yamlLoadHelper.LoadUint64(SS_YAML_KEY_NOT_BUSY_CYCLE); + // Unplug all HDDs first in case HDD-2 is to be plugged in as HDD-1 for (UINT i=0; i Date: Thu, 11 Nov 2021 21:20:54 +0000 Subject: [PATCH 2/4] Add comments to both Harddisk.cpp & the firmware code about 'sta abs16,x' false-reads, etc. Harddisk.cpp: Fix typos and update the notes on the r/w commands' operation. --- firmware/HDD/hddrvr.a65 | 18 ++++++++++++------ source/Harddisk.cpp | 42 +++++++++++++++++++++++++---------------- 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/firmware/HDD/hddrvr.a65 b/firmware/HDD/hddrvr.a65 index 7d69c053..93eedb5d 100644 --- a/firmware/HDD/hddrvr.a65 +++ b/firmware/HDD/hddrvr.a65 @@ -49,13 +49,19 @@ ; constants hd_execute = $c080 -hd_error = $c081 ; b7=busy, b0=error +hd_status = $c081 ; b7=busy, b0=error hd_command = $c082 hd_unitnum = $c083 hd_memblock = $c084 hd_diskblock = $c086 ;hd_nextbyte = $c088 ; legacy read-only port (still supported by AppleWin) +; Notes on accesses to I/O registers: +; . ROR ABS16,X and ROL ABS16,X - only used for $C081+s*$10 STATUS register: +; 6502: double read (old data), write (old data), write (new data). The writes are harmless as writes are ignored to STATUS. +; 65C02: double read (old data), write (new data). The write is harmless as writes are ignored to STATUS. +; . STA ABS16,X does a false-read. This is harmless for writable I/O registers, since the false-read has no side effect. + command = $42 unitnum = $43 memblock = $44 @@ -168,7 +174,7 @@ Bootstrap2 sta hd_unitnum,x ; b7=0 => disk 1 sta hd_command,x lda hd_execute,x - ror hd_error,x ; Post: C=0 or 1 + ror hd_status,x ; Post: C=0 or 1 bcc hdboot ; no image ready, boot diskette image instead @@ -272,7 +278,7 @@ GetSlotInX ; C=1 => via GetSlotInX (eg. Entrypoint / SmartPort2) ; X = Slot# << 4 ; Post: -; C = hd_error.b0 +; C = hd_status.b0 ; A = result of hd_execute ; X = Slot# << 4 cmdproc @@ -292,17 +298,17 @@ cmdproc sta hd_diskblock+1,x lda hd_execute,x ; A = result of hd_execute (NB. instantaneous 512 byte r/w!) -- rol hd_error,x ; b7=busy doing DMA? +- rol hd_status,x ; b7=busy doing DMA? bcs - plp ; restore C from start of cmdproc bcs done - ror hd_error,x ; Post: C=0 or 1 + ror hd_status,x ; Post: C=0 or 1 lda #0 beq hdboot2 done - ror hd_error,x ; Post: C=0 or 1 + ror hd_status,x ; Post: C=0 or 1 rts ;====================================== diff --git a/source/Harddisk.cpp b/source/Harddisk.cpp index 896f38ab..1539210f 100644 --- a/source/Harddisk.cpp +++ b/source/Harddisk.cpp @@ -42,54 +42,64 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../resource/resource.h" /* -Memory map: +Memory map (for slot 7): C0F0 (r) EXECUTE AND RETURN STATUS - C0F1 (r) STATUS (or ERROR) + C0F1 (r) STATUS (or ERROR): b7=busy, b0=error C0F2 (r/w) COMMAND C0F3 (r/w) UNIT NUMBER C0F4 (r/w) LOW BYTE OF MEMORY BUFFER C0F5 (r/w) HIGH BYTE OF MEMORY BUFFER C0F6 (r/w) LOW BYTE OF BLOCK NUMBER C0F7 (r/w) HIGH BYTE OF BLOCK NUMBER - C0F8 (r) NEXT BYTE + C0F8 (r) NEXT BYTE (legacy read-only port - still supported) + +Firmware notes: +. ROR ABS16,X and ROL ABS16,X - only used for $C081+s*$10 STATUS register: + 6502: double read (old data), write (old data), write (new data). The writes are harmless as writes to STATUS are ignored. + 65C02: double read (old data), write (new data). The write is harmless as writes to STATUS are ignored. +. STA ABS16,X does a false-read. This is harmless for writable I/O registers, since the false-read has no side effect. + */ /* -Hard drive emulation in Applewin. +Hard drive emulation in AppleWin. Concept - To emulate a 32mb hard drive connected to an Apple IIe via Applewin. + To emulate a 32mb hard drive connected to an Apple IIe via AppleWin. Designed to work with Autoboot Rom and Prodos. Overview 1. Hard drive image file The hard drive image file (.HDV) will be formatted into blocks of 512 bytes, in a linear fashion. The internal formatting and meaning of each - block to be decided by the Apple's operating system (ProDos). To create - an empty .HDV file, just create a 0 byte file (I prefer the debug method). - + block to be decided by the Apple's operating system (ProDOS). To create + an empty .HDV file, just create a 0 byte file. + 2. Emulation code - There are 4 commands Prodos will send to a block device. + There are 4 commands ProDOS will send to a block device. Listed below are each command and how it's handled: 1. STATUS - In the emulation's case, returns only a DEVICE OK (0) or DEVICE I/O ERROR (8). - DEVICE I/O ERROR only returned if no HDV file is selected. + In the emulation's case, returns only a DEVICE OK (0), DEVICE I/O ERROR ($27) or DEVICE NOT CONNECTED ($28) + DEVICE NOT CONNECTED only returned if no HDV file is selected. 2. READ Loads requested block into a 512 byte buffer by attempting to seek to location in HDV file. - If seek fails, returns a DEVICE I/O ERROR. Resets hd_buf_ptr used by HD_NEXTBYTE + If seek fails, returns a DEVICE I/O ERROR. Resets m_buf_ptr used by legacy HD_NEXTBYTE + Copies requested block from a 512 byte buffer to the Apple's memory. + Sets STATUS.busy=1 until the DMA operation completes. Returns a DEVICE OK if read was successful, or a DEVICE I/O ERROR otherwise. 3. WRITE Copies requested block from the Apple's memory to a 512 byte buffer then attempts to seek to requested block. If the seek fails (usually because the seek is beyond the EOF for the - HDV file), the Emulation will attempt to "grow" the HDV file to accomodate. - Once the file can accomodate, or if the seek did not fail, the buffer is + HDV file), the emulation will attempt to "grow" the HDV file to accommodate. + Once the file can accommodate, or if the seek did not fail, the buffer is written to the HDV file. NOTE: A2PC will grow *AND* shrink the HDV file. + Sets STATUS.busy=1 until the DMA operation completes. I didn't see the point in shrinking the file as this behaviour would require patching prodos (to detect DELETE FILE calls). @@ -99,9 +109,9 @@ Overview 3. Bugs The only thing I've noticed is that Copy II+ 7.1 seems to crash or stall - occasionally when trying to calculate how many free block are available + occasionally when trying to calculate how many free blocks are available when running a catalog. This might be due to the great number of blocks - available. Also, DDD pro will not optimise the disk correctally (it's + available. Also, DDD pro will not optimise the disk correctly (it's doing a disk defragment of some sort, and when it requests a block outside the range of the image file, it starts getting I/O errors), so don't bother. Any program that preforms a read before write to an "unwritten" From 25caffe7ebb75ec1fd19c9e7cf406702f80ab737 Mon Sep 17 00:00:00 2001 From: tomcw Date: Thu, 11 Nov 2021 21:24:21 +0000 Subject: [PATCH 3/4] Minor comment typo --- firmware/HDD/hddrvr.a65 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/HDD/hddrvr.a65 b/firmware/HDD/hddrvr.a65 index 93eedb5d..a55320e7 100644 --- a/firmware/HDD/hddrvr.a65 +++ b/firmware/HDD/hddrvr.a65 @@ -58,8 +58,8 @@ hd_diskblock = $c086 ; Notes on accesses to I/O registers: ; . ROR ABS16,X and ROL ABS16,X - only used for $C081+s*$10 STATUS register: -; 6502: double read (old data), write (old data), write (new data). The writes are harmless as writes are ignored to STATUS. -; 65C02: double read (old data), write (new data). The write is harmless as writes are ignored to STATUS. +; 6502: double read (old data), write (old data), write (new data). The writes are harmless as writes to STATUS are ignored. +; 65C02: double read (old data), write (new data). The write is harmless as writes to STATUS are ignored. ; . STA ABS16,X does a false-read. This is harmless for writable I/O registers, since the false-read has no side effect. command = $42 From 8662a9917964d0ee1005829153ff0bbb082b813f Mon Sep 17 00:00:00 2001 From: Andrea Date: Thu, 11 Nov 2021 21:45:55 +0000 Subject: [PATCH 4/4] Add InitializeIO() to Card and CardManager (PR #999) . Card::InitializeIO() is pure virtual . CardManager::InitializeIO() initialises all cards --- AppleWinExpress2008.vcproj | 4 ++ AppleWinExpress2019.vcxproj | 1 + AppleWinExpress2019.vcxproj.filters | 3 ++ source/Card.cpp | 54 ++++++++++++++++++++ source/Card.h | 14 +++--- source/CardManager.cpp | 15 +++++- source/CardManager.h | 2 + source/Disk.h | 2 +- source/FourPlay.h | 2 +- source/Harddisk.cpp | 2 +- source/Harddisk.h | 2 +- source/LanguageCard.cpp | 4 +- source/LanguageCard.h | 4 +- source/Memory.cpp | 77 +---------------------------- source/MouseInterface.h | 2 +- source/SAM.h | 2 +- source/SNESMAX.h | 6 +-- 17 files changed, 100 insertions(+), 96 deletions(-) create mode 100644 source/Card.cpp diff --git a/AppleWinExpress2008.vcproj b/AppleWinExpress2008.vcproj index 1e508132..90846767 100644 --- a/AppleWinExpress2008.vcproj +++ b/AppleWinExpress2008.vcproj @@ -657,6 +657,10 @@ RelativePath=".\source\AY8910.h" > + + diff --git a/AppleWinExpress2019.vcxproj b/AppleWinExpress2019.vcxproj index f3a979e5..6e8a483d 100644 --- a/AppleWinExpress2019.vcxproj +++ b/AppleWinExpress2019.vcxproj @@ -144,6 +144,7 @@ + diff --git a/AppleWinExpress2019.vcxproj.filters b/AppleWinExpress2019.vcxproj.filters index 6c70250e..49c6034d 100644 --- a/AppleWinExpress2019.vcxproj.filters +++ b/AppleWinExpress2019.vcxproj.filters @@ -238,6 +238,9 @@ Source Files\Emulator + + Source Files\Emulator + diff --git a/source/Card.cpp b/source/Card.cpp new file mode 100644 index 00000000..5c8e26cc --- /dev/null +++ b/source/Card.cpp @@ -0,0 +1,54 @@ +/* +AppleWin : An Apple //e emulator for Windows + +Copyright (C) 2021, Tom Charlesworth, Michael Pohoreski + +AppleWin is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +AppleWin is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with AppleWin; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "StdAfx.h" +#include "Card.h" + +#include "Tfe/tfe.h" +#include "Mockingboard.h" +#include "ParallelPrinter.h" +#include "z80emu.h" + + +void DummyCard::InitializeIO(LPBYTE pCxRomPeripheral) +{ + switch (QueryType()) + { + case CT_GenericPrinter: + PrintLoadRom(pCxRomPeripheral, m_slot); + break; + case CT_Uthernet: + tfe_InitializeIO(pCxRomPeripheral, m_slot); + break; + case CT_GenericClock: + break; // nothing to do + case CT_MockingboardC: + case CT_Phasor: + // only in slot 4 + if (m_slot == SLOT4) + { + MB_InitializeIO(pCxRomPeripheral, SLOT4, SLOT5); + } + break; + case CT_Z80: + Z80_InitializeIO(pCxRomPeripheral, m_slot); + break; + } +} diff --git a/source/Card.h b/source/Card.h index ba71fa7c..2f511af0 100644 --- a/source/Card.h +++ b/source/Card.h @@ -30,10 +30,10 @@ enum SLOTS { SLOT0=0, SLOT1, SLOT2, SLOT3, SLOT4, SLOT5, SLOT6, SLOT7, NUM_SLOTS class Card { public: - Card(void) : m_type(CT_Empty), m_slot(SLOT0) {} Card(SS_CARDTYPE type, UINT slot) : m_type(type), m_slot(slot) {} virtual ~Card(void) {} + virtual void InitializeIO(LPBYTE pCxRomPeripheral) = 0; virtual void Init(void) = 0; virtual void Reset(const bool powerCycle) = 0; SS_CARDTYPE QueryType(void) { return m_type; } @@ -50,11 +50,12 @@ private: class EmptyCard : public Card { public: - EmptyCard(void) {} + EmptyCard(UINT slot) : Card(CT_Empty, slot) {} virtual ~EmptyCard(void) {} - virtual void Init(void) {}; - virtual void Reset(const bool powerCycle) {}; + virtual void InitializeIO(LPBYTE pCxRomPeripheral) {} + virtual void Init(void) {} + virtual void Reset(const bool powerCycle) {} }; // @@ -65,6 +66,7 @@ public: DummyCard(SS_CARDTYPE type, UINT slot) : Card(type, slot) {} virtual ~DummyCard(void) {} - virtual void Init(void) {}; - virtual void Reset(const bool powerCycle) {}; + virtual void InitializeIO(LPBYTE pCxRomPeripheral); + virtual void Init(void) {} + virtual void Reset(const bool powerCycle) {} }; diff --git a/source/CardManager.cpp b/source/CardManager.cpp index 03c4f92b..29346cf5 100644 --- a/source/CardManager.cpp +++ b/source/CardManager.cpp @@ -48,7 +48,7 @@ void CardManager::InsertInternal(UINT slot, SS_CARDTYPE type) switch (type) { case CT_Empty: - m_slot[slot] = new EmptyCard; + m_slot[slot] = new EmptyCard(slot); break; case CT_Disk2: m_slot[slot] = new Disk2InterfaceCard(slot); @@ -150,7 +150,7 @@ void CardManager::InsertAuxInternal(SS_CARDTYPE type) switch (type) { case CT_Empty: - m_aux = new EmptyCard; + m_aux = new EmptyCard(SLOT_AUX); break; case CT_80Col: m_aux = new DummyCard(type, SLOT_AUX); @@ -188,3 +188,14 @@ void CardManager::RemoveAux(void) { InsertAux(CT_Empty); } + +void CardManager::InitializeIO(LPBYTE pCxRomPeripheral) +{ + for (UINT i = 0; i < NUM_SLOTS; ++i) + { + if (m_slot[i]) + { + m_slot[i]->InitializeIO(pCxRomPeripheral); + } + } +} diff --git a/source/CardManager.h b/source/CardManager.h index 1cbd38f3..3dab426b 100644 --- a/source/CardManager.h +++ b/source/CardManager.h @@ -57,6 +57,8 @@ public: class CSuperSerialCard* GetSSC(void) { return m_pSSC; } bool IsSSCInstalled(void) { return m_pSSC != NULL; } + void InitializeIO(LPBYTE pCxRomPeripheral); + private: void InsertInternal(UINT slot, SS_CARDTYPE type); void InsertAuxInternal(SS_CARDTYPE type); diff --git a/source/Disk.h b/source/Disk.h index e83f0326..59a62966 100644 --- a/source/Disk.h +++ b/source/Disk.h @@ -130,7 +130,7 @@ public: virtual void Init(void) {}; virtual void Reset(const bool powerCycle); - void InitializeIO(LPBYTE pCxRomPeripheral); + virtual void InitializeIO(LPBYTE pCxRomPeripheral); void Destroy(void); // no, doesn't "destroy" the disk image. DiskIIManagerShutdown() void Boot(void); diff --git a/source/FourPlay.h b/source/FourPlay.h index 4b87993c..b5fa0b39 100644 --- a/source/FourPlay.h +++ b/source/FourPlay.h @@ -14,7 +14,7 @@ public: virtual void Init(void) {}; virtual void Reset(const bool powerCycle) {}; - void InitializeIO(LPBYTE pCxRomPeripheral); + virtual void InitializeIO(LPBYTE pCxRomPeripheral); static BYTE __stdcall IORead(WORD pc, WORD addr, BYTE bWrite, BYTE value, ULONG nExecutedCycles); diff --git a/source/Harddisk.cpp b/source/Harddisk.cpp index 1539210f..a0eadba5 100644 --- a/source/Harddisk.cpp +++ b/source/Harddisk.cpp @@ -162,7 +162,7 @@ void HarddiskInterfaceCard::Reset(const bool powerCycle) //=========================================================================== -void HarddiskInterfaceCard::InitializeIO(const LPBYTE pCxRomPeripheral) +void HarddiskInterfaceCard::InitializeIO(LPBYTE pCxRomPeripheral) { const DWORD HARDDISK_FW_SIZE = APPLE_SLOT_SIZE; diff --git a/source/Harddisk.h b/source/Harddisk.h index 6bd9a89a..5a0483a6 100644 --- a/source/Harddisk.h +++ b/source/Harddisk.h @@ -88,7 +88,7 @@ public: virtual void Init(void) {} virtual void Reset(const bool powerCycle); - void InitializeIO(const LPBYTE pCxRomPeripheral); + virtual void InitializeIO(LPBYTE pCxRomPeripheral); void Destroy(void); const std::string& GetFullName(const int iDrive); const std::string& HarddiskGetFullPathName(const int iDrive); diff --git a/source/LanguageCard.cpp b/source/LanguageCard.cpp index b904cfed..bcb8b161 100644 --- a/source/LanguageCard.cpp +++ b/source/LanguageCard.cpp @@ -50,7 +50,7 @@ LanguageCardUnit::~LanguageCardUnit(void) SetMemMainLanguageCard(NULL); } -void LanguageCardUnit::InitializeIO(void) +void LanguageCardUnit::InitializeIO(LPBYTE pCxRomPeripheral) { RegisterIoHandler(kSlot0, &LanguageCardUnit::IO, &LanguageCardUnit::IO, NULL, NULL, this, NULL); } @@ -276,7 +276,7 @@ UINT Saturn128K::GetActiveBank(void) return m_uSaturnActiveBank; } -void Saturn128K::InitializeIO(void) +void Saturn128K::InitializeIO(LPBYTE pCxRomPeripheral) { RegisterIoHandler(kSlot0, &Saturn128K::IO, &Saturn128K::IO, NULL, NULL, this, NULL); } diff --git a/source/LanguageCard.h b/source/LanguageCard.h index 8f98c3db..6de8adfb 100644 --- a/source/LanguageCard.h +++ b/source/LanguageCard.h @@ -15,7 +15,7 @@ public: virtual void Init(void) {}; virtual void Reset(const bool powerCycle) {}; - virtual void InitializeIO(void); + virtual void InitializeIO(LPBYTE pCxRomPeripheral); virtual void SetMemorySize(UINT banks) {} // No-op for //e and slot-0 16K LC virtual UINT GetActiveBank(void) { return 0; } // Always 0 as only 1x 16K bank virtual void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper) { _ASSERT(0); } // Not used for //e @@ -71,7 +71,7 @@ public: Saturn128K(UINT banks); virtual ~Saturn128K(void); - virtual void InitializeIO(void); + virtual void InitializeIO(LPBYTE pCxRomPeripheral); virtual void SetMemorySize(UINT banks); virtual UINT GetActiveBank(void); virtual void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper); diff --git a/source/Memory.cpp b/source/Memory.cpp index 86725d87..21ffc2d0 100644 --- a/source/Memory.cpp +++ b/source/Memory.cpp @@ -1720,84 +1720,11 @@ void MemInitializeIO(void) InitIoHandlers(); if (g_pLanguageCard) - g_pLanguageCard->InitializeIO(); + g_pLanguageCard->InitializeIO(NULL); else RegisterIoHandler(LanguageCardUnit::kSlot0, IO_Null, IO_Null, NULL, NULL, NULL, NULL); - if (GetCardMgr().QuerySlot(SLOT1) == CT_GenericPrinter) - PrintLoadRom(pCxRomPeripheral, SLOT1); // $C100 : Parallel printer f/w - - if (GetCardMgr().QuerySlot(SLOT2) == CT_SSC) - dynamic_cast(GetCardMgr().GetRef(SLOT2)).InitializeIO(pCxRomPeripheral); // $C200 : SSC - - if (GetCardMgr().QuerySlot(SLOT3) == CT_Uthernet) - { - // Slot 3 contains the Uthernet card (which can coexist with an 80-col+Ram card in AUX slot) - // . Uthernet card has no ROM and only IO mapped at $C0Bx - tfe_InitializeIO(pCxRomPeripheral, SLOT3); - } - else if (GetCardMgr().QuerySlot(SLOT3) == CT_FourPlay) - { - dynamic_cast(GetCardMgr().GetRef(SLOT3)).InitializeIO(pCxRomPeripheral); - } - else if (GetCardMgr().QuerySlot(SLOT3) == CT_SNESMAX) - { - dynamic_cast(GetCardMgr().GetRef(SLOT3)).InitializeIO(pCxRomPeripheral); - } - - // Apple//e: Auxiliary slot contains Extended 80 Column card or RamWorksIII card - - if (GetCardMgr().QuerySlot(SLOT4) == CT_MouseInterface) - { - dynamic_cast(GetCardMgr().GetRef(SLOT4)).InitializeIO(pCxRomPeripheral); // $C400 : Mouse f/w - } - else if (GetCardMgr().QuerySlot(SLOT4) == CT_MockingboardC || GetCardMgr().QuerySlot(SLOT4) == CT_Phasor) - { - MB_InitializeIO(pCxRomPeripheral, SLOT4, SLOT5); - } - else if (GetCardMgr().QuerySlot(SLOT4) == CT_Z80) - { - Z80_InitializeIO(pCxRomPeripheral, SLOT4); // $C400 : Z80 card - } -// else if (GetCardMgr().QuerySlot(SLOT4) == CT_GenericClock) -// { -// LoadRom_Clock_Generic(pCxRomPeripheral, SLOT4); -// } - else if (GetCardMgr().QuerySlot(SLOT4) == CT_FourPlay) - { - dynamic_cast(GetCardMgr().GetRef(SLOT4)).InitializeIO(pCxRomPeripheral); - } - else if (GetCardMgr().QuerySlot(SLOT4) == CT_SNESMAX) - { - dynamic_cast(GetCardMgr().GetRef(SLOT4)).InitializeIO(pCxRomPeripheral); - } - - if (GetCardMgr().QuerySlot(SLOT5) == CT_Z80) - { - Z80_InitializeIO(pCxRomPeripheral, SLOT5); // $C500 : Z80 card - } - else if (GetCardMgr().QuerySlot(SLOT5) == CT_SAM) - { - dynamic_cast(GetCardMgr().GetRef(SLOT5)).InitializeIO(pCxRomPeripheral); - } - else if (GetCardMgr().QuerySlot(SLOT5) == CT_FourPlay) - { - dynamic_cast(GetCardMgr().GetRef(SLOT5)).InitializeIO(pCxRomPeripheral); - } - else if (GetCardMgr().QuerySlot(SLOT5) == CT_SNESMAX) - { - dynamic_cast(GetCardMgr().GetRef(SLOT5)).InitializeIO(pCxRomPeripheral); - } - else if (GetCardMgr().QuerySlot(SLOT5) == CT_Disk2) - { - dynamic_cast(GetCardMgr().GetRef(SLOT5)).InitializeIO(pCxRomPeripheral); // $C500 : Disk][ card - } - - if (GetCardMgr().QuerySlot(SLOT6) == CT_Disk2) - dynamic_cast(GetCardMgr().GetRef(SLOT6)).InitializeIO(pCxRomPeripheral); // $C600 : Disk][ card - - if (GetCardMgr().QuerySlot(SLOT7) == CT_GenericHDD) - dynamic_cast(GetCardMgr().GetRef(SLOT7)).InitializeIO(pCxRomPeripheral); + GetCardMgr().InitializeIO(pCxRomPeripheral); } // Called by: diff --git a/source/MouseInterface.h b/source/MouseInterface.h index 96bb1fac..1cdd545f 100644 --- a/source/MouseInterface.h +++ b/source/MouseInterface.h @@ -14,7 +14,7 @@ public: virtual void Init(void) {}; virtual void Reset(const bool powerCycle) {}; - void InitializeIO(LPBYTE pCxRomPeripheral); + virtual void InitializeIO(LPBYTE pCxRomPeripheral); // void Uninitialize(); void Reset(); UINT GetSlot(void) { return m_slot; } diff --git a/source/SAM.h b/source/SAM.h index 359d68d5..4e90515f 100644 --- a/source/SAM.h +++ b/source/SAM.h @@ -14,7 +14,7 @@ public: virtual void Init(void) {}; virtual void Reset(const bool powerCycle) {}; - void InitializeIO(LPBYTE pCxRomPeripheral); + virtual void InitializeIO(LPBYTE pCxRomPeripheral); static BYTE __stdcall IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE value, ULONG nExecutedCycles); diff --git a/source/SNESMAX.h b/source/SNESMAX.h index 8a0665e1..aa6591c5 100644 --- a/source/SNESMAX.h +++ b/source/SNESMAX.h @@ -18,10 +18,10 @@ public: } virtual ~SNESMAXCard(void) {} - virtual void Init(void) {}; - virtual void Reset(const bool powerCycle) {}; + virtual void Init(void) {} + virtual void Reset(const bool powerCycle) {} - void InitializeIO(LPBYTE pCxRomPeripheral); + virtual void InitializeIO(LPBYTE pCxRomPeripheral); static BYTE __stdcall IORead(WORD pc, WORD addr, BYTE bWrite, BYTE value, ULONG nExecutedCycles); static BYTE __stdcall IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE value, ULONG nExecutedCycles);