diff --git a/AppleWin/Applewin.vcproj b/AppleWin/Applewin.vcproj index 8c48bde1..c0cf1ef0 100644 --- a/AppleWin/Applewin.vcproj +++ b/AppleWin/Applewin.vcproj @@ -358,9 +358,6 @@ - - diff --git a/AppleWin/resource/Applewin.rc b/AppleWin/resource/Applewin.rc index fa6c9e9b..6837aec9 100644 --- a/AppleWin/resource/Applewin.rc +++ b/AppleWin/resource/Applewin.rc @@ -46,23 +46,6 @@ END #endif // APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE DISCARDABLE -BEGIN - IDS_TFE_CAPTION "Ethernet Settings" - IDS_TFE_ETHERNET "Ethernet" - IDS_TFE_INTERFACE "Interface" -END - -STRINGTABLE -BEGIN - IDS_OK "OK" - IDS_CANCEL "Cancel" -END ///////////////////////////////////////////////////////////////////////////// // @@ -216,8 +199,8 @@ BEGIN GROUPBOX "Harddisk Controller",IDC_STATIC,2,113,205,71 END -IDD_TFE_SETTINGS_DIALOG DIALOG DISCARDABLE 0, 0, 270, 100 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_TFE_SETTINGS_DIALOG DIALOG 0, 0, 270, 100 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Ethernet Settings" FONT 8, "MS Sans Serif" BEGIN @@ -233,6 +216,7 @@ BEGIN PUSHBUTTON "Cancel",IDCANCEL,80,75,50,14 END + ///////////////////////////////////////////////////////////////////////////// // // Icon @@ -249,8 +233,8 @@ DISK_ICON ICON "DISK.ICO" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,12,9,1 - PRODUCTVERSION 1,12,9,1 + FILEVERSION 1,13,0,0 + PRODUCTVERSION 1,13,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -268,12 +252,12 @@ BEGIN VALUE "Comments", "http://applewin.berlios.de" VALUE "CompanyName", "Michael O'Brien, Oliver Schmidt, Tom Charlesworth" VALUE "FileDescription", "Apple //e Emulator for Windows" - VALUE "FileVersion", "1, 12, 9, 1" + VALUE "FileVersion", "1, 13, 0, 0" VALUE "InternalName", "APPLEWIN" VALUE "LegalCopyright", "© 1994-2006 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski" VALUE "OriginalFilename", "APPLEWIN.EXE" VALUE "ProductName", "Apple //e Emulator" - VALUE "ProductVersion", "1, 12, 9, 1" + VALUE "ProductVersion", "1, 13, 0, 0" END END BLOCK "VarFileInfo" @@ -302,7 +286,6 @@ END IDR_HDDRVR FIRMWARE "Hddrvr.bin" - ///////////////////////////////////////////////////////////////////////////// // // ROM @@ -341,6 +324,25 @@ BEGIN END END + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_TFE_CAPTION "Ethernet Settings" + IDS_TFE_ETHERNET "Ethernet" + IDS_TFE_INTERFACE "Interface" +END + +STRINGTABLE +BEGIN + IDS_OK "OK" + IDS_CANCEL "Cancel" +END + #endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/AppleWin/source/AY8910.cpp b/AppleWin/source/AY8910.cpp index 77b690d7..a6e5b0aa 100644 --- a/AppleWin/source/AY8910.cpp +++ b/AppleWin/source/AY8910.cpp @@ -34,6 +34,11 @@ #include #include "ay8910.h" +#include "Common.h" +#include "Structs.h" +#include "Applewin.h" // For g_fh +#include "Mockingboard.h" // For g_uTimer1IrqCount + /////////////////////////////////////////////////////////// // typedefs & dummy funcs to allow MAME code to compile: @@ -105,7 +110,56 @@ struct AY8910 static struct AY8910 AYPSG[MAX_8910]; /* array of PSG's */ +static bool g_bAYReset = false; // Doing AY8910_reset() +//----------------------------------------------------------------------------- + +//#define LOG_AY8910 +#ifdef LOG_AY8910 +static void LogAY8910(int n, int r, UINT uFreq) +{ + // TO DO: Determine freq from 6522 timer + + if ((g_fh == NULL) || g_bAYReset) + return; + + static UINT nCnt = 0; + const UINT nNumAYs = 4; // 1..4 + if((r == 0)) + { + if(nCnt == 0) + { + fprintf(g_fh, "Time : "); + for(UINT i=0; iRegs[r] = v; -//#define LOG_AY8910 #ifdef LOG_AY8910 - extern FILE* g_fh; // Filehandle for log file - static UINT nCnt = 0; - if((n == 0) && (r == 0) && g_fh) - { - if(nCnt == 0) - fprintf(g_fh, "Time : APer BPer CPer NP EN AV BV CV\n"); - - fprintf(g_fh, "%02d.%02d: ", nCnt/60, nCnt%60); - nCnt++; - - fprintf(g_fh, "%04X ", *(USHORT*)&PSG->Regs[AY_AFINE]); - fprintf(g_fh, "%04X ", *(USHORT*)&PSG->Regs[AY_BFINE]); - fprintf(g_fh, "%04X ", *(USHORT*)&PSG->Regs[AY_CFINE]); - fprintf(g_fh, "%02X ", PSG->Regs[AY_NOISEPER]); - fprintf(g_fh, "%02X ", PSG->Regs[AY_ENABLE]); - fprintf(g_fh, "%02X ", PSG->Regs[AY_AVOL]); - fprintf(g_fh, "%02X ", PSG->Regs[AY_BVOL]); - fprintf(g_fh, "%02X\n", PSG->Regs[AY_CVOL]); - } + LogAY8910(n, r, 60); #endif /* A note about the period of tones, noise and envelope: for speed reasons,*/ @@ -692,6 +727,8 @@ void ay8910_write_ym(int chip, int addr, int data) void AY8910_reset(int chip) { + g_bAYReset = true; + int i; struct AY8910 *PSG = &AYPSG[chip]; @@ -706,6 +743,8 @@ void AY8910_reset(int chip) _AYWriteReg(chip,i,0); /* AYWriteReg() uses the timer system; we cannot */ /* call it at this time because the timer system */ /* has not been initialized. */ + + g_bAYReset = false; } //------------------------------------- diff --git a/AppleWin/source/Applewin.cpp b/AppleWin/source/Applewin.cpp index 7eec8a8e..02f3623d 100644 --- a/AppleWin/source/Applewin.cpp +++ b/AppleWin/source/Applewin.cpp @@ -412,38 +412,50 @@ void LoadConfiguration () { } //=========================================================================== -void RegisterExtensions () { - TCHAR command[MAX_PATH]; - GetModuleFileName((HMODULE)0,command,MAX_PATH); - command[MAX_PATH-1] = 0; - TCHAR icon[MAX_PATH]; - wsprintf(icon,TEXT("%s,1"),(LPCTSTR)command); - _tcscat(command,TEXT(" %1")); - RegSetValue(HKEY_CLASSES_ROOT,".bin",REG_SZ,"DiskImage",10); - RegSetValue(HKEY_CLASSES_ROOT,".do" ,REG_SZ,"DiskImage",10); - RegSetValue(HKEY_CLASSES_ROOT,".dsk",REG_SZ,"DiskImage",10); - RegSetValue(HKEY_CLASSES_ROOT,".nib",REG_SZ,"DiskImage",10); - RegSetValue(HKEY_CLASSES_ROOT,".po" ,REG_SZ,"DiskImage",10); -// RegSetValue(HKEY_CLASSES_ROOT,".aws",REG_SZ,"DiskImage",10); // TO DO -// RegSetValue(HKEY_CLASSES_ROOT,".hdv",REG_SZ,"DiskImage",10); // TO DO - RegSetValue(HKEY_CLASSES_ROOT, - "DiskImage", - REG_SZ,"Disk Image",21); - RegSetValue(HKEY_CLASSES_ROOT, - "DiskImage\\DefaultIcon", - REG_SZ,icon,_tcslen(icon)+1); - RegSetValue(HKEY_CLASSES_ROOT, - "DiskImage\\shell\\open\\command", - REG_SZ,command,_tcslen(command)+1); - RegSetValue(HKEY_CLASSES_ROOT, - "DiskImage\\shell\\open\\ddeexec", - REG_SZ,"%1",3); - RegSetValue(HKEY_CLASSES_ROOT, - "DiskImage\\shell\\open\\ddeexec\\application", - REG_SZ,"applewin",9); - RegSetValue(HKEY_CLASSES_ROOT, - "DiskImage\\shell\\open\\ddeexec\\topic", - REG_SZ,"system",7); +void RegisterExtensions () +{ + TCHAR szCommandTmp[MAX_PATH]; + GetModuleFileName((HMODULE)0,szCommandTmp,MAX_PATH); + + TCHAR command[MAX_PATH]; + wsprintf(command, "\"%s\"", szCommandTmp); // Wrap path & filename in quotes & null terminate + + TCHAR icon[MAX_PATH]; + wsprintf(icon,TEXT("%s,1"),(LPCTSTR)command); + + _tcscat(command,TEXT(" \"%1\"")); // Append "%1" + + RegSetValue(HKEY_CLASSES_ROOT,".bin",REG_SZ,"DiskImage",10); + RegSetValue(HKEY_CLASSES_ROOT,".do" ,REG_SZ,"DiskImage",10); + RegSetValue(HKEY_CLASSES_ROOT,".dsk",REG_SZ,"DiskImage",10); + RegSetValue(HKEY_CLASSES_ROOT,".nib",REG_SZ,"DiskImage",10); + RegSetValue(HKEY_CLASSES_ROOT,".po" ,REG_SZ,"DiskImage",10); +// RegSetValue(HKEY_CLASSES_ROOT,".aws",REG_SZ,"DiskImage",10); // TO DO +// RegSetValue(HKEY_CLASSES_ROOT,".hdv",REG_SZ,"DiskImage",10); // TO DO + + RegSetValue(HKEY_CLASSES_ROOT, + "DiskImage", + REG_SZ,"Disk Image",21); + + RegSetValue(HKEY_CLASSES_ROOT, + "DiskImage\\DefaultIcon", + REG_SZ,icon,_tcslen(icon)+1); + + RegSetValue(HKEY_CLASSES_ROOT, + "DiskImage\\shell\\open\\command", + REG_SZ,command,_tcslen(command)+1); + + RegSetValue(HKEY_CLASSES_ROOT, + "DiskImage\\shell\\open\\ddeexec", + REG_SZ,"%1",3); + + RegSetValue(HKEY_CLASSES_ROOT, + "DiskImage\\shell\\open\\ddeexec\\application", + REG_SZ,"applewin",9); + + RegSetValue(HKEY_CLASSES_ROOT, + "DiskImage\\shell\\open\\ddeexec\\topic", + REG_SZ,"system",7); } //=========================================================================== diff --git a/AppleWin/source/CPU.cpp b/AppleWin/source/CPU.cpp index 9a5f1742..ec49b3d6 100644 --- a/AppleWin/source/CPU.cpp +++ b/AppleWin/source/CPU.cpp @@ -106,6 +106,14 @@ static ULONG g_nCyclesExecuted; static signed long nInternalCyclesLeft; +// + +// Assume all interrupt sources assert until the device is told to stop: +// - eg by r/w to device's register or a machine reset + +static CRITICAL_SECTION g_CriticalSection; // To guard /g_bmIRQ/ +static volatile UINT32 g_bmIRQ = 0; + /**************************************************************************** * * GENERAL PURPOSE MACROS @@ -488,21 +496,6 @@ static DWORD InternalCpuExecute (DWORD totalcycles) nInternalCyclesLeft = (totalcycles<<8) - (cycles<<8); USHORT uExtraCycles = 0; - if(regs.bIRQ && !(regs.ps & AF_INTERRUPT)) - { - g_nCycleIrqStart = g_nCumulativeCycles + cycles; - regs.bIRQ = 0; - PUSH(regs.pc >> 8) - PUSH(regs.pc & 0xFF) - EF_TO_AF - regs.ps |= AF_RESERVED; - PUSH(regs.ps) - regs.ps |= AF_INTERRUPT; - regs.pc = * (WORD*) (mem+0xFFFE); - CYC(7) - continue; - } - switch (*(mem+regs.pc++)) { case 0x00: BRK CYC(7) break; @@ -764,6 +757,20 @@ static DWORD InternalCpuExecute (DWORD totalcycles) case 0xFE: ABSX INC CYC(6) break; case 0xFF: INVALID1 CYC(1) break; } + + if(g_bmIRQ && !(regs.ps & AF_INTERRUPT)) + { + // IRQ signals are deasserted when a specific r/w operation is done on device + g_nCycleIrqStart = g_nCumulativeCycles + cycles; + PUSH(regs.pc >> 8) + PUSH(regs.pc & 0xFF) + EF_TO_AF + regs.ps |= AF_RESERVED; + PUSH(regs.ps) + regs.ps |= AF_INTERRUPT; + regs.pc = * (WORD*) (mem+0xFFFE); + CYC(7) + } } while (cycles < totalcycles); EF_TO_AF @@ -784,6 +791,8 @@ void CpuDestroy () { cpugetcodefunc[loop] = NULL; cpulibrary[loop] = (HINSTANCE)0; } + + DeleteCriticalSection(&g_CriticalSection); } //=========================================================================== @@ -902,9 +911,15 @@ void CpuInitialize () { regs.ps = 0x20; regs.pc = *(LPWORD)(mem+0xFFFC); regs.sp = 0x01FF; - regs.bIRQ = 0; + + InitializeCriticalSection(&g_CriticalSection); + CpuIrqReset(); #ifdef _X86_ + // TO DO: + // . FreeLibrary isn't being called if DLLs' version is too low + // . This code is going to get ditched, so ignore this! + if (mem) { TCHAR filename[MAX_PATH]; _tcscpy(filename,progdir); @@ -998,11 +1013,27 @@ BOOL CpuSupportsFastPaging () { } //=========================================================================== -void CpuIRQ() + +void CpuIrqReset() { - regs.bIRQ = 1; + EnterCriticalSection(&g_CriticalSection); + g_bmIRQ = 0; + LeaveCriticalSection(&g_CriticalSection); } +void CpuIrqAssert(eIRQSRC Device) +{ + EnterCriticalSection(&g_CriticalSection); + g_bmIRQ |= 1<P; regs.sp = (USHORT)pSS->S + 0x100; regs.pc = pSS->PC; - regs.bIRQ = 0; + CpuIrqReset(); g_nCumulativeCycles = pSS->g_nCumulativeCycles; return 0; diff --git a/AppleWin/source/CPU.h b/AppleWin/source/CPU.h index 0183364f..77f3f776 100644 --- a/AppleWin/source/CPU.h +++ b/AppleWin/source/CPU.h @@ -28,6 +28,8 @@ void CpuReinitialize (); void CpuResetCompilerData (); void CpuSetupBenchmark (); BOOL CpuSupportsFastPaging (); -void CpuIRQ (); +void CpuIrqReset(); +void CpuIrqAssert(eIRQSRC Device); +void CpuIrqDeassert(eIRQSRC Device); DWORD CpuGetSnapshot(SS_CPU6502* pSS); DWORD CpuSetSnapshot(SS_CPU6502* pSS); diff --git a/AppleWin/source/Common.h b/AppleWin/source/Common.h index 4f909770..c0b913d2 100644 --- a/AppleWin/source/Common.h +++ b/AppleWin/source/Common.h @@ -1,7 +1,8 @@ #pragma once const double _M14 = 14.31818e6; -const double CLK_6502 = (_M14 / 14.0); +const double CLK_6502 = (_M14 / 14.0); // 1022727 + 1/7 +//const double CLK_6502 = 23 * 44100; // 1014300 const UINT uCyclesPerLine = 65; // 25 cycles of HBL & 40 cycles of HBL' const UINT uVisibleLinesPerFrame = 64*3; // 192 @@ -71,3 +72,4 @@ typedef BYTE (__stdcall *cxfunction)(WORD nPC, WORD nAddr, BYTE nWriteFlag, BYTE typedef struct _IMAGE__ { int unused; } *HIMAGE; +enum eIRQSRC {IS_6522=0, IS_SPEECH, IS_SSC}; diff --git a/AppleWin/source/Memory.cpp b/AppleWin/source/Memory.cpp index 65a893fd..0f1d3c8c 100644 --- a/AppleWin/source/Memory.cpp +++ b/AppleWin/source/Memory.cpp @@ -983,7 +983,7 @@ void MemReset () // INITIALIZE PAGING, FILLING IN THE 64K MEMORY IMAGE ResetPaging(1); regs.pc = *(LPWORD)(mem+0xFFFC); - regs.bIRQ = 0; + CpuIrqReset(); } //=========================================================================== diff --git a/AppleWin/source/Mockingboard.cpp b/AppleWin/source/Mockingboard.cpp index 0f54cd90..819a00fe 100644 --- a/AppleWin/source/Mockingboard.cpp +++ b/AppleWin/source/Mockingboard.cpp @@ -120,9 +120,10 @@ typedef struct // IFR & IER: -#define PERIPHERAL (1<<1) -#define TIMER2 (1<<5) -#define TIMER1 (1<<6) +#define IxR_PERIPHERAL (1<<1) +#define IxR_VOTRAX (1<<4) // TO DO: Get proper name from 6522 datasheet! +#define IxR_TIMER2 (1<<5) +#define IxR_TIMER1 (1<<6) // ACR: #define RUNMODE (1<<6) // 0 = 1-Shot Mode, 1 = Free Running Mode @@ -194,6 +195,7 @@ static const double g_f6522TimerPeriod_NoIRQ = CLK_6502 / 60.0; // Constant wha // External global vars: bool g_bMBTimerIrqActive = false; +UINT32 g_uTimer1IrqCount = 0; // DEBUG //--------------------------------------------------------------------------- @@ -208,7 +210,7 @@ static void StartTimer(SY6522_AY8910* pMB) if((pMB->nAY8910Number & 1) != SY6522_DEVICE_A) return; - if((pMB->sy6522.IER & TIMER1) == 0x00) + if((pMB->sy6522.IER & IxR_TIMER1) == 0x00) return; USHORT nPeriod = pMB->sy6522.TIMER1_LATCH.w; @@ -216,14 +218,6 @@ static void StartTimer(SY6522_AY8910* pMB) if(nPeriod <= 0xff) // Timer1L value has been written (but TIMER1H hasn't) return; -#if 0 - if(nPeriod < 0x3000) // Bit of IRQ protection (probably not needed) - Phasor has ~0x800 cycle period - { - _ASSERT(0); - return; - } -#endif - pMB->nTimerStatus = 1; // 6522 CLK runs at same speed as 6502 CLK @@ -285,7 +279,6 @@ static void AY8910_Write(BYTE nDevice, BYTE nReg, BYTE nValue, BYTE nAYDevice) case AY_WRITE: // 6: WRITE TO PSG _AYWriteReg(nDevice+2*nAYDevice, pMB->nAYCurrentRegister, pMB->sy6522.ORA); -// AY8910_write_ym(nDevice+2*nAYDevice, pMB->nAYCurrentRegister, pMB->sy6522.ORA); break; case AY_LATCH: // 7: LATCH ADDRESS @@ -303,6 +296,17 @@ static void UpdateIFR(SY6522_AY8910* pMB) if(pMB->sy6522.IFR & pMB->sy6522.IER & 0x7F) pMB->sy6522.IFR |= 0x80; + + // Now update the IRQ signal from all 6522s + // . OR-sum of all active TIMER1, TIMER2 & SPEECH sources (from all 6522s) + UINT bIRQ = 0; + for(UINT i=0; isy6522.IFR &= ~TIMER1; + pMB->sy6522.IFR &= ~IxR_TIMER1; UpdateIFR(pMB); pMB->sy6522.TIMER1_LATCH.h = nValue; @@ -371,7 +375,7 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) case 0x07: // TIMER1H_LATCH // Clear Timer1 Interrupt Flag. pMB->sy6522.TIMER1_LATCH.h = nValue; - pMB->sy6522.IFR &= ~TIMER1; + pMB->sy6522.IFR &= ~IxR_TIMER1; UpdateIFR(pMB); break; case 0x08: // TIMER2L @@ -379,7 +383,7 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) break; case 0x09: // TIMER2H // Clear Timer2 Interrupt Flag. - pMB->sy6522.IFR &= ~TIMER2; + pMB->sy6522.IFR &= ~IxR_TIMER2; UpdateIFR(pMB); pMB->sy6522.TIMER2_LATCH.h = nValue; @@ -410,7 +414,7 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) UpdateIFR(pMB); // Check if timer has been disabled. - if(pMB->sy6522.IER & TIMER1) + if(pMB->sy6522.IER & IxR_TIMER1) break; if(pMB->nTimerStatus == 0) @@ -461,7 +465,7 @@ static BYTE SY6522_Read(BYTE nDevice, BYTE nReg) break; case 0x04: // TIMER1L_COUNTER nValue = pMB->sy6522.TIMER1_COUNTER.l; - pMB->sy6522.IFR &= ~TIMER1; // Also clears Timer1 Interrupt Flag + pMB->sy6522.IFR &= ~IxR_TIMER1; // Also clears Timer1 Interrupt Flag UpdateIFR(pMB); break; case 0x05: // TIMER1H_COUNTER @@ -475,7 +479,7 @@ static BYTE SY6522_Read(BYTE nDevice, BYTE nReg) break; case 0x08: // TIMER2L nValue = pMB->sy6522.TIMER2_COUNTER.l; - pMB->sy6522.IFR &= ~TIMER2; // Also clears Timer2 Interrupt Flag + pMB->sy6522.IFR &= ~IxR_TIMER2; // Also clears Timer2 Interrupt Flag UpdateIFR(pMB); break; case 0x09: // TIMER2H @@ -543,32 +547,12 @@ const BYTE AMPLITUDE_MASK = 0x0F; static BYTE SSI263_Read(BYTE nDevice, BYTE nReg) { - BYTE nValue; - SY6522_AY8910* pMB = &g_MB[nDevice]; - switch(nReg) - { - case SSI_DURPHON: - nValue = pMB->SpeechChip.DurationPhonome; - break; - case SSI_INFLECT: - nValue = pMB->SpeechChip.Inflection; - break; - case SSI_RATEINF: - nValue = pMB->SpeechChip.RateInflection; - break; - case SSI_CTTRAMP: - nValue = pMB->SpeechChip.CtrlArtAmp; - break; - case SSI_FILFREQ: - nValue = pMB->SpeechChip.FilterFreq; - break; - default: - break; - } + // Regardless of register, just return inverted A/!R in bit7 + // . A/!R is low for IRQ - return nValue; + return pMB->SpeechChip.CurrentMode << 7; } static void SSI263_Write(BYTE nDevice, BYTE nReg, BYTE nValue) @@ -581,6 +565,14 @@ static void SSI263_Write(BYTE nDevice, BYTE nReg, BYTE nValue) #if LOG_SSI263 if(g_fh) fprintf(g_fh, "DUR = 0x%02X, PHON = 0x%02X\n\n", nValue>>6, nValue&PHONEME_MASK); #endif + + // Datasheet is not clear, but a write to DURPHON must clear the IRQ + if(g_bPhasorEnable) + CpuIrqDeassert(IS_SPEECH); + pMB->sy6522.IFR &= ~IxR_PERIPHERAL; + UpdateIFR(pMB); + pMB->SpeechChip.CurrentMode &= ~1; // Clear SSI263's D7 pin + pMB->SpeechChip.DurationPhonome = nValue; // Phoneme output not dependent on CONTROL bit @@ -703,6 +695,11 @@ static void Votrax_Write(BYTE nDevice, BYTE nValue) { g_bVotraxPhoneme = true; + // !A/R: Acknowledge receipt of phoneme data (signal goes from high to low) + SY6522_AY8910* pMB = &g_MB[nDevice]; + pMB->sy6522.IFR &= ~IxR_VOTRAX; + UpdateIFR(pMB); + SSI263_Play(Votrax2SSI263[nValue & PHONEME_MASK]); } @@ -895,18 +892,19 @@ static DWORD WINAPI SSI263Thread(LPVOID lpParameter) { if((pMB->SpeechChip.CurrentMode != MODE_IRQ_DISABLED)) { - CpuIRQ(); + pMB->SpeechChip.CurrentMode |= 1; // Set SSI263's D7 pin + + // Is Phasor's SSI263.IRQ wired directly to IRQ? (Bypassing the 6522) + CpuIrqAssert(IS_SPEECH); } } else { if((pMB->SpeechChip.CurrentMode != MODE_IRQ_DISABLED) && (pMB->sy6522.PCR == 0x0C)) { - pMB->sy6522.IFR |= PERIPHERAL; + pMB->sy6522.IFR |= IxR_PERIPHERAL; UpdateIFR(pMB); - - if(pMB->sy6522.IER & PERIPHERAL) - CpuIRQ(); + pMB->SpeechChip.CurrentMode |= 1; // Set SSI263's D7 pin } } @@ -914,11 +912,10 @@ static DWORD WINAPI SSI263Thread(LPVOID lpParameter) if(g_bVotraxPhoneme && (pMB->sy6522.PCR == 0xB0)) { - pMB->sy6522.IFR |= 0x10; - UpdateIFR(pMB); + // !A/R: Time-out of old phoneme (signal goes from low to high) - if(pMB->sy6522.IER & 0x10) - CpuIRQ(); + pMB->sy6522.IFR |= IxR_VOTRAX; + UpdateIFR(pMB); g_bVotraxPhoneme = false; } @@ -939,6 +936,10 @@ static void SSI263_Play(unsigned int nPhoneme) g_nCurrentActivePhoneme = nPhoneme; + hr = SSI263Voice[g_nCurrentActivePhoneme].lpDSBvoice->SetCurrentPosition(0); + if(FAILED(hr)) + return; + hr = SSI263Voice[g_nCurrentActivePhoneme].lpDSBvoice->Play(0,0,0); // Not looping if(FAILED(hr)) return; @@ -1449,7 +1450,7 @@ void MB_EndOfFrame() if(g_SoundcardType == SC_NONE) return; - if(!g_bFullSpeed && !g_bMBTimerIrqActive && !(g_MB[0].sy6522.IFR & TIMER1)) + if(!g_bFullSpeed && !g_bMBTimerIrqActive && !(g_MB[0].sy6522.IFR & IxR_TIMER1)) MB_Update(); } @@ -1478,9 +1479,11 @@ void MB_UpdateCycles(USHORT nClocks) if( bTimer1Underflow && (g_nMBTimerDevice == i) && g_bMBTimerIrqActive ) { - pMB->sy6522.IFR |= TIMER1; + g_uTimer1IrqCount++; // DEBUG + + pMB->sy6522.IFR |= IxR_TIMER1; UpdateIFR(pMB); - CpuIRQ(); + if((pMB->sy6522.ACR & RUNMODE) == RM_ONESHOT) { // One-shot mode @@ -1524,7 +1527,7 @@ void MB_SetSoundcardType(eSOUNDCARDTYPE NewSoundcardType) double MB_GetFramePeriod() { - return (g_bMBTimerIrqActive||(g_MB[0].sy6522.IFR & TIMER1)) ? (double)g_n6522TimerPeriod : g_f6522TimerPeriod_NoIRQ; + return (g_bMBTimerIrqActive||(g_MB[0].sy6522.IFR & IxR_TIMER1)) ? (double)g_n6522TimerPeriod : g_f6522TimerPeriod_NoIRQ; } bool MB_IsActive() @@ -1606,15 +1609,18 @@ DWORD MB_SetSnapshot(SS_CARD_MOCKINGBOARD* pSS, DWORD /*dwSlot*/) // // Crude - currently only support a single speech chip + // FIX THIS: + // . Speech chip could be Votrax instead + // . Is this IRQ compatible with Phasor? if(pMB->SpeechChip.DurationPhonome) { g_nSSI263Device = nDeviceNum; - if((pMB->SpeechChip.CurrentMode != MODE_IRQ_DISABLED) && (pMB->sy6522.PCR == 0x0C) && (pMB->sy6522.IER & PERIPHERAL)) + if((pMB->SpeechChip.CurrentMode != MODE_IRQ_DISABLED) && (pMB->sy6522.PCR == 0x0C) && (pMB->sy6522.IER & IxR_PERIPHERAL)) { - pMB->sy6522.IFR |= PERIPHERAL; + pMB->sy6522.IFR |= IxR_PERIPHERAL; UpdateIFR(pMB); - CpuIRQ(); + pMB->SpeechChip.CurrentMode |= 1; // Set SSI263's D7 pin } } diff --git a/AppleWin/source/Mockingboard.h b/AppleWin/source/Mockingboard.h index 90ee5802..d35c5612 100644 --- a/AppleWin/source/Mockingboard.h +++ b/AppleWin/source/Mockingboard.h @@ -1,6 +1,7 @@ #pragma once extern bool g_bMBTimerIrqActive; +extern UINT32 g_uTimer1IrqCount; // DEBUG void MB_Initialize(); void MB_Reinitialize(); diff --git a/AppleWin/source/Structs.h b/AppleWin/source/Structs.h index ed042fa6..9be73d1d 100644 --- a/AppleWin/source/Structs.h +++ b/AppleWin/source/Structs.h @@ -1,4 +1,6 @@ -// +// Structs used by save-state file + +// *** DON'T CHANGE ANY STRUCT WITHOUT CONSIDERING BACKWARDS COMPATIBILITY WITH .AWS FORMAT *** #define MAKE_VERSION(a,b,c,d) ((a<<24) | (b<<16) | (c<<8) | (d)) @@ -34,6 +36,8 @@ typedef struct // IRQ = OR-sum of all interrupt sources } SS_CPU6502; +const UINT uRecvBufferSize = 9; + typedef struct { DWORD baudrate; @@ -42,7 +46,7 @@ typedef struct DWORD comminactivity; // If non-zero then COM port open BYTE controlbyte; BYTE parity; - BYTE recvbuffer[9]; + BYTE recvbuffer[uRecvBufferSize]; DWORD recvbytes; BYTE stopbits; } SS_IO_Comms; @@ -232,7 +236,7 @@ typedef struct BYTE CtrlArtAmp; BYTE FilterFreq; // - BYTE CurrentMode; + BYTE CurrentMode; // b7:6=Mode; b0=D7 pin (for IRQ) } SSI263A; typedef struct