mirror of
https://github.com/AppleWin/AppleWin.git
synced 2025-01-11 05:29:55 +00:00
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:
parent
622a60c20f
commit
8a433b6e0d
@ -358,9 +358,6 @@
|
||||
<Filter
|
||||
Name="Docs"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\docs\Bugs.txt">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\docs\CodingConventions.txt">
|
||||
</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
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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};
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
extern bool g_bMBTimerIrqActive;
|
||||
extern UINT32 g_uTimer1IrqCount; // DEBUG
|
||||
|
||||
void MB_Initialize();
|
||||
void MB_Reinitialize();
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user