AppleWin/source/Peripheral_Clock_ThunderClockPlus.cpp
2014-05-23 22:59:02 +01:00

241 lines
6.1 KiB
C++

/*
AppleWin : An Apple //e emulator for Windows
Copyright (C) 2008, Michael Pohoreski
AppleWin is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
AppleWin is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with AppleWin; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Description: Thunderware ThunderClock+
*
* Author: Michael Pohoreski
*/
#include "StdAfx.h"
#pragma hdrstop
#include "..\resource\resource.h"
// #include "resource.h" // BUG -- wrong resource!!!
#include <time.h>
void LoadRom_Clock_ThunderClockPlus(LPBYTE pCxRomPeripheral, UINT uSlot);
/*
static BYTE __stdcall Clock_Generic_Read_C0(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULONG nCyclesLeft);
static BYTE __stdcall Clock_Generic_Write_C0(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULONG nCyclesLeft);
static BYTE __stdcall Clock_Generic_Read_CX(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULONG nCyclesLeft);
static BYTE __stdcall Clock_Generic_Write_CX(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULONG nCyclesLeft);
UINT g_uClockInSlot4 = CT_GenericClock;
BYTE *g_pGenericClockFirmware = NULL;
enum ClockCommandEnum
{
CC_READ = 0x18
};
enum ClockLatchEnum
{
CL_SEC_0X,
CL_SEC_X0,
CL_MINS_0X,
CL_MINS_X0,
CL_HOURS_0X,
CL_HOURS_X0,
CL_DAY_0X,
CL_DAY_X0,
CL_DOW_0X,
CL_DOW_X0,
CL_MONTH
};
int iClockCommand = 0;
int iClockLatch = 0;
int iClockStrobe = 0;
int iClockBit = 0;
BYTE iClockOutByte = 0;
static BYTE __stdcall Clock_Generic_Read_C0(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULONG nCyclesLeft)
{
BYTE nOutput = 0;
{
// BCD
static int y = 0x2013;
static int d = 4; // min
static int n = 5;
static int w = 6;
static int h = 7;
static int m = 8;
static int s = 9;
// int nDOW = pLocalTime->tm_wday + 1;
switch( iClockLatch )
{
case CL_MONTH:
// nOutput = (pLocalTime->tm_mon << (7 + iClockBit)) & 0x80;
nOutput = ((n >> 0) & 0xF) << (7 + iClockBit);
break;
case CL_DOW_X0:
nOutput = ((w >> 4) & 0xF) << (7 + iClockBit);
break;
case CL_DOW_0X:
nOutput = ((w >> 0) & 0xF) << (7 + iClockBit);
break;
case CL_DAY_X0:
nOutput = ((d >> 4) & 0xF) << (7 + iClockBit);
break;
case CL_DAY_0X:
nOutput = ((d >> 0) & 0xF) << (7 + iClockBit);
break;
case CL_HOURS_X0:
nOutput = ((h >> 4) & 0xF) << (7 + iClockBit);
break;
case CL_HOURS_0X:
nOutput = ((h >> 0) & 0xF) << (7 + iClockBit);
break;
case CL_MINS_X0:
nOutput = ((m >> 4) & 0xF) << (7 + iClockBit);
break;
case CL_MINS_0X:
nOutput = ((m >> 0) & 0xF) << (7 + iClockBit);
break;
case CL_SEC_X0:
nOutput = ((s >> 4) & 0xF) << (7 + iClockBit);
break;
case CL_SEC_0X:
nOutput = ((s >> 0) & 0xF) << (7 + iClockBit);
break;
default:
break;
}
// nOutput = 0xFF;
}
char sText[ 128 ];
sprintf( sText, " Read [%d] (%d) = %02X\n", iClockLatch, iClockBit, nOutput );
OutputDebugString( sText );
return nOutput;
}
static BYTE __stdcall Clock_Generic_Write_C0(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULONG nCyclesLeft)
{
int iSlot = (nAddr >> 12) - 0x8;
if( iSlot > 0 )
{
if( nValue & 0x02)
{
iClockBit++;
if( iClockBit >= 4 )
{
iClockBit = 0;
iClockLatch++;
}
}
switch( nAddr & 0x0F )
{
case 0x00: // set time format
if( nValue == CC_READ )
{
iClockCommand = nValue;
iClockLatch = 0;
iClockBit = 0;
}
// 0x18 = Time Read
// get 10 nibbles
// 0x1C =
// 0x18
// 0x04
// 0x0C
break;
default:
break;
}
char sText[ 128 ];
sprintf( sText, " Write: $%04X: %02X Clock: %s Strobe: %s\n"
, nAddr, nValue
, (nValue & 0x02)
? "Raise "
: "Drop "
, (nValue & 0x04)
? "On "
: "off"
);
OutputDebugString( sText );
}
return 0;
}
static BYTE __stdcall Clock_Generic_Read_CX(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULONG nCyclesLeft)
{
return 0;
// Chain to default...
}
static BYTE __stdcall Clock_Generic_Write_CX(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULONG nCyclesLeft)
{
return 0;
// Chain to default...
}
void LoadRom_Clock_ThunderClockPlus(LPBYTE pCxRomPeripheral, UINT uSlot)
{
HRSRC hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_THUNDERCLOCKPLUS_FW), "FIRMWARE");
if(hResInfo == NULL)
return;
DWORD dwResSize = SizeofResource(NULL, hResInfo);
if(dwResSize != FIRMWARE_EXPANSION_SIZE)
return;
HGLOBAL hResData = LoadResource(NULL, hResInfo);
if(hResData == NULL)
return;
BYTE* pData = (BYTE*) LockResource(hResData); // NB. Don't need to unlock resource
if(pData == NULL)
return;
// Slot ROM is a mirror of the 1st page of the firmware
memcpy(pCxRomPeripheral + uSlot*256, pData, APPLE_SLOT_SIZE);
#if _DEBUG
if (pCxRomPeripheral[ uSlot*256 + 0 ] != 0x08)
MessageBox( NULL, "Bad ThunderClock ROM: 1st byte", NULL, MB_OK );
if (pCxRomPeripheral[ uSlot*256 + 2 ] != 0x28)
MessageBox( NULL, "Bad ThunderClock ROM: 2nd byte", NULL, MB_OK );
#endif
if( !g_pGenericClockFirmware )
{
g_pGenericClockFirmware = new BYTE [FIRMWARE_EXPANSION_SIZE];
if (g_pGenericClockFirmware)
memcpy(g_pGenericClockFirmware, pData, FIRMWARE_EXPANSION_SIZE);
}
// RegisterIoHandler( uSlot, &Clock_Generic_Read_C0, &Clock_Generic_Write_C0, Clock_Generic_Read_CX, Clock_Generic_Write_CX, NULL, g_pGenericClockFirmware );
RegisterIoHandler( uSlot, &Clock_Generic_Read_C0, &Clock_Generic_Write_C0, NULL, NULL, NULL, g_pGenericClockFirmware );
}
*/