mirror of
https://github.com/dschmenk/Appalm.git
synced 2024-11-10 11:04:43 +00:00
1803 lines
61 KiB
C
1803 lines
61 KiB
C
|
#include <PalmOS.h>
|
||
|
#include "Apple2.h"
|
||
|
extern UInt16 grMode;
|
||
|
|
||
|
UInt16 memIOU, vidIOU, kbdIOU, spkrIOU, btnIOU[3], pdlIOU[2], pdlResetIOU[2];
|
||
|
UInt8 kbdBuffer[16];
|
||
|
UInt8 kbdHead, kbdCount;
|
||
|
UInt8 *AppleMemory;
|
||
|
UInt8 *AuxMemory;
|
||
|
UInt8 *AppleROM;
|
||
|
UInt8 *BootROM;
|
||
|
READBYTE *ReadFunction;
|
||
|
WRITEBYTE *WriteFunction;
|
||
|
UInt8 auxDirty = 0;
|
||
|
|
||
|
void showDiskName(UInt16, Char *);
|
||
|
void showDriveState(UInt16, Boolean);
|
||
|
UInt8 RIOM(UInt16);
|
||
|
void WIOM(UInt16, UInt8);
|
||
|
UInt8 RC3M(UInt16);
|
||
|
void clrVidFuncs(UInt16);
|
||
|
void toggleVideoSoftSwitch(UInt8);
|
||
|
|
||
|
/*
|
||
|
* Function prototypes for sector nibblizing
|
||
|
*/
|
||
|
static void init_GCR_table(void);
|
||
|
static UInt8 gcr_read_nibble(void);
|
||
|
static void gcr_write_nibble( UInt8 );
|
||
|
static void decode62( UInt8* );
|
||
|
static void encode62( UInt8* );
|
||
|
static void FM_encode( UInt8 );
|
||
|
static UInt8 FM_decode(void);
|
||
|
static void write_sync( int );
|
||
|
static int read_address_field( int*, int*, int* );
|
||
|
static void write_address_field( int, int, int );
|
||
|
static int read_data_field(void);
|
||
|
static void write_data_field(void);
|
||
|
int NibblesToSectors(UInt8 *nibbles, UInt8 *sectors, int volume, int track);
|
||
|
void SectorsToNibbles(UInt8 *sectors, UInt8 *nibbles, int volume, int track);
|
||
|
|
||
|
void initMemory(void)
|
||
|
{
|
||
|
vidIOU = SS_TEXT;
|
||
|
memIOU =
|
||
|
kbdIOU =
|
||
|
spkrIOU =
|
||
|
btnIOU[0] =
|
||
|
btnIOU[1] =
|
||
|
btnIOU[2] =
|
||
|
pdlIOU[0] =
|
||
|
pdlIOU[1] = 0;
|
||
|
pdlResetIOU[0] =
|
||
|
pdlResetIOU[1] = 0x80;
|
||
|
kbdHead =
|
||
|
kbdCount = 0;
|
||
|
MemSet(AppleMemory, 65536, 0);
|
||
|
MemSet(AuxMemory, 16384+2048, 0);
|
||
|
MemSet(ReadFunction, 1024, 0);
|
||
|
MemSet(WriteFunction, 1024, 0);
|
||
|
loadROM();
|
||
|
MemMove(AppleMemory + 0xC100, AppleROM, 0x3F00);
|
||
|
setMemFuncs();
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************\
|
||
|
* *
|
||
|
* ROM Access *
|
||
|
* *
|
||
|
\*****************************************************************************/
|
||
|
|
||
|
/* Apple ROM Paging */
|
||
|
|
||
|
void READONLY(UInt16, UInt8);
|
||
|
UInt8 RRMP(UInt16);
|
||
|
void awrap_ROMReadWrite(void)
|
||
|
{
|
||
|
asm(".global RRMP");
|
||
|
asm(".global READONLY");
|
||
|
asm("RRMP:");
|
||
|
asm("clr.l %d0");
|
||
|
asm("READONLY:");
|
||
|
asm("rts");
|
||
|
}
|
||
|
RDMEM_CWRAP(REXP, address)
|
||
|
{
|
||
|
if (!SS_ISSET(memIOU, SS_SLOTCXROM) && address == 0xCFFF)
|
||
|
{
|
||
|
MemMove(AppleMemory + 0xCE00, BootROM, 256);
|
||
|
SS_RESET(memIOU, SS_EXPNROM);
|
||
|
return (0x00);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return (AppleMemory[address]);
|
||
|
}
|
||
|
}
|
||
|
RDMEM_CWRAP(RC3M, address)
|
||
|
{
|
||
|
if (!SS_ISSET(memIOU, SS_SLOTC3ROM))
|
||
|
{
|
||
|
SS_SET(memIOU, SS_EXPNROM);
|
||
|
MemMove(AppleMemory + 0xC800, AppleROM + 0x700, 2048);
|
||
|
}
|
||
|
return (AppleMemory[address]);
|
||
|
}
|
||
|
void loadROM(void)
|
||
|
{
|
||
|
DmOpenRef romDB;
|
||
|
LocalID romID;
|
||
|
MemHandle romRec;
|
||
|
UInt8 *roms;
|
||
|
UInt32 romStart;
|
||
|
UInt16 count;
|
||
|
|
||
|
romID = DmFindDatabase(0, "apple2e.rom");
|
||
|
romDB = DmOpenDatabase(0, romID, dmModeReadOnly);
|
||
|
romRec = DmQueryRecord(romDB, 0);
|
||
|
roms = (UInt8 *) MemHandleLock(romRec);
|
||
|
romStart = 0x004100;
|
||
|
AppleROM = MemPtrNew(0x3F00);
|
||
|
MemMove(AppleROM, roms + romStart, 0x3F00);
|
||
|
MemHandleUnlock(romRec);
|
||
|
DmCloseDatabase(romDB);
|
||
|
romID = DmFindDatabase(0, "slot6.rom");
|
||
|
romDB = DmOpenDatabase(0, romID, dmModeReadOnly);
|
||
|
romRec = DmQueryRecord(romDB, 0);
|
||
|
roms = (UInt8 *) MemHandleLock(romRec);
|
||
|
BootROM = MemPtrNew(256);
|
||
|
MemMove(BootROM, roms, 256);
|
||
|
MemHandleUnlock(romRec);
|
||
|
DmCloseDatabase(romDB);
|
||
|
BootROM[0x004C] = 0xA9;
|
||
|
BootROM[0x004D] = 0x00;
|
||
|
BootROM[0x004E] = 0xEA;
|
||
|
}
|
||
|
void unloadROM(void)
|
||
|
{
|
||
|
MemPtrFree(AppleROM);
|
||
|
MemPtrFree(BootROM);
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************\
|
||
|
* *
|
||
|
* Soft switches *
|
||
|
* *
|
||
|
\*****************************************************************************/
|
||
|
|
||
|
void AuxWriteBnk1(UInt16, UInt8);
|
||
|
void AuxWriteBnk2(UInt16, UInt8);
|
||
|
void AuxWrite(UInt16, UInt8);
|
||
|
void AuxMapWriteBnk1(UInt16, UInt8);
|
||
|
void AuxMapWriteBnk2(UInt16, UInt8);
|
||
|
void AuxMapWrite(UInt16, UInt8);
|
||
|
UInt8 AuxReadBnk1(UInt16);
|
||
|
UInt8 AuxReadBnk2(UInt16);
|
||
|
UInt8 AuxRead(UInt16);
|
||
|
UInt8 RomRead(UInt16);
|
||
|
void awrap_AuxMemReadWrite(void)
|
||
|
{
|
||
|
asm(".global AuxWriteBnk1");
|
||
|
asm(".global AuxWriteBnk2");
|
||
|
asm(".global AuxWrite");
|
||
|
asm(".global AuxMapWriteBnk1");
|
||
|
asm(".global AuxMapWriteBnk2");
|
||
|
asm(".global AuxMapWrite");
|
||
|
asm(".global AuxReadBnk1");
|
||
|
asm(".global AuxReadBnk2");
|
||
|
asm(".global AuxRead");
|
||
|
asm(".global RomRead");
|
||
|
asm("AuxWriteBnk1:");
|
||
|
asm("move.l AuxMemory@END.w(%a5), %a6");
|
||
|
asm("sub.l #0xD000, %a6");
|
||
|
asm("move.b %d0, (%a6, %d6.l)");
|
||
|
asm("rts");
|
||
|
asm("AuxWriteBnk2:");
|
||
|
asm("AuxWrite:");
|
||
|
asm("move.l AuxMemory@END.w(%a5), %a6");
|
||
|
asm("sub.l #0xC000, %a6");
|
||
|
asm("move.b %d0, (%a6, %d6.l)");
|
||
|
asm("rts");
|
||
|
asm("AuxMapWriteBnk1:");
|
||
|
asm("move.l AuxMemory@END.w(%a5), %a6");
|
||
|
asm("sub.l #0xD000, %a6");
|
||
|
asm("move.b %d0, (%a6, %d6.l)");
|
||
|
asm("move.b %d0, (%a2, %d6.l)");
|
||
|
asm("rts");
|
||
|
asm("AuxMapWriteBnk2:");
|
||
|
asm("AuxMapWrite:");
|
||
|
asm("move.l AuxMemory@END.w(%a5), %a6");
|
||
|
asm("sub.l #0xC000, %a6");
|
||
|
asm("move.b %d0, (%a6, %d6.l)");
|
||
|
asm("move.b %d0, (%a2, %d6.l)");
|
||
|
asm("rts");
|
||
|
asm("AuxReadBnk1:");
|
||
|
asm("move.l AuxMemory@END.w(%a5), %a6");
|
||
|
asm("sub.l #0xD000, %a6");
|
||
|
asm("clr.l %d0");
|
||
|
asm("move.b (%a6, %d6.l), %d0");
|
||
|
asm("rts");
|
||
|
asm("AuxReadBnk2:");
|
||
|
asm("AuxRead:");
|
||
|
asm("move.l AuxMemory@END.w(%a5), %a6");
|
||
|
asm("sub.l #0xC000, %a6");
|
||
|
asm("clr.l %d0");
|
||
|
asm("move.b (%a6, %d6.l), %d0");
|
||
|
asm("rts");
|
||
|
asm("RomRead:");
|
||
|
asm("move.l AppleROM@END.w(%a5), %a6");
|
||
|
asm("sub.l #0xC100, %a6");
|
||
|
asm("clr.l %d0");
|
||
|
asm("move.b (%a6, %d6.l), %d0");
|
||
|
asm("rts");
|
||
|
}
|
||
|
void WTXTM(UInt16, UInt8);
|
||
|
void WATXTM(UInt16, UInt8);
|
||
|
UInt8 RATXTM(UInt16 address);
|
||
|
void writeMemorySoftSwitch(UInt8 io)
|
||
|
{
|
||
|
UInt16 page;
|
||
|
UInt8 *tempPage;
|
||
|
|
||
|
switch (io)
|
||
|
{
|
||
|
case IO_OFFSET(CLR80STORE):
|
||
|
if (SS_ISSET(vidIOU, SS_80STORE))
|
||
|
{
|
||
|
clrVidFuncs(vidIOU);
|
||
|
SS_RESET(vidIOU, SS_80STORE);
|
||
|
if (SS_ISSET(vidIOU, SS_PAGE2))
|
||
|
{
|
||
|
WriteFunction[0x08] = WTXTM;
|
||
|
WriteFunction[0x09] = WTXTM;
|
||
|
WriteFunction[0x0A] = WTXTM;
|
||
|
WriteFunction[0x0B] = WTXTM;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
WriteFunction[0x04] = WTXTM;
|
||
|
WriteFunction[0x05] = WTXTM;
|
||
|
WriteFunction[0x06] = WTXTM;
|
||
|
WriteFunction[0x07] = WTXTM;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case IO_OFFSET(SET80STORE):
|
||
|
if (!SS_ISSET(vidIOU, SS_80STORE))
|
||
|
{
|
||
|
clrVidFuncs(vidIOU);
|
||
|
SS_SET(vidIOU, SS_80STORE);
|
||
|
if (SS_ISSET(vidIOU, SS_PAGE2))
|
||
|
{
|
||
|
if ((grMode > GRMODE_COLOR) && prefs.enable80Col)
|
||
|
{
|
||
|
WriteFunction[0x04] = WATXTM;
|
||
|
WriteFunction[0x05] = WATXTM;
|
||
|
WriteFunction[0x06] = WATXTM;
|
||
|
WriteFunction[0x07] = WATXTM;
|
||
|
ReadFunction[0x04] = RATXTM;
|
||
|
ReadFunction[0x05] = RATXTM;
|
||
|
ReadFunction[0x06] = RATXTM;
|
||
|
ReadFunction[0x07] = RATXTM;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
WriteFunction[0x04] = READONLY;
|
||
|
WriteFunction[0x05] = READONLY;
|
||
|
WriteFunction[0x06] = READONLY;
|
||
|
WriteFunction[0x07] = READONLY;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
WriteFunction[0x04] = WTXTM;
|
||
|
WriteFunction[0x05] = WTXTM;
|
||
|
WriteFunction[0x06] = WTXTM;
|
||
|
WriteFunction[0x07] = WTXTM;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case IO_OFFSET(RDMAINRAM):
|
||
|
if (SS_ISSET(memIOU, SS_RAMRD))
|
||
|
{
|
||
|
SS_RESET(memIOU, SS_RAMRD);
|
||
|
for (page = 0x02; page < 0xC0; page++)
|
||
|
ReadFunction[page] = NULL;
|
||
|
setVideoFuncs(false);
|
||
|
}
|
||
|
break;
|
||
|
case IO_OFFSET(RDCARDRAM):
|
||
|
if (!SS_ISSET(memIOU, SS_RAMRD))
|
||
|
{
|
||
|
SS_SET(memIOU, SS_RAMRD);
|
||
|
for (page = 0x02; page < 0xC0; page++)
|
||
|
ReadFunction[page] = RRMP;
|
||
|
}
|
||
|
break;
|
||
|
case IO_OFFSET(WRMAINRAM):
|
||
|
if (SS_ISSET(memIOU, SS_RAMWRT))
|
||
|
{
|
||
|
SS_RESET(memIOU, SS_RAMWRT);
|
||
|
for (page = 0x02; page < 0xC0; page++)
|
||
|
WriteFunction[page] = NULL;
|
||
|
setVideoFuncs(false);
|
||
|
}
|
||
|
break;
|
||
|
case IO_OFFSET(WRCARDRAM):
|
||
|
if (!SS_ISSET(memIOU, SS_RAMWRT))
|
||
|
{
|
||
|
SS_SET(memIOU, SS_RAMWRT);
|
||
|
for (page = 0x02; page < 0xC0; page++)
|
||
|
WriteFunction[page] = READONLY;
|
||
|
}
|
||
|
break;
|
||
|
case IO_OFFSET(SETSLOTCXROM):
|
||
|
if (SS_ISSET(memIOU, SS_SLOTCXROM))
|
||
|
{
|
||
|
SS_RESET(memIOU, SS_SLOTCXROM);
|
||
|
ReadFunction[0xC1] = RRMP;
|
||
|
ReadFunction[0xC2] = RRMP;
|
||
|
ReadFunction[0xC4] = RRMP;
|
||
|
ReadFunction[0xC5] = RRMP;
|
||
|
ReadFunction[0xC6] = RRMP;
|
||
|
ReadFunction[0xC7] = RRMP;
|
||
|
MemSet(AppleMemory + 0xC100, 512, 0);
|
||
|
MemSet(AppleMemory + 0xC400, 1024, 0);
|
||
|
ReadFunction[0xC6] = NULL;
|
||
|
MemMove(AppleMemory + 0x00C600, BootROM, 256);
|
||
|
}
|
||
|
break;
|
||
|
case IO_OFFSET(SETINTCXROM):
|
||
|
if (!SS_ISSET(memIOU, SS_SLOTCXROM))
|
||
|
{
|
||
|
SS_SET(memIOU, SS_SLOTCXROM);
|
||
|
ReadFunction[0xC1] = NULL;
|
||
|
ReadFunction[0xC2] = NULL;
|
||
|
ReadFunction[0xC4] = NULL;
|
||
|
ReadFunction[0xC5] = NULL;
|
||
|
ReadFunction[0xC6] = NULL;
|
||
|
ReadFunction[0xC7] = NULL;
|
||
|
MemMove(AppleMemory + 0xC100, AppleROM, 512);
|
||
|
MemMove(AppleMemory + 0xC400, AppleROM + 0x300, 1024);
|
||
|
}
|
||
|
break;
|
||
|
case IO_OFFSET(SETINTC3ROM):
|
||
|
if (!SS_ISSET(memIOU, SS_SLOTC3ROM))
|
||
|
{
|
||
|
SS_SET(memIOU, SS_SLOTC3ROM);
|
||
|
MemMove(AppleMemory + 0xC300, AppleROM + 0x200, 256);
|
||
|
}
|
||
|
break;
|
||
|
case IO_OFFSET(SETSLOTC3ROM):
|
||
|
if (SS_ISSET(memIOU, SS_SLOTC3ROM))
|
||
|
{
|
||
|
SS_RESET(memIOU, SS_SLOTC3ROM);
|
||
|
MemSet(AppleMemory + 0xC300, 256, 0);
|
||
|
}
|
||
|
break;
|
||
|
case IO_OFFSET(CLR80VID):
|
||
|
SS_RESET(vidIOU, SS_80VID);
|
||
|
setVideoFuncs(true);
|
||
|
break;
|
||
|
case IO_OFFSET(SET80VID):
|
||
|
SS_SET(vidIOU, SS_80VID);
|
||
|
setVideoFuncs(true);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
void updateLanguageCardMapping(void)
|
||
|
{
|
||
|
READBYTE rfn;
|
||
|
WRITEBYTE wfn;
|
||
|
UInt16 page;
|
||
|
|
||
|
if (SS_ISSET(memIOU, SS_LCRAMMAP))
|
||
|
{
|
||
|
MemMove(AppleMemory + 0xD000, AuxMemory + (SS_ISSET(memIOU, SS_LCBNK2) ? 0x1000 : 0x0000), 4096);
|
||
|
MemMove(AppleMemory + 0xE000, AuxMemory + 0x2000, 8192);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MemMove(AppleMemory + 0xD000, AppleROM + 0xD000 - 0xC100, 4096+8192);
|
||
|
}
|
||
|
if (SS_ISSET(memIOU, SS_LCRAMWRT))
|
||
|
{
|
||
|
if (SS_ISSET(memIOU, SS_LCRAMMAP))
|
||
|
{
|
||
|
wfn = SS_ISSET(memIOU, SS_LCBNK2) ? AuxMapWriteBnk2 : AuxMapWriteBnk1;
|
||
|
WriteFunction[0xD0] = WriteFunction[0xD1] = wfn;
|
||
|
WriteFunction[0xD2] = WriteFunction[0xD3] = wfn;
|
||
|
WriteFunction[0xD4] = WriteFunction[0xD5] = wfn;
|
||
|
WriteFunction[0xD6] = WriteFunction[0xD7] = wfn;
|
||
|
WriteFunction[0xD8] = WriteFunction[0xD9] = wfn;
|
||
|
WriteFunction[0xDA] = WriteFunction[0xDB] = wfn;
|
||
|
WriteFunction[0xDC] = WriteFunction[0xDD] = wfn;
|
||
|
WriteFunction[0xDE] = WriteFunction[0xDF] = wfn;
|
||
|
for (page = 0xE0; page <= 0xFF; page++)
|
||
|
WriteFunction[page] = AuxMapWrite;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
wfn = SS_ISSET(memIOU, SS_LCBNK2) ? AuxWriteBnk2 : AuxWriteBnk1;
|
||
|
WriteFunction[0xD0] = WriteFunction[0xD1] = wfn;
|
||
|
WriteFunction[0xD2] = WriteFunction[0xD3] = wfn;
|
||
|
WriteFunction[0xD4] = WriteFunction[0xD5] = wfn;
|
||
|
WriteFunction[0xD6] = WriteFunction[0xD7] = wfn;
|
||
|
WriteFunction[0xD8] = WriteFunction[0xD9] = wfn;
|
||
|
WriteFunction[0xDA] = WriteFunction[0xDB] = wfn;
|
||
|
WriteFunction[0xDC] = WriteFunction[0xDD] = wfn;
|
||
|
WriteFunction[0xDE] = WriteFunction[0xDF] = wfn;
|
||
|
for (page = 0xE0; page <= 0xFF; page++)
|
||
|
WriteFunction[page] = AuxWrite;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
for (page = 0xD0; page <= 0xFF; page++)
|
||
|
WriteFunction[page] = READONLY;
|
||
|
for (page = 0xD0; page <= 0xFF; page++)
|
||
|
ReadFunction[page] = NULL;
|
||
|
clrPcCheckFuncs();
|
||
|
auxDirty = 0;
|
||
|
}
|
||
|
void toggleLanguageCard(UInt8 io)
|
||
|
{
|
||
|
READBYTE rfn;
|
||
|
WRITEBYTE wfn;
|
||
|
UInt16 page, dirty, pc6502;
|
||
|
|
||
|
/* set IOU soft switches */
|
||
|
dirty = memIOU;
|
||
|
switch (io)
|
||
|
{
|
||
|
case 0x00:
|
||
|
case 0x04:
|
||
|
SS_SET(memIOU, SS_LCBNK2);
|
||
|
SS_SET(memIOU, SS_LCRAMMAP);
|
||
|
SS_RESET(memIOU, SS_LCRAMWRT);
|
||
|
break;
|
||
|
case 0x01:
|
||
|
case 0x05:
|
||
|
SS_SET(memIOU, SS_LCBNK2);
|
||
|
SS_RESET(memIOU, SS_LCRAMMAP);
|
||
|
SS_SET(memIOU, SS_LCRAMWRT);
|
||
|
break;
|
||
|
case 0x02:
|
||
|
case 0x06:
|
||
|
SS_SET(memIOU, SS_LCBNK2);
|
||
|
SS_RESET(memIOU, SS_LCRAMMAP);
|
||
|
SS_RESET(memIOU, SS_LCRAMWRT);
|
||
|
break;
|
||
|
case 0x03:
|
||
|
case 0x07:
|
||
|
SS_SET(memIOU, SS_LCBNK2);
|
||
|
SS_SET(memIOU, SS_LCRAMMAP);
|
||
|
SS_SET(memIOU, SS_LCRAMWRT);
|
||
|
break;
|
||
|
case 0x08:
|
||
|
case 0x0C:
|
||
|
SS_RESET(memIOU, SS_LCBNK2);
|
||
|
SS_SET(memIOU, SS_LCRAMMAP);
|
||
|
SS_RESET(memIOU, SS_LCRAMWRT);
|
||
|
break;
|
||
|
case 0x09:
|
||
|
case 0x0D:
|
||
|
SS_RESET(memIOU, SS_LCBNK2);
|
||
|
SS_RESET(memIOU, SS_LCRAMMAP);
|
||
|
SS_SET(memIOU, SS_LCRAMWRT);
|
||
|
break;
|
||
|
case 0x0A:
|
||
|
case 0x0E:
|
||
|
SS_RESET(memIOU, SS_LCBNK2);
|
||
|
SS_RESET(memIOU, SS_LCRAMMAP);
|
||
|
SS_RESET(memIOU, SS_LCRAMWRT);
|
||
|
break;
|
||
|
case 0x0B:
|
||
|
case 0x0F:
|
||
|
SS_RESET(memIOU, SS_LCBNK2);
|
||
|
SS_SET(memIOU, SS_LCRAMMAP);
|
||
|
SS_SET(memIOU, SS_LCRAMWRT);
|
||
|
break;
|
||
|
}
|
||
|
/*
|
||
|
* Update only the changed state.
|
||
|
*/
|
||
|
if ((dirty ^= memIOU))
|
||
|
{
|
||
|
if (dirty & SS_LCRAMMAP)
|
||
|
{
|
||
|
updateLanguageCardMapping();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (SS_ISSET(memIOU, SS_LCRAMMAP))
|
||
|
{
|
||
|
if (dirty & SS_LCBNK2)
|
||
|
{
|
||
|
pc6502 = state6502.LongRegs.PC-state6502.LongRegs.MEMBASE;
|
||
|
if ((pc6502 >= 0xD000) && (pc6502 < 0xE000))
|
||
|
{
|
||
|
updateLanguageCardMapping();
|
||
|
return;
|
||
|
}
|
||
|
if (!auxDirty)
|
||
|
{
|
||
|
/*
|
||
|
* Install special versions of JMP, JSR, BRK, RTI, and RTS that check for memory ranges.
|
||
|
*/
|
||
|
setPcCheckFuncs();
|
||
|
auxDirty = 1;
|
||
|
}
|
||
|
rfn = SS_ISSET(memIOU, SS_LCBNK2) ? AuxReadBnk2 : AuxReadBnk1;
|
||
|
ReadFunction[0xD0] = ReadFunction[0xD1] = rfn;
|
||
|
ReadFunction[0xD2] = ReadFunction[0xD3] = rfn;
|
||
|
ReadFunction[0xD4] = ReadFunction[0xD5] = rfn;
|
||
|
ReadFunction[0xD6] = ReadFunction[0xD7] = rfn;
|
||
|
ReadFunction[0xD8] = ReadFunction[0xD9] = rfn;
|
||
|
ReadFunction[0xDA] = ReadFunction[0xDB] = rfn;
|
||
|
ReadFunction[0xDC] = ReadFunction[0xDD] = rfn;
|
||
|
ReadFunction[0xDE] = ReadFunction[0xDF] = rfn;
|
||
|
}
|
||
|
if (SS_ISSET(memIOU, SS_LCRAMWRT))
|
||
|
{
|
||
|
wfn = SS_ISSET(memIOU, SS_LCBNK2) ? AuxMapWriteBnk2 : AuxMapWriteBnk1;
|
||
|
WriteFunction[0xD0] = WriteFunction[0xD1] = wfn;
|
||
|
WriteFunction[0xD2] = WriteFunction[0xD3] = wfn;
|
||
|
WriteFunction[0xD4] = WriteFunction[0xD5] = wfn;
|
||
|
WriteFunction[0xD6] = WriteFunction[0xD7] = wfn;
|
||
|
WriteFunction[0xD8] = WriteFunction[0xD9] = wfn;
|
||
|
WriteFunction[0xDA] = WriteFunction[0xDB] = wfn;
|
||
|
WriteFunction[0xDC] = WriteFunction[0xDD] = wfn;
|
||
|
WriteFunction[0xDE] = WriteFunction[0xDF] = wfn;
|
||
|
if (dirty & SS_LCRAMWRT)
|
||
|
for (page = 0xE0; page <= 0xFF; page++)
|
||
|
WriteFunction[page] = AuxMapWrite;
|
||
|
}
|
||
|
else if (dirty & SS_LCRAMWRT)
|
||
|
for (page = 0xD0; page <= 0xFF; page++)
|
||
|
WriteFunction[page] = READONLY;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (SS_ISSET(memIOU, SS_LCRAMWRT))
|
||
|
{
|
||
|
wfn = SS_ISSET(memIOU, SS_LCBNK2) ? AuxWriteBnk2 : AuxWriteBnk1;
|
||
|
WriteFunction[0xD0] = WriteFunction[0xD1] = wfn;
|
||
|
WriteFunction[0xD2] = WriteFunction[0xD3] = wfn;
|
||
|
WriteFunction[0xD4] = WriteFunction[0xD5] = wfn;
|
||
|
WriteFunction[0xD6] = WriteFunction[0xD7] = wfn;
|
||
|
WriteFunction[0xD8] = WriteFunction[0xD9] = wfn;
|
||
|
WriteFunction[0xDA] = WriteFunction[0xDB] = wfn;
|
||
|
WriteFunction[0xDC] = WriteFunction[0xDD] = wfn;
|
||
|
WriteFunction[0xDE] = WriteFunction[0xDF] = wfn;
|
||
|
if (dirty & SS_LCRAMWRT)
|
||
|
for (page = 0xE0; page <= 0xFF; page++)
|
||
|
WriteFunction[page] = AuxWrite;
|
||
|
}
|
||
|
else if (dirty & SS_LCRAMWRT)
|
||
|
for (page = 0xD0; page <= 0xFF; page++)
|
||
|
WriteFunction[page] = READONLY;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
void setMemFuncs(void)
|
||
|
{
|
||
|
UInt16 page;
|
||
|
|
||
|
updateLanguageCardMapping();
|
||
|
if (!SS_ISSET(memIOU, SS_SLOTCXROM))
|
||
|
{
|
||
|
ReadFunction[0xC1] = RRMP;
|
||
|
ReadFunction[0xC2] = RRMP;
|
||
|
ReadFunction[0xC4] = RRMP;
|
||
|
ReadFunction[0xC5] = RRMP;
|
||
|
ReadFunction[0xC6] = RRMP;
|
||
|
ReadFunction[0xC7] = RRMP;
|
||
|
}
|
||
|
if (SS_ISSET(memIOU, SS_RAMRD))
|
||
|
for (page = 0x02; page < 0xC0; page++)
|
||
|
ReadFunction[page] = RRMP;
|
||
|
if (SS_ISSET(memIOU, SS_RAMWRT))
|
||
|
for (page = 0x02; page < 0xC0; page++)
|
||
|
WriteFunction[page] = READONLY;
|
||
|
ReadFunction[0xC0] = RIOM;
|
||
|
ReadFunction[0xC3] = RC3M;
|
||
|
WriteFunction[0xC0] = WIOM;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************\
|
||
|
* *
|
||
|
* Disk access control *
|
||
|
* *
|
||
|
\*****************************************************************************/
|
||
|
|
||
|
#define RAW_TRACK_BYTES 6192
|
||
|
#define RAW_SECTOR_BYTES 387
|
||
|
#define DOS_TRACK_BYTES 4096
|
||
|
#define RAW_TRACK_BITS (RAW_TRACK_BYTES*8)
|
||
|
#define NO_OF_PHASES 8
|
||
|
#define MAX_PHYSICAL_TRACK_NO (40*NO_OF_PHASES)
|
||
|
#define MAX_DRIVE_NO 2
|
||
|
|
||
|
static Int8 stepper_movement_table[16][NO_OF_PHASES] =
|
||
|
{
|
||
|
{ 0, 0, 0, 0, 0, 0, 0, 0}, /* all electromagnets off */
|
||
|
{ 0, -1, -2, -3, 0, 3, 2, 1}, /* EM 1 on */
|
||
|
{ 2, 1, 0, -1, -2, -3, 0, 3}, /* EM 2 on */
|
||
|
{ 1, 0, -1, -2, -3, 0, 3, 2}, /* EMs 1 & 2 on */
|
||
|
{ 0, 3, 2, 1, 0, -1, -2, -3}, /* EM 3 on */
|
||
|
{ 0, -1, 0, 1, 0, -1, 0, 1}, /* EMs 1 & 3 on */
|
||
|
{ 3, 2, 1, 0, -1, -2, -3, 0}, /* EMs 2 & 3 on */
|
||
|
{ 2, 1, 0, -1, -2, -3, 0, 3}, /* EMs 1, 2 & 3 on */
|
||
|
{-2, -3, 0, 3, 2, 1, 0, -1}, /* EM 4 on */
|
||
|
{-1, -2, -3, 0, 3, 2, 1, 0}, /* EMs 1 & 4 on */
|
||
|
{ 0, 1, 0, -1, 0, 1, 0, -1}, /* EMs 2 & 4 */
|
||
|
{ 0, -1, -2, -3, 0, 3, 2, 1}, /* EMs 1, 2 & 4 on */
|
||
|
{-3, 0, 3, 2, 1, 0, -1, -2}, /* EMs 3 & 4 on */
|
||
|
{-2, -3, 0, 3, 2, 1, 0, -1}, /* EMs 1, 3 & 4 on */
|
||
|
{ 0, 3, 2, 1, 0, -1, -2, -3}, /* EMs 2, 3 & 4 on */
|
||
|
{ 0, 0, 0, 0, 0, 0, 0, 0}
|
||
|
}; /* all electromagnets on */
|
||
|
|
||
|
static Boolean track_buffer_valid;
|
||
|
static Int8 write_mode;
|
||
|
static UInt8 *nibble_buf;
|
||
|
static UInt16 track_buffer_pos;
|
||
|
static UInt16 track_buffer_size;
|
||
|
static UInt8 write_protect;
|
||
|
static UInt8 address_latch, data_latch;
|
||
|
static Boolean motor_state;
|
||
|
static UInt8 drive_no = 0;
|
||
|
struct stateDisk_t
|
||
|
{
|
||
|
char diskname[32];
|
||
|
LocalID diskdb;
|
||
|
DmOpenRef diskimage;
|
||
|
MemHandle track_buffer_handle;
|
||
|
Int16 physical_track_no;
|
||
|
Int16 stepper_status;
|
||
|
Boolean track_buffer_valid;
|
||
|
Boolean track_buffer_raw;
|
||
|
Boolean track_buffer_dirty;
|
||
|
Int8 track_count;
|
||
|
Int8 track_buffer_track;
|
||
|
Int8 write_mode;
|
||
|
Int16 last_track;
|
||
|
UInt8 *nibble_buf;
|
||
|
UInt16 track_buffer_pos;
|
||
|
UInt16 track_buffer_size;
|
||
|
UInt8 write_protect;
|
||
|
UInt8 logical_track;
|
||
|
UInt8 address_latch, data_latch;
|
||
|
} stateDisk[2] = {0};
|
||
|
UInt32 DskIoICountDiff = 0;
|
||
|
UInt32 LastDskIoICount = 0;
|
||
|
|
||
|
/*
|
||
|
* SLOT 6 IO read.
|
||
|
*/
|
||
|
RDMEM_CWRAP(SLT6, address)
|
||
|
{
|
||
|
return (BootROM[address & 0xFF]);
|
||
|
}
|
||
|
void setCurrentDisk(int drive)
|
||
|
{
|
||
|
if (drive != drive_no)
|
||
|
{
|
||
|
if (drive_no)
|
||
|
showDriveState(drive_no, false);
|
||
|
drive_no = drive;
|
||
|
showDiskName(drive_no, stateDisk[drive_no - 1].diskname);
|
||
|
showDriveState(drive_no, motor_state);
|
||
|
}
|
||
|
drive--;
|
||
|
track_buffer_valid = stateDisk[drive].track_buffer_valid;
|
||
|
write_mode = stateDisk[drive].write_mode;
|
||
|
nibble_buf = stateDisk[drive].nibble_buf;
|
||
|
track_buffer_pos = stateDisk[drive].track_buffer_pos;
|
||
|
track_buffer_size = stateDisk[drive].track_buffer_size;
|
||
|
write_protect = stateDisk[drive].write_protect;
|
||
|
address_latch = stateDisk[drive].address_latch;
|
||
|
data_latch = stateDisk[drive].data_latch;
|
||
|
}
|
||
|
int getCurrentDrive(void)
|
||
|
{
|
||
|
return (drive_no | (motor_state ? 0x80 : 0));
|
||
|
}
|
||
|
void updateCurrentDisk(int drive)
|
||
|
{
|
||
|
if (drive--)
|
||
|
{
|
||
|
stateDisk[drive].track_buffer_pos = track_buffer_pos;
|
||
|
stateDisk[drive].address_latch = address_latch;
|
||
|
stateDisk[drive].data_latch = data_latch;
|
||
|
}
|
||
|
}
|
||
|
void load_track_buffer(int drive)
|
||
|
{
|
||
|
UInt8 *values;
|
||
|
|
||
|
if (stateDisk[--drive].diskdb)
|
||
|
{
|
||
|
stateDisk[drive].logical_track = (stateDisk[drive].physical_track_no + 1) >> 2;
|
||
|
if (stateDisk[drive].logical_track >= stateDisk[drive].track_count)
|
||
|
stateDisk[drive].logical_track = stateDisk[drive].track_count - 1;
|
||
|
if ((stateDisk[drive].logical_track != stateDisk[drive].last_track) || !stateDisk[drive].track_buffer_valid)
|
||
|
{
|
||
|
if (stateDisk[drive].track_buffer_dirty && !stateDisk[drive].track_buffer_raw)
|
||
|
{
|
||
|
stateDisk[drive].track_buffer_handle = DmGetRecord(stateDisk[drive].diskimage, stateDisk[drive].last_track);
|
||
|
values = (UInt8 *) MemHandleLock(stateDisk[drive].track_buffer_handle);
|
||
|
NibblesToSectors(stateDisk[drive].nibble_buf, values, 254, stateDisk[drive].last_track);
|
||
|
MemHandleUnlock(stateDisk[drive].track_buffer_handle);
|
||
|
DmReleaseRecord(stateDisk[drive].diskimage, stateDisk[drive].last_track, true);
|
||
|
}
|
||
|
else if (stateDisk[drive].track_buffer_handle)
|
||
|
MemHandleUnlock(stateDisk[drive].track_buffer_handle);
|
||
|
stateDisk[drive].track_buffer_handle = DmQueryRecord(stateDisk[drive].diskimage, stateDisk[drive].logical_track);
|
||
|
values = (UInt8 *) MemHandleLock(stateDisk[drive].track_buffer_handle);
|
||
|
if (stateDisk[drive].track_buffer_raw)
|
||
|
stateDisk[drive].nibble_buf = values;
|
||
|
else
|
||
|
{
|
||
|
SectorsToNibbles(values, stateDisk[drive].nibble_buf, 254, stateDisk[drive].logical_track);
|
||
|
MemHandleUnlock(stateDisk[drive].track_buffer_handle);
|
||
|
stateDisk[drive].track_buffer_handle = 0;
|
||
|
}
|
||
|
stateDisk[drive].last_track = stateDisk[drive].logical_track;
|
||
|
stateDisk[drive].track_buffer_track = stateDisk[drive].physical_track_no;
|
||
|
stateDisk[drive].track_buffer_dirty = false;
|
||
|
stateDisk[drive].track_buffer_valid = true;
|
||
|
stateDisk[drive].track_buffer_pos = 0;
|
||
|
if (drive_no == (drive + 1))
|
||
|
setCurrentDisk(drive_no);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
void write_nibble(UInt8 data)
|
||
|
{
|
||
|
if (!track_buffer_valid)
|
||
|
load_track_buffer(drive_no);
|
||
|
else if (DskIoICountDiff > 100)
|
||
|
{
|
||
|
if (DskIoICountDiff < 65536)
|
||
|
{
|
||
|
/*
|
||
|
* Advance position based on instruction count.
|
||
|
*/
|
||
|
track_buffer_pos += (DskIoICountDiff >> 12) * (track_buffer_size >> 4); /* divide by ~4096 instructions per sector */
|
||
|
if (track_buffer_pos >= track_buffer_size)
|
||
|
track_buffer_pos -= track_buffer_size;
|
||
|
}
|
||
|
if (track_buffer_size == RAW_TRACK_BYTES)
|
||
|
{
|
||
|
/*
|
||
|
* Round position up to a sector boundary.
|
||
|
*/
|
||
|
if (track_buffer_pos > RAW_SECTOR_BYTES*15)
|
||
|
track_buffer_pos = 0;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*14)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*15;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*13)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*14;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*12)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*13;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*11)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*12;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*10)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*11;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*9)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*10;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*8)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*9;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*7)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*8;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*6)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*7;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*5)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*6;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*4)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*5;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*3)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*4;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*2)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*3;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*1)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*2;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*0)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*1;
|
||
|
}
|
||
|
}
|
||
|
nibble_buf[track_buffer_pos] = data;
|
||
|
if (++track_buffer_pos >= track_buffer_size)
|
||
|
track_buffer_pos = 0;
|
||
|
stateDisk[drive_no - 1].track_buffer_dirty = true;
|
||
|
}
|
||
|
UInt8 read_nibble()
|
||
|
{
|
||
|
UInt8 data;
|
||
|
|
||
|
if (!track_buffer_valid)
|
||
|
load_track_buffer(drive_no);
|
||
|
else if (DskIoICountDiff > 100)
|
||
|
{
|
||
|
if (DskIoICountDiff < 65536)
|
||
|
{
|
||
|
/*
|
||
|
* Advance position based on instruction count.
|
||
|
*/
|
||
|
track_buffer_pos += (DskIoICountDiff >> 12) * (track_buffer_size >> 4); /* divide by ~4096 instructions per sector */
|
||
|
if (track_buffer_pos >= track_buffer_size)
|
||
|
track_buffer_pos -= track_buffer_size;
|
||
|
}
|
||
|
if (track_buffer_size == RAW_TRACK_BYTES)
|
||
|
{
|
||
|
/*
|
||
|
* Round position up to a sector boundary.
|
||
|
*/
|
||
|
if (track_buffer_pos > RAW_SECTOR_BYTES*15)
|
||
|
track_buffer_pos = 0;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*14)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*15;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*13)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*14;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*12)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*13;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*11)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*12;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*10)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*11;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*9)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*10;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*8)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*9;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*7)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*8;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*6)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*7;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*5)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*6;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*4)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*5;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*3)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*4;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*2)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*3;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*1)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*2;
|
||
|
else if (track_buffer_pos > RAW_SECTOR_BYTES*0)
|
||
|
track_buffer_pos = RAW_SECTOR_BYTES*1;
|
||
|
}
|
||
|
}
|
||
|
data = nibble_buf[track_buffer_pos];
|
||
|
if (++track_buffer_pos >= track_buffer_size)
|
||
|
track_buffer_pos = 0;
|
||
|
return (data);
|
||
|
}
|
||
|
void toggleStepper(int drive, UInt8 magnet, UInt8 on)
|
||
|
{
|
||
|
if (drive--)
|
||
|
{
|
||
|
if (on)
|
||
|
stateDisk[drive].stepper_status |= (1 << magnet);
|
||
|
else
|
||
|
stateDisk[drive].stepper_status &= ~(1 << magnet);
|
||
|
if (motor_state)
|
||
|
{
|
||
|
stateDisk[drive].physical_track_no += stepper_movement_table[stateDisk[drive].stepper_status][stateDisk[drive].physical_track_no & 0x07];
|
||
|
if (stateDisk[drive].physical_track_no < 0)
|
||
|
stateDisk[drive].physical_track_no = 0;
|
||
|
else if (stateDisk[drive].physical_track_no >= MAX_PHYSICAL_TRACK_NO)
|
||
|
stateDisk[drive].physical_track_no = MAX_PHYSICAL_TRACK_NO - 1;
|
||
|
stateDisk[drive].track_buffer_valid = track_buffer_valid = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
void toggleMotor(int drive, Boolean on_off)
|
||
|
{
|
||
|
if (drive--)
|
||
|
{
|
||
|
if (motor_state != on_off)
|
||
|
{
|
||
|
motor_state = on_off;
|
||
|
showDriveState(drive_no, motor_state);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
void positionDisk(int drive, UInt16 new_track, UInt16 new_position)
|
||
|
{
|
||
|
drive--;
|
||
|
stateDisk[drive].physical_track_no = new_track << 2;
|
||
|
if (stateDisk[drive].physical_track_no >= MAX_PHYSICAL_TRACK_NO)
|
||
|
stateDisk[drive].physical_track_no = MAX_PHYSICAL_TRACK_NO - 1;
|
||
|
load_track_buffer(drive + 1);
|
||
|
stateDisk[drive].track_buffer_pos = new_position;
|
||
|
if (stateDisk[drive].track_buffer_pos >= stateDisk[drive].track_buffer_size)
|
||
|
stateDisk[drive].track_buffer_pos = 0;
|
||
|
if (drive_no == (drive + 1))
|
||
|
setCurrentDisk(drive_no);
|
||
|
}
|
||
|
void queryDisk(int drive, UInt16 *track, UInt16 *pos)
|
||
|
{
|
||
|
if (drive-- == drive_no)
|
||
|
updateCurrentDisk(drive_no);
|
||
|
*track = stateDisk[drive].physical_track_no >> 2;
|
||
|
*pos = stateDisk[drive].track_buffer_pos;
|
||
|
}
|
||
|
int mountDisk(int drive, char *file, Boolean writeable)
|
||
|
{
|
||
|
UInt16 attrs;
|
||
|
UInt32 type, numrecs, ttlbytes, recbytes;
|
||
|
umountDisk(drive--);
|
||
|
stateDisk[drive].track_buffer_pos = 0;
|
||
|
stateDisk[drive].track_buffer_dirty = false;
|
||
|
stateDisk[drive].diskdb = file ? DmFindDatabase(0, file) : 0;
|
||
|
if (stateDisk[drive].diskdb)
|
||
|
{
|
||
|
StrCopy(stateDisk[drive].diskname, file);
|
||
|
stateDisk[drive].diskimage = DmOpenDatabase(0, stateDisk[drive].diskdb, 0);
|
||
|
DmDatabaseInfo(0, stateDisk[drive].diskdb, NULL, &attrs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &type, NULL);
|
||
|
stateDisk[drive].track_buffer_raw = (type == (UInt32)'RDSK') ? true : false;
|
||
|
stateDisk[drive].write_protect = attrs & dmHdrAttrReadOnly ? true : !writeable;
|
||
|
DmDatabaseSize(0, stateDisk[drive].diskdb, &numrecs, &ttlbytes, &recbytes);
|
||
|
stateDisk[drive].track_count = numrecs;
|
||
|
if (stateDisk[drive].track_buffer_raw)
|
||
|
{
|
||
|
stateDisk[drive].track_buffer_size = recbytes / stateDisk[drive].track_count;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
stateDisk[drive].nibble_buf = MemPtrNew(RAW_TRACK_BYTES);
|
||
|
stateDisk[drive].track_buffer_size = RAW_TRACK_BYTES;
|
||
|
init_GCR_table();
|
||
|
}
|
||
|
stateDisk[drive].track_buffer_handle = 0;
|
||
|
stateDisk[drive].track_buffer_valid = false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
stateDisk[drive].diskname[0] = '\0';
|
||
|
stateDisk[drive].diskimage = 0;
|
||
|
stateDisk[drive].nibble_buf = MemPtrNew(RAW_TRACK_BYTES);
|
||
|
MemSet(stateDisk[drive].nibble_buf, RAW_TRACK_BYTES, 0xFF);
|
||
|
stateDisk[drive].track_buffer_handle = 0;
|
||
|
stateDisk[drive].track_buffer_size = RAW_TRACK_BYTES;
|
||
|
stateDisk[drive].track_buffer_valid = true;
|
||
|
stateDisk[drive].write_protect = true;
|
||
|
}
|
||
|
if (drive_no == (drive + 1))
|
||
|
{
|
||
|
drive_no = 0;
|
||
|
setCurrentDisk(drive + 1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
showDiskName(drive + 1, stateDisk[drive].diskname);
|
||
|
showDriveState(drive + 1, false);
|
||
|
}
|
||
|
return (stateDisk[drive].diskdb != 0);
|
||
|
}
|
||
|
void umountDisk(int drive)
|
||
|
{
|
||
|
UInt8 *values;
|
||
|
|
||
|
if (drive-- == drive_no)
|
||
|
updateCurrentDisk(drive_no);
|
||
|
if (stateDisk[drive].diskdb)
|
||
|
{
|
||
|
if (!stateDisk[drive].track_buffer_raw)
|
||
|
{
|
||
|
if (stateDisk[drive].track_buffer_dirty)
|
||
|
{
|
||
|
stateDisk[drive].track_buffer_handle = DmGetRecord(stateDisk[drive].diskimage, stateDisk[drive].last_track);
|
||
|
values = (UInt8 *) MemHandleLock(stateDisk[drive].track_buffer_handle);
|
||
|
NibblesToSectors(stateDisk[drive].nibble_buf, values, 254, stateDisk[drive].last_track);
|
||
|
MemHandleUnlock(stateDisk[drive].track_buffer_handle);
|
||
|
DmReleaseRecord(stateDisk[drive].diskimage, stateDisk[drive].last_track, true);
|
||
|
}
|
||
|
MemPtrFree(stateDisk[drive].nibble_buf);
|
||
|
}
|
||
|
else if (stateDisk[drive].track_buffer_handle)
|
||
|
{
|
||
|
MemHandleUnlock(stateDisk[drive].track_buffer_handle);
|
||
|
}
|
||
|
DmCloseDatabase(stateDisk[drive].diskimage);
|
||
|
stateDisk[drive].diskdb = 0;
|
||
|
}
|
||
|
else if (stateDisk[drive].nibble_buf)
|
||
|
MemPtrFree(stateDisk[drive].nibble_buf);
|
||
|
stateDisk[drive].nibble_buf = NULL;
|
||
|
stateDisk[drive].track_buffer_handle = 0;
|
||
|
stateDisk[drive].track_buffer_valid = false;
|
||
|
toggleMotor(drive + 1, 0);
|
||
|
}
|
||
|
void resetDisks(void)
|
||
|
{
|
||
|
#if 0
|
||
|
UInt8 drive, *values;
|
||
|
|
||
|
updateCurrentDisk(drive_no);
|
||
|
for (drive = 0; drive < 2; drive++)
|
||
|
{
|
||
|
if (stateDisk[drive].diskdb)
|
||
|
{
|
||
|
if (!stateDisk[drive].track_buffer_raw)
|
||
|
{
|
||
|
if (stateDisk[drive].track_buffer_dirty)
|
||
|
{
|
||
|
stateDisk[drive].track_buffer_handle = DmGetRecord(stateDisk[drive].diskimage, stateDisk[drive].last_track);
|
||
|
values = (UInt8 *) MemHandleLock(stateDisk[drive].track_buffer_handle);
|
||
|
NibblesToSectors(stateDisk[drive].nibble_buf, values, 254, stateDisk[drive].last_track);
|
||
|
MemHandleUnlock(stateDisk[drive].track_buffer_handle);
|
||
|
DmReleaseRecord(stateDisk[drive].diskimage, stateDisk[drive].last_track, true);
|
||
|
}
|
||
|
}
|
||
|
else if (stateDisk[drive].track_buffer_handle)
|
||
|
{
|
||
|
MemHandleUnlock(stateDisk[drive].track_buffer_handle);
|
||
|
}
|
||
|
}
|
||
|
toggleMotor(drive + 1, 0);
|
||
|
stateDisk[drive].physical_track_no = 0;
|
||
|
stateDisk[drive].track_buffer_handle = 0;
|
||
|
stateDisk[drive].track_buffer_pos = 0;
|
||
|
stateDisk[drive].track_buffer_valid = false;
|
||
|
stateDisk[drive].track_buffer_dirty = false;
|
||
|
}
|
||
|
#else
|
||
|
umountDisk(1);
|
||
|
umountDisk(2);
|
||
|
mountDisk(1, stateDisk[0].diskname, stateDisk[0].write_protect);
|
||
|
mountDisk(2, stateDisk[1].diskname, stateDisk[1].write_protect);
|
||
|
#endif
|
||
|
drive_no = 0;
|
||
|
setCurrentDisk(1);
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************\
|
||
|
* *
|
||
|
* I/O page access *
|
||
|
* *
|
||
|
\*****************************************************************************/
|
||
|
|
||
|
/*
|
||
|
* I/O Read.
|
||
|
*/
|
||
|
UInt8 RIOM(UInt16);
|
||
|
UInt8 cwrap_RIOM(UInt16);
|
||
|
UInt8 awrap_RIOM(UInt16 a)
|
||
|
{
|
||
|
asm(".global RIOM");
|
||
|
asm("RIOM:");
|
||
|
/*
|
||
|
* Quick check for Disk read byte.
|
||
|
*/
|
||
|
asm("cmp.b #0xEC, %d6");
|
||
|
asm("bne.b L1");
|
||
|
/*
|
||
|
* Check for buffer valid.
|
||
|
*/
|
||
|
asm("tst.b track_buffer_valid@END.w(%a5)");
|
||
|
asm("beq.b L1");
|
||
|
/*
|
||
|
* Update access time.
|
||
|
*/
|
||
|
asm("move.l AppleInstrInc@END.w(%a5), %d0");
|
||
|
asm("sub.l %d1, %d0");
|
||
|
asm("add.l AppleInstrCount@END.w(%a5), %d0");
|
||
|
asm("move.l %d0, %a6");
|
||
|
asm("sub.l LastDskIoICount@END.w(%a5), %d0");
|
||
|
asm("move.l %d0, DskIoICountDiff@END.w(%a5)");
|
||
|
asm("move.l %a6, LastDskIoICount@END.w(%a5)");
|
||
|
/*
|
||
|
* Check for back-to-back read.
|
||
|
*/
|
||
|
asm("cmp.l #100, %d0"); // This is the instruction count that determines if it is back-to-back
|
||
|
asm("bgt.b L1");
|
||
|
/*
|
||
|
* Check for read or write.
|
||
|
*/
|
||
|
asm("tst.b write_mode@END.w(%a5)");
|
||
|
asm("bne.b L1");
|
||
|
/*
|
||