Submitted changed files from AppleWin-Tom branch to trunk

. Change: Added support for SSC receive IRQ (eg. Z-Link)
. Fix: [Bug #7231] AppleWin installed in path with spaces

Internal:
. Modified operation of interrupt assert/deassert
This commit is contained in:
tomch 2006-05-02 21:56:28 +00:00
parent 8a453a479e
commit 0b8d9e723c
11 changed files with 258 additions and 162 deletions

View File

@ -358,9 +358,6 @@
<Filter
Name="Docs"
Filter="">
<File
RelativePath=".\docs\Bugs.txt">
</File>
<File
RelativePath=".\docs\CodingConventions.txt">
</File>

View File

@ -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
/////////////////////////////////////////////////////////////////////////////

View File

@ -34,6 +34,11 @@
#include <crtdbg.h>
#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; i<nNumAYs; i++)
fprintf(g_fh, "APer BPer CPer NP EN AV BV CV ");
fprintf(g_fh, "\n");
}
fprintf(g_fh, "%02d.%02d: ", g_uTimer1IrqCount/uFreq, g_uTimer1IrqCount%uFreq);
for(int j=0; j<n*(3*5+5*3+1); j++)
fprintf(g_fh, " ");
UINT i=n;
{
UCHAR* pAYRegs = &AYPSG[i].Regs[0];
fprintf(g_fh, "%04X ", *(USHORT*)&pAYRegs[AY_AFINE]);
fprintf(g_fh, "%04X ", *(USHORT*)&pAYRegs[AY_BFINE]);
fprintf(g_fh, "%04X ", *(USHORT*)&pAYRegs[AY_CFINE]);
fprintf(g_fh, "%02X ", pAYRegs[AY_NOISEPER]);
fprintf(g_fh, "%02X ", pAYRegs[AY_ENABLE]);
fprintf(g_fh, "%02X ", pAYRegs[AY_AVOL]);
fprintf(g_fh, "%02X ", pAYRegs[AY_BVOL]);
fprintf(g_fh, "%02X ", pAYRegs[AY_CVOL]);
}
fprintf(g_fh, "\n");
nCnt++;
}
}
#endif
//-----------------------------------------------------------------------------
void _AYWriteReg(int n, int r, int v)
{
@ -115,27 +169,8 @@ void _AYWriteReg(int n, int r, int v)
PSG->Regs[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;
}
//-------------------------------------

View File

@ -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);
}
//===========================================================================

View File

@ -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<<Device;
LeaveCriticalSection(&g_CriticalSection);
}
void CpuIrqDeassert(eIRQSRC Device)
{
EnterCriticalSection(&g_CriticalSection);
g_bmIRQ &= ~(1<<Device);
LeaveCriticalSection(&g_CriticalSection);
}
//===========================================================================
DWORD CpuGetSnapshot(SS_CPU6502* pSS)
@ -1026,7 +1057,7 @@ DWORD CpuSetSnapshot(SS_CPU6502* pSS)
regs.ps = pSS->P;
regs.sp = (USHORT)pSS->S + 0x100;
regs.pc = pSS->PC;
regs.bIRQ = 0;
CpuIrqReset();
g_nCumulativeCycles = pSS->g_nCumulativeCycles;
return 0;

View File

@ -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);

View File

@ -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};

View File

@ -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();
}
//===========================================================================

View File

@ -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; i<NUM_SY6522; i++)
bIRQ |= g_MB[i].sy6522.IFR & 0x80;
if (bIRQ)
CpuIrqAssert(IS_6522);
else
CpuIrqDeassert(IS_6522);
}
static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue)
@ -360,7 +364,7 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue)
/* Initiates timer1 & clears time-out of timer1 */
// Clear Timer Interrupt Flag.
pMB->sy6522.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
}
}

View File

@ -1,6 +1,7 @@
#pragma once
extern bool g_bMBTimerIrqActive;
extern UINT32 g_uTimer1IrqCount; // DEBUG
void MB_Initialize();
void MB_Reinitialize();

View File

@ -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