System almost boots, but VIA interrupts are borked

This commit is contained in:
InvisibleUp 2020-07-12 22:12:19 -04:00
parent 725f477884
commit 027e2397c4
8 changed files with 274 additions and 170 deletions

View File

@ -37,6 +37,7 @@
#include "GLOBGLUE.h"
#include "HW/RAM/RAMADDR.h"
#include "HW/VIA/VIAEMDEV.h"
#include "HW/SCC/SCCEMDEV.h"
/*
ReportAbnormalID unused 0x111D - 0x11FF
@ -1519,28 +1520,28 @@ LOCALVAR uint8_t CurIPL = 0;
GLOBALPROC VIAorSCCinterruptChngNtfy(void)
{
#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
uint8_t NewIPL;
if (InterruptButton) {
NewIPL = 7;
} else if (SCCInterruptRequest) {
NewIPL = 4;
} else if (VIA2_InterruptRequest) {
NewIPL = 2;
} else if (VIA1_InterruptRequest) {
NewIPL = 1;
} else {
NewIPL = 0;
}
#else
uint8_t VIA1_InterruptRequest = (VIA_Read(VIA1, rIFR) & 0b01111111) != 0;
uint8_t SCCInterruptRequest = 0;
uint8_t VIAandNotSCC = VIA1_InterruptRequest & ~ SCCInterruptRequest;
uint8_t NewIPL = VIAandNotSCC
| (SCCInterruptRequest << 1)
| (InterruptButton << 2);
#endif
uint8_t VIA2_InterruptRequest = (VIA_Read(VIA2, rIFR) & 0b01111111) != 0;
if ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)) {
if (InterruptButton) {
NewIPL = 7;
} else if (SCCInterruptRequest) {
NewIPL = 4;
} else if (VIA2_InterruptRequest) {
NewIPL = 2;
} else if (VIA1_InterruptRequest) {
NewIPL = 1;
} else {
NewIPL = 0;
}
} else {
uint8_t VIAandNotSCC = VIA1_InterruptRequest & ~ SCCInterruptRequest;
NewIPL = VIAandNotSCC
| (SCCInterruptRequest << 1)
| (InterruptButton << 2);
}
if (NewIPL != CurIPL) {
CurIPL = NewIPL;
m68k_IPLchangeNtfy();

View File

@ -38,6 +38,7 @@
#endif
#include "HW/DISK/SONYEMDV.h"
#include <stdio.h>
/*
ReportAbnormalID unused 0x090B - 0x09FF
@ -926,7 +927,12 @@ typedef struct DriverDat_R DriverDat_R;
#define kcom_checkval 0x841339E2
#define Sony_dolog (dbglog_HAVE && 0)
//#define Sony_dolog (dbglog_HAVE && 0)
#define dbglog_StartLine()
#define dbglog_writeCStr(str) fprintf(stderr, "%s", str)
#define dbglog_writeHex(hex) fprintf(stderr, "$%X", hex)
#define dbglog_WriteNote(str) fprintf(stderr, "%s\n", str)
#define dbglog_writeReturn(str) fprintf(stderr, "\n")
#if Sony_SupportTags
LOCALVAR CPTR TheTagBuffer;
@ -952,22 +958,23 @@ LOCALFUNC MacErr_t Sony_Mount(CPTR p)
CPTR dvl = DriveVarsLocation(i);
if (0 == dvl) {
#if Sony_dolog
//#if Sony_dolog
dbglog_WriteNote("Sony : Mount : no dvl");
#endif
//#endif
result = mnvm_nsDrvErr;
} else if (get_vm_byte(dvl + kDiskInPlace) == 0x00) {
uint32_t L = ImageDataSize[i] >> 9; /* block count */
#if Sony_dolog
//fprintf(stderr, "Sony : Mount : Drive=%d, L=$%x\n", i, L);
//#if Sony_dolog
dbglog_StartLine();
dbglog_writeCStr("Sony : Mount : Drive=");
dbglog_writeHex(i);
dbglog_writeCStr(", L=");
dbglog_writeHex(L);
dbglog_writeReturn();
#endif
//#endif
#if CurEmMd <= kEmMd_Twiggy
if (L == 1702) {
@ -1026,9 +1033,9 @@ LOCALFUNC MacErr_t Sony_Mount(CPTR p)
result = mnvm_noErr;
} else {
/* disk already in place, a mistake has been made */
#if Sony_dolog
//#if Sony_dolog
dbglog_WriteNote("Sony : Mount : already in place");
#endif
//#endif
}
return result;
@ -1097,18 +1104,18 @@ LOCALFUNC MacErr_t Sony_Prime(CPTR p)
CPTR dvl = DriveVarsLocation(Drive_No);
if (0 == dvl) {
#if Sony_dolog
//#if Sony_dolog
dbglog_WriteNote("Sony : Prime : no dvl");
#endif
//#endif
result = mnvm_nsDrvErr;
} else
#if CurEmMd >= kEmMd_Twiggy
if (0xA002 != (IOTrap & 0xF0FE)) {
#if Sony_dolog
//#if Sony_dolog
dbglog_WriteNote("Sony : Prime : "
"not read (0xA002) or write (0xA003)");
#endif
//#endif
result = mnvm_controlErr;
} else
@ -1191,7 +1198,7 @@ LOCALFUNC MacErr_t Sony_Prime(CPTR p)
Sony_Count = get_vm_long(ParamBlk + kioReqCount);
#if Sony_dolog
//#if Sony_dolog
dbglog_StartLine();
dbglog_writeCStr("Sony : Prime : Drive=");
dbglog_writeHex(Drive_No);
@ -1202,7 +1209,7 @@ LOCALFUNC MacErr_t Sony_Prime(CPTR p)
dbglog_writeCStr(", Count=");
dbglog_writeHex(Sony_Count);
dbglog_writeReturn();
#endif
//#endif
if ((0 != (Sony_Start & 0x1FF))
|| (0 != (Sony_Count & 0x1FF)))
@ -1248,15 +1255,15 @@ LOCALFUNC MacErr_t Sony_Control(CPTR p)
uint16_t OpCode = get_vm_word(ParamBlk + kcsCode);
if (kKillIO == OpCode) {
#if Sony_dolog
//#if Sony_dolog
dbglog_WriteNote("Sony : Control : kKillIO");
#endif
//#endif
result = mnvm_miscErr;
} else if (kSetTagBuffer == OpCode) {
#if Sony_dolog
//#if Sony_dolog
dbglog_WriteNote("Sony : Control : kSetTagBuffer");
#endif
//#endif
#if Sony_SupportTags
TheTagBuffer = get_vm_long(ParamBlk + kcsParam);
@ -1265,9 +1272,9 @@ LOCALFUNC MacErr_t Sony_Control(CPTR p)
result = mnvm_controlErr;
#endif
} else if (kTrackCacheControl == OpCode) {
#if Sony_dolog
//#if Sony_dolog
dbglog_WriteNote("Sony : Control : kTrackCacheControl");
#endif
//#endif
#if CurEmMd <= kEmMd_128K
result = mnvm_controlErr;
@ -1294,33 +1301,33 @@ LOCALFUNC MacErr_t Sony_Control(CPTR p)
CPTR dvl = DriveVarsLocation(Drive_No);
if (0 == dvl) {
#if Sony_dolog
//#if Sony_dolog
dbglog_WriteNote("Sony : Control : no dvl");
#endif
//#endif
result = mnvm_nsDrvErr;
} else if (get_vm_byte(dvl + kDiskInPlace) == 0) {
#if Sony_dolog
//#if Sony_dolog
dbglog_WriteNote("Sony : Control : not DiskInPlace");
#endif
//#endif
result = mnvm_offLinErr;
} else {
switch (OpCode) {
case kVerifyDisk :
#if Sony_dolog
//#if Sony_dolog
dbglog_WriteNote("Sony : Control : kVerifyDisk");
#endif
//#endif
result = mnvm_noErr;
break;
case kEjectDisk :
#if Sony_dolog
//#if Sony_dolog
dbglog_StartLine();
dbglog_writeCStr("Sony : Control : kEjectDisk : ");
dbglog_writeHex(Drive_No);
dbglog_writeReturn();
#endif
//#endif
put_vm_byte(dvl + kWriteProt, 0x00);
/* Drive Writeable */
@ -1336,22 +1343,22 @@ LOCALFUNC MacErr_t Sony_Control(CPTR p)
result = Drive_Eject(Drive_No);
break;
case kFormatDisk :
#if Sony_dolog
//#if Sony_dolog
dbglog_StartLine();
dbglog_writeCStr("Sony : Control : kFormatDisk : ");
dbglog_writeHex(Drive_No);
dbglog_writeReturn();
#endif
//#endif
result = mnvm_noErr;
break;
case kDriveIcon :
#if Sony_dolog
//#if Sony_dolog
dbglog_StartLine();
dbglog_writeCStr("Sony : Control : kDriveIcon : ");
dbglog_writeHex(Drive_No);
dbglog_writeReturn();
#endif
//#endif
if (get_vm_word(dvl + kQType) != 0) {
put_vm_long(ParamBlk + kcsParam,
@ -1370,13 +1377,13 @@ LOCALFUNC MacErr_t Sony_Control(CPTR p)
{
uint32_t v;
#if Sony_dolog
//#if Sony_dolog
dbglog_StartLine();
dbglog_writeCStr(
"Sony : Control : kDriveInfo : ");
dbglog_writeHex(kDriveIcon);
dbglog_writeReturn();
#endif
//#endif
if (get_vm_word(dvl + kQType) != 0) {
v = 0x00000001; /* unspecified drive */
@ -1397,12 +1404,12 @@ LOCALFUNC MacErr_t Sony_Control(CPTR p)
break;
#endif
default :
#if Sony_dolog
//#if Sony_dolog
dbglog_StartLine();
dbglog_writeCStr("Sony : Control : OpCode : ");
dbglog_writeHex(OpCode);
dbglog_writeReturn();
#endif
//#endif
#if ExtraAbnormalReports
if ((kGetIconID != OpCode)
&& (kMediaIcon != OpCode)
@ -1436,12 +1443,12 @@ LOCALFUNC MacErr_t Sony_Status(CPTR p)
/* CPTR DeviceCtl = get_vm_long(p + ExtnDat_params + 4); */
uint16_t OpCode = get_vm_word(ParamBlk + kcsCode);
#if Sony_dolog
//#if Sony_dolog
dbglog_StartLine();
dbglog_writeCStr("Sony : Sony_Status OpCode = ");
dbglog_writeHex(OpCode);
dbglog_writeReturn();
#endif
//#endif
if (kDriveStatus == OpCode) {
tDrive Drive_No = get_vm_word(ParamBlk + kioVRefNum) - 1;
@ -1483,11 +1490,12 @@ LOCALFUNC MacErr_t Sony_Close(CPTR p)
return mnvm_closErr; /* Can't Close Driver */
}
// Initialize disk subsystem
LOCALFUNC MacErr_t Sony_OpenA(CPTR p)
{
#if Sony_dolog
//#if Sony_dolog
dbglog_WriteNote("Sony : OpenA");
#endif
//#endif
if (MountCallBack != 0) {
return mnvm_opWrErr; /* driver already open */
@ -1504,14 +1512,15 @@ LOCALFUNC MacErr_t Sony_OpenA(CPTR p)
}
}
// Initialize disk drives
LOCALFUNC MacErr_t Sony_OpenB(CPTR p)
{
int16_t i;
CPTR dvl;
#if Sony_dolog
//#if Sony_dolog
dbglog_WriteNote("Sony : OpenB");
#endif
//#endif
CPTR SonyVars = get_vm_long(p + ExtnDat_params + 4);
/* CPTR ParamBlk = get_vm_long(p + ExtnDat_params + 24); (unused) */
@ -1579,11 +1588,12 @@ LOCALFUNC MacErr_t Sony_OpenB(CPTR p)
return mnvm_noErr;
}
// Write callback address for M68k to mount disks w/
LOCALFUNC MacErr_t Sony_OpenC(CPTR p)
{
#if Sony_dolog
//#if Sony_dolog
dbglog_WriteNote("Sony : OpenC");
#endif
//#endif
MountCallBack = get_vm_long(p + ExtnDat_params + 0)
#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)

View File

@ -29,21 +29,12 @@
#include "HW/KBRD/KBRDEMDV.h"
#include "HW/VIA/VIAEMDEV.h"
#ifdef _VIA_Debug
#include <stdio.h>
#endif
/*
ReportAbnormalID unused 0x0B03 - 0x0BFF
*/
void KYBD_ShiftOutData(uint8_t v) {
VIA_ShiftInData(VIA1, v);
}
uint8_t KYBD_ShiftInData(void) {
return VIA_ShiftOutData(VIA1);
}
enum {
kKybdStateIdle,
kKybdStateRecievingCommand,
@ -64,7 +55,7 @@ LOCALPROC GotKeyBoardData(uint8_t v)
HaveKeyBoardResult = true;
KeyBoardResult = v;
} else {
v = VIA_Read(VIA1, rSR);
VIA_ShiftInData_Ext(VIA1, v);
VIA_RaiseInterrupt(VIA1, 2);
}
}
@ -118,8 +109,9 @@ GLOBALPROC DoKybd_ReceiveCommand(void)
ReportAbnormalID(0x0B01,
"KybdState != kKybdStateRecievingCommand");
} else {
uint8_t in = KYBD_ShiftInData();
uint8_t in = VIA_ShiftOutData_Ext(VIA1);
fprintf(stderr, "KybdStateRecievedCommand\n");
KybdState = kKybdStateRecievedCommand;
switch (in) {
@ -161,6 +153,7 @@ GLOBALPROC DoKybd_ReceiveEndCommand(void)
"KybdState != kKybdStateRecievingEndCommand");
} else {
KybdState = kKybdStateIdle;
fprintf(stderr, "KybdStateIdle\n");
#ifdef _VIA_Debug
fprintf(stderr, "enter DoKybd_ReceiveEndCommand\n");
#endif
@ -169,7 +162,7 @@ GLOBALPROC DoKybd_ReceiveEndCommand(void)
fprintf(stderr, "HaveKeyBoardResult: %d\n", KeyBoardResult);
#endif
HaveKeyBoardResult = false;
KYBD_ShiftOutData(KeyBoardResult);
VIA_ShiftInData_Ext(VIA1, KeyBoardResult);
}
}
}
@ -178,13 +171,14 @@ GLOBALPROC Kybd_DataLineChngNtfy(void)
{
switch (KybdState) {
case kKybdStateIdle:
if (Kybd_CheckDataReady() == 0) {
if (Kybd_CheckDataReady() == 1) {
fprintf(stderr, "KybdStateRecievingCommand\n");
KybdState = kKybdStateRecievingCommand;
#ifdef _VIA_Debug
fprintf(stderr, "posting kICT_Kybd_ReceiveCommand\n");
#endif
/*ICT_add(kICT_Kybd_ReceiveCommand,
6800UL * kCycleScale / 64 * ClockMult);*/
ICT_add(kICT_Kybd_ReceiveCommand,
6800UL * kCycleScale / 64 * ClockMult);
if (InquiryCommandTimer != 0) {
InquiryCommandTimer = 0; /* abort Inquiry */
@ -192,14 +186,15 @@ GLOBALPROC Kybd_DataLineChngNtfy(void)
}
break;
case kKybdStateRecievedCommand:
if (Kybd_CheckDataReady() == 1) {
if (Kybd_CheckDataReady() == 0) {
KybdState = kKybdStateRecievingEndCommand;
fprintf(stderr, "KybdStateRecievingEndCommand\n");
#ifdef _VIA_Debug
fprintf(stderr,
"posting kICT_Kybd_ReceiveEndCommand\n");
#endif
/*ICT_add(kICT_Kybd_ReceiveEndCommand,
6800UL * kCycleScale / 64 * ClockMult);*/
ICT_add(kICT_Kybd_ReceiveEndCommand,
6800UL * kCycleScale / 64 * ClockMult);
}
break;
}

View File

@ -38,8 +38,6 @@
"Zilog SCC/ESCC User's Manual".
*/
#if 0
#include "SYSDEPNS.h"
#include "UI/MYOSGLUE.h"
@ -257,17 +255,19 @@ static int rx_data_offset = 0;
/// VIA INTERFACE FUNCTIONS //////////////////////////////////////////////////
bool SCC_GetvSCCWrReq()
uint8_t SCCInterruptRequest;
static bool SCC_GetvSCCWrReq()
{
return VIA_ReadBit(VIA1, rIRA, 7);
}
void SCC_SetvSCCWrReq(bool value)
static void SCC_SetvSCCWrReq(bool value)
{
VIA_WriteBit(VIA1, rIRA, 7, value, false);
}
bool SCC_GetvSync()
static bool SCC_GetvSync()
{
switch(CurEmMd) {
case kEmMd_SE:
@ -598,7 +598,7 @@ LOCALPROC SCC_ResetChannel(int chan)
GLOBALPROC SCC_Reset(void)
{
SCCwaitrq = 1;
SCC_SetvSCCWrReq(1);
SCC.SCC_Interrupt_Type = 0;
@ -2827,5 +2827,3 @@ GLOBALFUNC uint32_t SCC_Access(uint32_t Data, bool WriteMem, CPTR addr)
return Data;
}
#endif

View File

@ -17,10 +17,9 @@
#ifndef SCCEMDEV_H
#define SCCEMDEV_H
extern uint8_t SCCInterruptRequest;
EXPORTPROC SCC_Reset(void);
EXPORTFUNC uint32_t SCC_Access(uint32_t Data, bool WriteMem, CPTR addr);
EXPORTFUNC bool SCC_InterruptsEnabled(void);
#if EmLocalTalk

View File

@ -33,6 +33,23 @@
/* Global state */
VIA_State_t VIA_State[VIA_MAXNUM];
#define CyclesPerViaTime (10 * ClockMult)
#define CyclesScaledPerViaTime (kCycleScale * CyclesPerViaTime)
// TODO: Move these into the VIA_State_t struct
bool VIA1_T1Running = true;
bool VIA1_T1IntReady = false;
iCountt VIA1_T1LastTime = 0;
uint8_t VIA1_T1_Active = 0;
const uint8_t VIA_T1_IRQ = 6;
bool VIA1_T2Running = true;
bool VIA1_T2IntReady = false;
bool VIA1_T2C_ShortTime = false;
iCountt VIA1_T2LastTime = 0;
uint8_t VIA1_T2_Active = 0;
const uint8_t VIA_T2_IRQ = 5;
// Hardware reset
bool VIA_Zap(void) {
memset(VIA_State, 0, sizeof(VIA_State));
@ -42,14 +59,29 @@ bool VIA_Zap(void) {
// Software reset
void VIA_Reset(void) {
for (int i = 0; i < VIA_MAXNUM; i += 1) {
VIA_State[i].vBufA = 0xFF;
VIA_State[i].vBufB = 0xFF;
VIA_State[i].vBufA = 0x00;
VIA_State[i].vBufB = 0x00;
VIA_State[i].vDirA = 0x00;
VIA_State[i].vDirB = 0x00;
VIA_State[i].vIER = 0x00;
VIA_State[i].vIFR = 0x00;
VIA_State[i].vSR = 0x00;
VIA_State[i].vACR = 0x00;
VIA_State[i].vPCR = 0x00;
VIA_State[i].vT1C = 0x00;
VIA_State[i].vT1L = 0x00;
VIA_State[i].vT2C = 0x00;
VIA_State[i].vT2L = 0x00;
}
// temporary
VIA1_T1Running = false;
VIA1_T1IntReady = false;
VIA1_T1LastTime = 0;
VIA1_T1_Active = 0;
VIA1_T2Running = false;
VIA1_T2IntReady = false;
VIA1_T2LastTime = 0;
VIA1_T2_Active = 0;
}
// Raise an interrupt by irq number
@ -60,16 +92,18 @@ void VIA_RaiseInterrupt(uint8_t id, uint8_t irq)
// Set interrupt flag
uint8_t vIFR_old = VIA_State[id].vIFR & VIA_State[id].vIER & 0b01111111;
VIA_State[id].vIFR |= (1 << irq) | (1 << 7);
VIA_State[id].vIFR |= (1 << irq);// | (1 << 7);
uint8_t vIFR_new = VIA_State[id].vIFR & VIA_State[id].vIER & 0b01111111;
// Call interrupt handler, if required
if (vIFR_old != vIFR_new) {
/*if (VIA_State[id].vISR[irq] != NULL) {
if (irq == 2) {
fprintf(stderr, "IRQ %d raised\n", irq);
}
if (VIA_State[id].vISR[irq] != NULL) {
VIA_State[id].vISR[irq]();
}*/
}
VIAorSCCinterruptChngNtfy();
//fprintf(stderr, "IRQ %d raised\n", irq);
} else {
//fprintf(stderr, "IRQ %d attempted\n", irq);
}
@ -88,11 +122,13 @@ void VIA_LowerInterrupt(uint8_t id, uint8_t irq)
// Call interrupt handler, if required
if (vIFR_old != vIFR_new) {
/*if (VIA_State[id].vISR[irq] != NULL) {
VIA_State[id].vISR[irq]();
}*/
if (irq == 2) {
fprintf(stderr, "IRQ %d lowered\n", irq);
}
VIAorSCCinterruptChngNtfy();
//fprintf(stderr, "IRQ %d lowered\n", irq);
if (VIA_State[id].vISR[irq] != NULL) {
VIA_State[id].vISR[irq]();
}
} else {
//fprintf(stderr, "IRQ %d attempted (lower)\n", irq);
}
@ -199,24 +235,6 @@ void VIA_TickTimers()
}
}*/
// Do fancy shift register stuff
void VIA_TickShiftRegister(uint8_t id)
{
assert(id < VIA_MAXNUM);
VIA_State_t *via = &VIA_State[id];
switch ((via->vACR & 0x1C) >> 2) {
case 3 : /* Shifting In */
break;
case 6 : /* shift out under o2 clock */
VIA_LowerInterrupt(id, 3);
VIA_RaiseInterrupt(id, 2);
break;
case 7 : /* Shifting Out */
break;
}
}
// temporary debugging stuff
#define BIN_PAT "%c%c%c%c_%c%c%c%c"
#define TO_BIN(byte) \
@ -236,19 +254,35 @@ void VIA_Write(uint8_t id, VIA_Register_t reg, uint8_t data, bool runISR)
assert(reg < rINVALID);
VIA_State_t *via = &VIA_State[id];
uint8_t data_old = VIA_Read(id, reg);
uint8_t vIFR_old = via->vIFR & via->vIER & 0b01111111;
// Set up before/after comparisions
uint8_t data_old = 0;
if (reg == rIRA || reg == rORA) {
//fprintf(stderr, "Set PA to "BIN_PAT"\n", TO_BIN(data));
data_old = via->vBufA;
} else if (reg == rIRB) {
data_old = via->vBufB;
} else if (reg == rIFR || reg == rIER) {
//data_old = via->vIFR & via->vIER & 0b01111111;
data_old = via->vIFR;
} else if (reg == rACR) {
data_old = via->vACR;
}
/*if (reg == rIRA || reg == rORA) {
fprintf(stderr, "Set PA to "BIN_PAT"\n", TO_BIN(data));
} else {
//`fprintf(stderr, "Set PB to "BIN_PAT"\n", TO_BIN(data));
fprintf(stderr, "Set PB to "BIN_PAT"\n", TO_BIN(data));
}*/
//fprintf(stderr, "VIA%d Write %d <- %d\n", id+1, reg, data);
if (reg == rSR) {
fprintf(stderr, "vSR: %d, %d, %d\n", true, ((via->vACR & 0x1C) >> 2), data);
}
switch(reg) {
case rIRB: via->vIFR &= 0b11100111; // clear keyboard interrupts
via->vBufB = data; break;
case rIRA:
case rORA: via->vBufA = data; break;
case rORA: via->vIFR &= 0b11111100; // clear time interrupts
via->vBufA = data; break;
case rDDRB: via->vDirB = data; break;
case rDDRA: via->vDirA = data; break;
case rT1CL:
@ -263,10 +297,10 @@ void VIA_Write(uint8_t id, VIA_Register_t reg, uint8_t data, bool runISR)
via->vT2C = via->vT2L;
via->vIFR &= 0b10111111;
break;
case rSR: via->vSR = data; break;
case rSR: VIA_ShiftInData_M68k(id, data); break;
case rACR: via->vACR = data; break;
case rPCR: via->vPCR = data; break;
case rIFR: via->vIFR &= (~data & 0b01111111); break;
case rIFR: via->vIFR &= (~data & 0b01111111); break; // seems to be correct?
case rIER:
switch(data & 0b10000000) {
case 0b00000000: // clear
@ -280,10 +314,6 @@ void VIA_Write(uint8_t id, VIA_Register_t reg, uint8_t data, bool runISR)
default: assert(true);
}
/*if ((data_old & via->vIFR) != (data & via->vIFR) && reg == rIFR) {
VIAorSCCinterruptChngNtfy();
}*/
// Assert vBufA or vBufB ISRs if needed
uint8_t diff = (data ^ data_old);
if (runISR && (reg == rIRA || reg == rORA || reg == rIRB)) {
@ -300,17 +330,41 @@ void VIA_Write(uint8_t id, VIA_Register_t reg, uint8_t data, bool runISR)
// Run global ISR if required
uint8_t vIFR_new = via->vIFR & via->vIER & 0b01111111;
uint8_t vIFR_old = data_old & via->vIER & 0b01111111;
if (runISR && (reg == rIFR || reg == rIER) && (vIFR_old != vIFR_new))
{
/*if (VIA_State[id].vISR[irq] != NULL) {
VIA_State[id].vISR[irq]();
}*/
// Iterate through each bit
uint8_t bit = 0;
uint8_t mask = 0b1;
while (mask != 0) {
if ((vIFR_new & vIFR_new & mask) != 0) {
if (via->vISR[bit] != NULL) { via->vISR[bit](); }
}
bit += 1;
mask <<= 1;
}
VIAorSCCinterruptChngNtfy();
//fprintf(stderr, "IRQ raised ("BIN_PAT")\n", TO_BIN((vIFR_old ^ vIFR_new)));
fprintf(stderr, "IRQ raised ("BIN_PAT")\n", TO_BIN((vIFR_old ^ vIFR_new)));
}
else if (reg == rIFR || reg == rIER)
{
//fprintf(stderr, "IRQ attempt ("BIN_PAT")\n", TO_BIN((vIFR_old ^ vIFR_new)));
fprintf(stderr, "IRQ attempt ("BIN_PAT")\n", TO_BIN((data_old ^ vIFR_new)));
}
if (reg == rACR) {
uint8_t ShiftMode = (via->vACR & 0x1C) >> 2;
uint8_t ShiftMode_old = (data_old & 0x1C) >> 2;
// Check if shift direction has changed
if (ShiftMode != 0 && (ShiftMode & 0b100) != (ShiftMode_old & 0b100)) {
if ((ShiftMode & 0b100) == 0) {
VIA_RaiseInterrupt(id, 2);
}
}
// Clear keyboard interrupt flag if we modified shift register params
// Supposedly, this isn't sufficient. I have no idea what that means.
else if (ShiftMode == 0) {
VIA_LowerInterrupt(id, 2);
}
}
}
@ -321,6 +375,10 @@ uint8_t VIA_Read(uint8_t id, VIA_Register_t reg)
assert(reg < rINVALID);
VIA_State_t *via = &VIA_State[id];
if (reg == rSR) {
fprintf(stderr, "vSR: %d, %d, %d\n", false, ((via->vACR & 0x1C) >> 2), via->vSR);
}
switch(reg) {
// not sure if reading *all* of vBufA or vBufB is correct,
// but it shouldn't matter.
@ -338,8 +396,7 @@ uint8_t VIA_Read(uint8_t id, VIA_Register_t reg)
case rT2CL: via->vIFR &= 0b11011111; // TODO: is this used correctly?
return (via->vT2C & 0xFF00) >> 8;
case rT2CH: return (via->vT2C & 0x00FF);
case rSR:
return via->vSR;
case rSR: return VIA_ShiftOutData_M68k(id);
case rACR: return via->vACR;
case rPCR: return via->vPCR;
case rIFR: return via->vIFR;
@ -348,6 +405,14 @@ uint8_t VIA_Read(uint8_t id, VIA_Register_t reg)
}
}
// temporary debugging thing
/*uint8_t VIA_Read(uint8_t id, VIA_Register_t reg)
{
uint8_t result = VIA_Read2(id, reg);
fprintf(stderr, "VIA%d Read %d -> %d\n", id+1, reg, result);
return result;
}*/
// Read a single bit
bool VIA_ReadBit(uint8_t id, VIA_Register_t reg, uint8_t bit)
{
@ -369,56 +434,90 @@ void VIA_WriteBit(uint8_t id, VIA_Register_t reg, uint8_t bit, bool value, bool
VIA_RunDataISR(id, reg, bit);*/
}
// ShiftMode states (from M68k perspective)
// 3: Shifting in (to M68k)
// 6: Shifting out under O2 clock (raise interrupt when done)
// 7: Shifting out
// Called by either end; store data in vSR.
// TODO: this probably shouldn't be instant.
void VIA_ShiftInData(uint8_t id, uint8_t v)
void VIA_ShiftInData_M68k(uint8_t id, uint8_t v)
{
assert(id < VIA_MAXNUM);
VIA_State_t *via = &VIA_State[id];
//VIA_LowerInterrupt(id, 2); // data ready
uint8_t ShiftMode = (via->vACR & 0x1C) >> 2;
assert(ShiftMode == 0 || ShiftMode == 3);
VIA_State[id].vSR = v;
VIA_RaiseInterrupt(id, 2); // data ready
VIA_RaiseInterrupt(id, 4); // data clock
if (ShiftMode == 6) {
VIA_RaiseInterrupt(id, 2); // data ready
VIA_RaiseInterrupt(id, 4); // data clock
}
}
// Called by either end, get data out of vSR
// TODO: this probably shouldn't be instant.
uint8_t VIA_ShiftOutData(uint8_t id)
uint8_t VIA_ShiftOutData_M68k(uint8_t id)
{
assert(id < VIA_MAXNUM);
VIA_State_t *via = &VIA_State[id];
uint8_t ShiftMode = (via->vACR & 0x1C) >> 2;
if (ShiftMode == 3) {
VIA_RaiseInterrupt(id, 2); // data ready
VIA_RaiseInterrupt(id, 4); // data clock
// data bit
if (via->vSR & 1) {
VIA_RaiseInterrupt(id, 3);
} else {
VIA_LowerInterrupt(id, 3);
}
} else {
VIA_LowerInterrupt(id, 2); // data ready
}
return VIA_State[id].vSR;
}
// Same functions, from the peripheal end
void VIA_ShiftInData_Ext(uint8_t id, uint8_t v)
{
assert(id < VIA_MAXNUM);
VIA_State_t *via = &VIA_State[id];
uint8_t ShiftMode = (via->vACR & 0x1C) >> 2;
fprintf(stderr, "vSR: %d, %d, %d (ext)\n", true, ShiftMode, v);
assert(ShiftMode == 0 || ShiftMode == 3);
// Not immediately after startup?
if (ShiftMode != 0) {
VIA_State[id].vSR = v;
VIA_RaiseInterrupt(id, 2); // data ready
VIA_RaiseInterrupt(id, 4); // data clock
}
}
// TODO: this probably shouldn't be instant.
uint8_t VIA_ShiftOutData_Ext(uint8_t id)
{
assert(id < VIA_MAXNUM);
VIA_State_t *via = &VIA_State[id];
uint8_t ShiftMode = (via->vACR & 0x1C) >> 2;
fprintf(stderr, "vSR: %d, %d, %d (ext)\n", false, ShiftMode, VIA_State[id].vSR);
assert(ShiftMode == 7);
VIA_RaiseInterrupt(id, 2); // data ready
VIA_RaiseInterrupt(id, 3); // data rx
VIA_WriteBit(id, rIFR, 4, (via->vSR & 1), false); // data clock
VIA_RaiseInterrupt(id, 4); // data clock
// data bit
if (via->vSR & 1) {
VIA_RaiseInterrupt(id, 3);
} else {
VIA_LowerInterrupt(id, 3);
}
return VIA_State[id].vSR;
}
/// Old messy VIA timer code (VIA-1 only for now) ///
#define CyclesPerViaTime (10 * ClockMult)
#define CyclesScaledPerViaTime (kCycleScale * CyclesPerViaTime)
// TODO: Move these into the VIA_State_t struct
bool VIA1_T1Running = true;
bool VIA1_T1IntReady = false;
iCountt VIA1_T1LastTime = 0;
uint8_t VIA1_T1_Active = 0;
const uint8_t VIA_T1_IRQ = 6;
bool VIA1_T2Running = true;
bool VIA1_T2IntReady = false;
bool VIA1_T2C_ShortTime = false;
iCountt VIA1_T2LastTime = 0;
uint8_t VIA1_T2_Active = 0;
const uint8_t VIA_T2_IRQ = 5;
void VIA1_DoTimer1Check()
{
if (!VIA1_T1Running) { return; }

View File

@ -74,7 +74,7 @@ void VIA_Reset(void);
// Raise an interrupt by irq number, calling registered ISR if required
void VIA_RaiseInterrupt(uint8_t id, uint8_t irq);
// Register a VIA interrupt service routine
//void VIA_RegisterISR(uint8_t id, uint8_t irq, VIA_ISR_t isr);
void VIA_RegisterISR(uint8_t id, uint8_t irq, VIA_ISR_t isr);
// Register data state-change notification interrupts
void VIA_RegisterDataISR(uint8_t port, uint8_t id, uint8_t bit, VIA_ISR_t isr);
@ -90,9 +90,10 @@ bool VIA_ReadBit(uint8_t id, VIA_Register_t reg, uint8_t bit);
// Write a single bit. Can raise data ISR if required.
void VIA_WriteBit(uint8_t id, VIA_Register_t reg, uint8_t bit, bool value, bool runISR);
// NOTE: for these, raise the interrupt manually w/ VIA_RaiseInterrupt
void VIA_ShiftInData(uint8_t id, uint8_t v);
uint8_t VIA_ShiftOutData(uint8_t id);
void VIA_ShiftInData_M68k(uint8_t id, uint8_t v);
uint8_t VIA_ShiftOutData_M68k(uint8_t id);
void VIA_ShiftInData_Ext(uint8_t id, uint8_t v);
uint8_t VIA_ShiftOutData_Ext(uint8_t id);
// Compatiblity stuff, probably
void VIA1_DoTimer1Check();

View File

@ -112,7 +112,7 @@ const DevMethods_t DEVICES[] = {
.timeend = NULL,
},
// SCC
/* {
{
.init = NULL,
.reset = SCC_Reset,
.starttick = NULL,
@ -120,7 +120,7 @@ const DevMethods_t DEVICES[] = {
.subtick = NULL,
.timebegin = NULL,
.timeend = NULL,
},*/
},
// SCSI
{
.init = NULL,
@ -392,6 +392,7 @@ LOCALFUNC bool InitEmulation(void)
// temporarily register some ISRs until I put these in a better place
// Mac Plus only
VIA_RegisterDataISR(VIA1, DataRegA, 4, MemOverlay_ChangeNtfy);
VIA_RegisterISR(VIA1, 2, Kybd_DataLineChngNtfy);
return true;
}
// VBlank interrupt