2006-02-25 20:50:29 +00:00
/*
AppleWin : An Apple //e emulator for Windows
Copyright ( C ) 1994 - 1996 , Michael O ' Brien
Copyright ( C ) 1999 - 2001 , Oliver Schmidt
Copyright ( C ) 2002 - 2005 , Tom Charlesworth
2007-04-01 15:24:52 +00:00
Copyright ( C ) 2006 - 2007 , Tom Charlesworth , Michael Pohoreski
2006-02-25 20:50:29 +00:00
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: Memory emulation
*
* Author : Various
*/
# include "StdAfx.h"
# pragma hdrstop
2007-08-06 21:38:35 +00:00
# include "MouseInterface.h"
2008-08-19 21:36:31 +00:00
# ifdef SUPPORT_CPM
# include "z80\z80emu.h"
2008-08-31 15:37:53 +00:00
# include "z80\z80.h"
2008-08-19 21:36:31 +00:00
# endif
2006-03-13 23:46:57 +00:00
# include "..\resource\resource.h"
2006-02-25 20:50:29 +00:00
# define MF_80STORE 0x00000001
# define MF_ALTZP 0x00000002
# define MF_AUXREAD 0x00000004
# define MF_AUXWRITE 0x00000008
# define MF_BANK2 0x00000010
# define MF_HIGHRAM 0x00000020
# define MF_HIRES 0x00000040
# define MF_PAGE2 0x00000080
# define MF_SLOTC3ROM 0x00000100
# define MF_SLOTCXROM 0x00000200
# define MF_WRITERAM 0x00000400
# define MF_IMAGEMASK 0x000003F7
# define SW_80STORE (memmode & MF_80STORE)
# define SW_ALTZP (memmode & MF_ALTZP)
# define SW_AUXREAD (memmode & MF_AUXREAD)
# define SW_AUXWRITE (memmode & MF_AUXWRITE)
# define SW_BANK2 (memmode & MF_BANK2)
# define SW_HIGHRAM (memmode & MF_HIGHRAM)
# define SW_HIRES (memmode & MF_HIRES)
# define SW_PAGE2 (memmode & MF_PAGE2)
# define SW_SLOTC3ROM (memmode & MF_SLOTC3ROM)
# define SW_SLOTCXROM (memmode & MF_SLOTCXROM)
# define SW_WRITERAM (memmode & MF_WRITERAM)
2007-05-28 11:16:42 +00:00
//-----------------------------------------------------------------------------
//static DWORD imagemode;
static LPBYTE memshadow [ 0x100 ] ;
LPBYTE memwrite [ 0x100 ] ;
iofunction IORead [ 256 ] ;
iofunction IOWrite [ 256 ] ;
static LPVOID SlotParameters [ NUM_SLOTS ] ;
//static BOOL fastpaging = 0; // Redundant: only ever set to 0, by MemSetFastPaging(0)
//static DWORD image = 0;
//static DWORD lastimage = 0;
2006-02-25 20:50:29 +00:00
static BOOL lastwriteram = 0 ;
2007-05-28 11:16:42 +00:00
2006-02-25 20:50:29 +00:00
LPBYTE mem = NULL ;
2007-05-28 11:16:42 +00:00
//
2006-02-25 20:50:29 +00:00
static LPBYTE memaux = NULL ;
2007-05-28 11:16:42 +00:00
static LPBYTE memmain = NULL ;
2006-02-25 20:50:29 +00:00
LPBYTE memdirty = NULL ;
2007-05-28 11:16:42 +00:00
static LPBYTE memrom = NULL ;
2006-02-25 20:50:29 +00:00
static LPBYTE memimage = NULL ;
2007-05-28 11:16:42 +00:00
static LPBYTE pCxRomInternal = NULL ;
static LPBYTE pCxRomPeripheral = NULL ;
2006-02-25 20:50:29 +00:00
static DWORD memmode = MF_BANK2 | MF_SLOTCXROM | MF_WRITERAM ;
static BOOL modechanging = 0 ;
2008-06-20 23:47:25 +00:00
static BOOL Pravets8charmode = 0 ;
2006-03-09 21:10:40 +00:00
MemoryInitPattern_e g_eMemoryInitPattern = MIP_FF_FF_00_00 ;
2006-02-25 20:50:29 +00:00
# ifdef RAMWORKS
UINT g_uMaxExPages = 1 ; // user requested ram pages
static LPBYTE RWpages [ 128 ] ; // pointers to RW memory banks
# endif
2007-05-28 11:16:42 +00:00
BYTE __stdcall IO_Annunciator ( WORD programcounter , WORD address , BYTE write , BYTE value , ULONG nCycles ) ;
void UpdatePaging ( BOOL initialize , BOOL updatewriteonly ) ;
2006-02-25 20:50:29 +00:00
2007-05-28 11:16:42 +00:00
//=============================================================================
static BYTE __stdcall IORead_C00x ( WORD pc , WORD addr , BYTE bWrite , BYTE d , ULONG nCyclesLeft )
{
return KeybReadData ( pc , addr , bWrite , d , nCyclesLeft ) ;
2006-02-25 20:50:29 +00:00
}
2007-05-28 11:16:42 +00:00
static BYTE __stdcall IOWrite_C00x ( WORD pc , WORD addr , BYTE bWrite , BYTE d , ULONG nCyclesLeft )
{
if ( ( addr & 0xf ) < = 0xB )
return MemSetPaging ( pc , addr , bWrite , d , nCyclesLeft ) ;
else
return VideoSetMode ( pc , addr , bWrite , d , nCyclesLeft ) ;
}
//-------------------------------------
static BYTE __stdcall IORead_C01x ( WORD pc , WORD addr , BYTE bWrite , BYTE d , ULONG nCyclesLeft )
{
switch ( addr & 0xf )
2006-03-12 09:05:39 +00:00
{
2007-05-28 11:16:42 +00:00
case 0x0 : return KeybReadFlag ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x1 : return MemCheckPaging ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x2 : return MemCheckPaging ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x3 : return MemCheckPaging ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x4 : return MemCheckPaging ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x5 : return MemCheckPaging ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x6 : return MemCheckPaging ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x7 : return MemCheckPaging ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x8 : return MemCheckPaging ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x9 : return VideoCheckVbl ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xA : return VideoCheckMode ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xB : return VideoCheckMode ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xC : return MemCheckPaging ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xD : return MemCheckPaging ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xE : return VideoCheckMode ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xF : return VideoCheckMode ( pc , addr , bWrite , d , nCyclesLeft ) ;
2006-03-12 09:05:39 +00:00
}
2007-05-28 11:16:42 +00:00
return 0 ;
}
static BYTE __stdcall IOWrite_C01x ( WORD pc , WORD addr , BYTE bWrite , BYTE d , ULONG nCyclesLeft )
{
return KeybReadFlag ( pc , addr , bWrite , d , nCyclesLeft ) ;
}
//-------------------------------------
static BYTE __stdcall IORead_C02x ( WORD pc , WORD addr , BYTE bWrite , BYTE d , ULONG nCyclesLeft )
{
return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
}
static BYTE __stdcall IOWrite_C02x ( WORD pc , WORD addr , BYTE bWrite , BYTE d , ULONG nCyclesLeft )
{
return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
}
//-------------------------------------
static BYTE __stdcall IORead_C03x ( WORD pc , WORD addr , BYTE bWrite , BYTE d , ULONG nCyclesLeft )
{
return SpkrToggle ( pc , addr , bWrite , d , nCyclesLeft ) ;
}
static BYTE __stdcall IOWrite_C03x ( WORD pc , WORD addr , BYTE bWrite , BYTE d , ULONG nCyclesLeft )
{
return SpkrToggle ( pc , addr , bWrite , d , nCyclesLeft ) ;
}
//-------------------------------------
static BYTE __stdcall IORead_C04x ( WORD pc , WORD addr , BYTE bWrite , BYTE d , ULONG nCyclesLeft )
{
return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
}
static BYTE __stdcall IOWrite_C04x ( WORD pc , WORD addr , BYTE bWrite , BYTE d , ULONG nCyclesLeft )
{
return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
}
//-------------------------------------
static BYTE __stdcall IORead_C05x ( WORD pc , WORD addr , BYTE bWrite , BYTE d , ULONG nCyclesLeft )
{
switch ( addr & 0xf )
{
case 0x0 : return VideoSetMode ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x1 : return VideoSetMode ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x2 : return VideoSetMode ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x3 : return VideoSetMode ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x4 : return MemSetPaging ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x5 : return MemSetPaging ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x6 : return MemSetPaging ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x7 : return MemSetPaging ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x8 : return IO_Annunciator ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x9 : return IO_Annunciator ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xA : return IO_Annunciator ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xB : return IO_Annunciator ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xC : return IO_Annunciator ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xD : return IO_Annunciator ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xE : return VideoSetMode ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xF : return VideoSetMode ( pc , addr , bWrite , d , nCyclesLeft ) ;
}
return 0 ;
}
static BYTE __stdcall IOWrite_C05x ( WORD pc , WORD addr , BYTE bWrite , BYTE d , ULONG nCyclesLeft )
{
switch ( addr & 0xf )
{
case 0x0 : return VideoSetMode ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x1 : return VideoSetMode ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x2 : return VideoSetMode ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x3 : return VideoSetMode ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x4 : return MemSetPaging ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x5 : return MemSetPaging ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x6 : return MemSetPaging ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x7 : return MemSetPaging ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x8 : return IO_Annunciator ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x9 : return IO_Annunciator ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xA : return IO_Annunciator ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xB : return IO_Annunciator ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xC : return IO_Annunciator ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xD : return IO_Annunciator ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xE : return VideoSetMode ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xF : return VideoSetMode ( pc , addr , bWrite , d , nCyclesLeft ) ;
}
return 0 ;
}
//-------------------------------------
static BYTE __stdcall IORead_C06x ( WORD pc , WORD addr , BYTE bWrite , BYTE d , ULONG nCyclesLeft )
2008-06-20 23:47:25 +00:00
{
static byte CurrentKestroke = 0 ;
CurrentKestroke = KeybGetKeycode ( ) ;
2007-05-28 11:16:42 +00:00
switch ( addr & 0xf )
2006-03-12 09:05:39 +00:00
{
2008-06-20 23:47:25 +00:00
//In Pravets8A/C if SETMODE (8bit character encoding) is enabled, bit6 in $C060 is 0; Else it is 1
//If (CAPS lOCK of Pravets8A/C is on or Shift is pressed) and (MODE is enabled), bit7 in $C000 is 1; Else it is 0
//Writing into $C060 sets MODE on and off. If bit 0 is 0 the the MODE is set 0, if bit 0 is 1 then MODE is set to 1 (8-bit)
case 0x0 : return TapeRead ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x1 : return JoyReadButton ( pc , addr , bWrite , d , nCyclesLeft ) ; //$C061 Digital input 0 (If bit 7=1 then JoyButton 0 or OpenApple is pressed)
case 0x2 : return JoyReadButton ( pc , addr , bWrite , d , nCyclesLeft ) ; //$C062 Digital input 1 (If bit 7=1 then JoyButton 1 or ClosedApple is pressed)
case 0x3 : return JoyReadButton ( pc , addr , bWrite , d , nCyclesLeft ) ; //$C063 Digital input 2
case 0x4 : return JoyReadPosition ( pc , addr , bWrite , d , nCyclesLeft ) ; //$C064 Analog input 0
case 0x5 : return JoyReadPosition ( pc , addr , bWrite , d , nCyclesLeft ) ; //$C065 Analog input 1
case 0x6 : return JoyReadPosition ( pc , addr , bWrite , d , nCyclesLeft ) ; //$C066 Analog input 2
case 0x7 : return JoyReadPosition ( pc , addr , bWrite , d , nCyclesLeft ) ; //$C067 Analog input 3
2007-05-28 11:16:42 +00:00
case 0x8 : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x9 : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xA : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xB : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xC : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xD : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xE : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xF : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
}
return 0 ;
}
static BYTE __stdcall IOWrite_C06x ( WORD pc , WORD addr , BYTE bWrite , BYTE d , ULONG nCyclesLeft )
{
2008-06-20 23:47:25 +00:00
switch ( addr & 0xf )
{
case 0x0 :
if ( g_Apple2Type = = A2TYPE_PRAVETS8A )
return TapeWrite ( pc , addr , bWrite , d , nCyclesLeft ) ;
else
return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ; //Apple2 value
}
return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ; //Apple2 value
2007-05-28 11:16:42 +00:00
}
//-------------------------------------
static BYTE __stdcall IORead_C07x ( WORD pc , WORD addr , BYTE bWrite , BYTE d , ULONG nCyclesLeft )
{
switch ( addr & 0xf )
{
2008-06-20 23:47:25 +00:00
case 0x0 : return JoyResetPosition ( pc , addr , bWrite , d , nCyclesLeft ) ; //$C070 Analog input reset
2007-05-28 11:16:42 +00:00
case 0x1 : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x2 : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x3 : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x4 : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x5 : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x6 : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x7 : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x8 : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x9 : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xA : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xB : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xC : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xD : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xE : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xF : return VideoCheckMode ( pc , addr , bWrite , d , nCyclesLeft ) ;
}
return 0 ;
}
static BYTE __stdcall IOWrite_C07x ( WORD pc , WORD addr , BYTE bWrite , BYTE d , ULONG nCyclesLeft )
{
switch ( addr & 0xf )
{
case 0x0 : return JoyResetPosition ( pc , addr , bWrite , d , nCyclesLeft ) ;
# ifdef RAMWORKS
case 0x1 : return MemSetPaging ( pc , addr , bWrite , d , nCyclesLeft ) ; // extended memory card set page
case 0x2 : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x3 : return MemSetPaging ( pc , addr , bWrite , d , nCyclesLeft ) ; // Ramworks III set page
# else
case 0x1 : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x2 : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x3 : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
# endif
case 0x4 : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x5 : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x6 : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x7 : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x8 : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0x9 : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xA : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xB : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xC : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xD : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xE : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
case 0xF : return IO_Null ( pc , addr , bWrite , d , nCyclesLeft ) ;
}
return 0 ;
}
//-----------------------------------------------------------------------------
static iofunction IORead_C0xx [ 8 ] =
{
IORead_C00x , // Keyboard
IORead_C01x , // Memory/Video
IORead_C02x , // Cassette
IORead_C03x , // Speaker
IORead_C04x ,
IORead_C05x , // Video
IORead_C06x , // Joystick
IORead_C07x , // Joystick/Video
} ;
static iofunction IOWrite_C0xx [ 8 ] =
{
IOWrite_C00x , // Memory/Video
IOWrite_C01x , // Keyboard
IOWrite_C02x , // Cassette
IOWrite_C03x , // Speaker
IOWrite_C04x ,
IOWrite_C05x , // Video/Memory
IOWrite_C06x ,
IOWrite_C07x , // Joystick/Ramworks
} ;
static BYTE IO_SELECT ;
static BYTE IO_SELECT_InternalROM ;
static BYTE * ExpansionRom [ NUM_SLOTS ] ;
enum eExpansionRomType { eExpRomNull = 0 , eExpRomInternal , eExpRomPeripheral } ;
static eExpansionRomType g_eExpansionRomType = eExpRomNull ;
static UINT g_uPeripheralRomSlot = 0 ;
//=============================================================================
2007-08-06 21:38:35 +00:00
BYTE __stdcall IO_Null ( WORD programcounter , WORD address , BYTE write , BYTE value , ULONG nCyclesLeft )
2007-05-28 11:16:42 +00:00
{
if ( ! write )
2007-08-06 21:38:35 +00:00
return MemReadFloatingBus ( nCyclesLeft ) ;
2007-05-28 11:16:42 +00:00
else
2006-03-12 09:05:39 +00:00
return 0 ;
2007-05-28 11:16:42 +00:00
}
2007-08-06 21:38:35 +00:00
BYTE __stdcall IO_Annunciator ( WORD programcounter , WORD address , BYTE write , BYTE value , ULONG nCyclesLeft )
2007-05-28 11:16:42 +00:00
{
// Apple//e ROM:
// . PC=FA6F: LDA $C058 (SETAN0)
// . PC=FA72: LDA $C05A (SETAN1)
// . PC=C2B5: LDA $C05D (CLRAN2)
// NB. AN3: For //e & //c these locations are now used to enabled/disabled DHIRES
return 0 ;
}
// Enabling expansion ROM ($C800..$CFFF]:
// . Enable if: Enable1 && Enable2
// . Enable1 = I/O SELECT' (6502 accesses $Csxx)
// - Reset when 6502 accesses $CFFF
// . Enable2 = I/O STROBE' (6502 accesses [$C800..$CFFF])
2007-08-06 21:38:35 +00:00
BYTE __stdcall IORead_Cxxx ( WORD programcounter , WORD address , BYTE write , BYTE value , ULONG nCyclesLeft )
2007-05-28 11:16:42 +00:00
{
if ( address = = 0xCFFF )
{
// Disable expansion ROM at [$C800..$CFFF]
// . SSC will disable on an access to $CFxx - but ROM only writes to $CFFF, so it doesn't matter
IO_SELECT = 0 ;
IO_SELECT_InternalROM = 0 ;
g_uPeripheralRomSlot = 0 ;
if ( SW_SLOTCXROM )
{
// NB. SW_SLOTCXROM==0 ensures that internal rom stays switched in
memset ( pCxRomPeripheral + 0x800 , 0 , 0x800 ) ;
memset ( mem + 0xC800 , 0 , 0x800 ) ;
g_eExpansionRomType = eExpRomNull ;
}
// NB. IO_SELECT won't get set, so ROM won't be switched back in...
}
//
BYTE IO_STROBE = 0 ;
if ( IS_APPLE2 | | SW_SLOTCXROM )
{
if ( ( address > = 0xC100 ) & & ( address < = 0xC7FF ) )
{
const UINT uSlot = ( address > > 8 ) & 0xF ;
if ( ( uSlot ! = 3 ) & & ExpansionRom [ uSlot ] )
IO_SELECT | = 1 < < uSlot ;
else if ( ( SW_SLOTC3ROM ) & & ExpansionRom [ uSlot ] )
IO_SELECT | = 1 < < uSlot ; // Slot3 & Peripheral ROM
else if ( ! SW_SLOTC3ROM )
IO_SELECT_InternalROM = 1 ; // Slot3 & Internal ROM
}
else if ( ( address > = 0xC800 ) & & ( address < = 0xCFFF ) )
{
IO_STROBE = 1 ;
}
//
if ( IO_SELECT & & IO_STROBE )
{
// Enable Peripheral Expansion ROM
UINT uSlot = 1 ;
for ( ; uSlot < NUM_SLOTS ; uSlot + + )
{
if ( IO_SELECT & ( 1 < < uSlot ) )
{
BYTE RemainingSelected = IO_SELECT & ~ ( 1 < < uSlot ) ;
_ASSERT ( RemainingSelected = = 0 ) ;
break ;
}
}
if ( ExpansionRom [ uSlot ] & & ( g_uPeripheralRomSlot ! = uSlot ) )
{
memcpy ( pCxRomPeripheral + 0x800 , ExpansionRom [ uSlot ] , 0x800 ) ;
memcpy ( mem + 0xC800 , ExpansionRom [ uSlot ] , 0x800 ) ;
g_eExpansionRomType = eExpRomPeripheral ;
g_uPeripheralRomSlot = uSlot ;
}
}
else if ( IO_SELECT_InternalROM & & IO_STROBE & & ( g_eExpansionRomType ! = eExpRomInternal ) )
{
// Enable Internal ROM
// . Get this for PR#3
memcpy ( mem + 0xC800 , pCxRomInternal + 0x800 , 0x800 ) ;
g_eExpansionRomType = eExpRomInternal ;
g_uPeripheralRomSlot = 0 ;
}
}
if ( ! IS_APPLE2 & & ! SW_SLOTCXROM )
{
// !SW_SLOTC3ROM = Internal ROM: $C300-C3FF
// !SW_SLOTCXROM = Internal ROM: $C100-CFFF
if ( ( address > = 0xC100 ) & & ( address < = 0xC7FF ) ) // Don't care about state of SW_SLOTC3ROM
IO_SELECT_InternalROM = 1 ;
else if ( ( address > = 0xC800 ) & & ( address < = 0xCFFF ) )
IO_STROBE = 1 ;
if ( ! SW_SLOTCXROM & & IO_SELECT_InternalROM & & IO_STROBE & & ( g_eExpansionRomType ! = eExpRomInternal ) )
{
// Enable Internal ROM
memcpy ( mem + 0xC800 , pCxRomInternal + 0x800 , 0x800 ) ;
g_eExpansionRomType = eExpRomInternal ;
g_uPeripheralRomSlot = 0 ;
}
2006-03-12 09:05:39 +00:00
}
2007-05-28 11:16:42 +00:00
if ( ( g_eExpansionRomType = = eExpRomNull ) & & ( address > = 0xC800 ) )
2007-08-06 21:38:35 +00:00
return IO_Null ( programcounter , address , write , value , nCyclesLeft ) ;
2007-05-28 11:16:42 +00:00
else
return mem [ address ] ;
}
2007-08-06 21:38:35 +00:00
BYTE __stdcall IOWrite_Cxxx ( WORD programcounter , WORD address , BYTE write , BYTE value , ULONG nCyclesLeft )
2007-05-28 11:16:42 +00:00
{
return 0 ;
2006-02-25 20:50:29 +00:00
}
//===========================================================================
2007-05-28 11:16:42 +00:00
static BYTE g_bmSlotInit = 0 ;
static void InitIoHandlers ( )
{
g_bmSlotInit = 0 ;
UINT i = 0 ;
for ( ; i < 8 ; i + + ) // C00x..C07x
{
IORead [ i ] = IORead_C0xx [ i ] ;
IOWrite [ i ] = IOWrite_C0xx [ i ] ;
}
for ( ; i < 16 ; i + + ) // C08x..C0Fx
{
IORead [ i ] = IO_Null ;
IOWrite [ i ] = IO_Null ;
}
//
for ( ; i < 256 ; i + + ) // C10x..CFFx
{
IORead [ i ] = IORead_Cxxx ;
IOWrite [ i ] = IOWrite_Cxxx ;
}
//
IO_SELECT = 0 ;
IO_SELECT_InternalROM = 0 ;
g_eExpansionRomType = eExpRomNull ;
g_uPeripheralRomSlot = 0 ;
for ( i = 0 ; i < NUM_SLOTS ; i + + )
ExpansionRom [ i ] = NULL ;
}
// All slots [0..7] must register their handlers
void RegisterIoHandler ( UINT uSlot , iofunction IOReadC0 , iofunction IOWriteC0 , iofunction IOReadCx , iofunction IOWriteCx , LPVOID lpSlotParameter , BYTE * pExpansionRom )
{
_ASSERT ( uSlot < NUM_SLOTS ) ;
g_bmSlotInit | = 1 < < uSlot ;
SlotParameters [ uSlot ] = lpSlotParameter ;
IORead [ uSlot + 8 ] = IOReadC0 ;
IOWrite [ uSlot + 8 ] = IOWriteC0 ;
if ( uSlot = = 0 ) // Don't trash C0xx handlers
return ;
if ( IOReadCx = = NULL ) IOReadCx = IORead_Cxxx ;
if ( IOWriteCx = = NULL ) IOWriteCx = IOWrite_Cxxx ;
for ( UINT i = 0 ; i < 16 ; i + + )
{
IORead [ uSlot * 16 + i ] = IOReadCx ;
IOWrite [ uSlot * 16 + i ] = IOWriteCx ;
}
// What about [$C80x..$CFEx]? - Do any cards use this as I/O memory?
ExpansionRom [ uSlot ] = pExpansionRom ;
2006-02-25 20:50:29 +00:00
}
//===========================================================================
2007-05-28 11:16:42 +00:00
//// Only called by MemSetFastPaging()
//void BackMainImage ()
//{
// for (UINT loop = 0; loop < 256; loop++)
// {
// if (memshadow[loop] && ((*(memdirty+loop) & 1) || (loop <= 1)))
// CopyMemory(memshadow[loop],memimage+(loop << 8),256);
//
// *(memdirty+loop) &= ~1;
// }
//}
//===========================================================================
void ResetPaging ( BOOL initialize )
{
//if (!initialize)
// MemSetFastPaging(0);
lastwriteram = 0 ;
memmode = MF_BANK2 | MF_SLOTCXROM | MF_WRITERAM ;
UpdatePaging ( initialize , 0 ) ;
2006-02-25 20:50:29 +00:00
}
//===========================================================================
2007-05-28 11:16:42 +00:00
//void UpdateFastPaging () {
// BOOL found = 0;
// DWORD imagenum = 0;
// do
// if ((imagemode[imagenum] == memmode) ||
// ((lastimage >= 3) &&
// ((imagemode[imagenum] & MF_IMAGEMASK) == (memmode & MF_IMAGEMASK))))
// found = 1;
// else
// ++imagenum;
// while ((imagenum <= lastimage) && !found);
// if (found) {
// image = imagenum;
// mem = memimage+(image << 16);
// if (imagemode[image] != memmode) {
// imagemode[image] = memmode;
// UpdatePaging(0,1);
// }
// }
// else {
// if (lastimage < MAXIMAGES-1) {
// imagenum = ++lastimage;
// if (lastimage >= 3)
// VirtualAlloc(memimage+lastimage*0x10000,0x10000,MEM_COMMIT,PAGE_READWRITE);
// }
// else {
// static DWORD nextimage = 0;
// if (nextimage > lastimage)
// nextimage = 0;
// imagenum = nextimage++;
// }
// imagemode[image = imagenum] = memmode;
// mem = memimage+(image << 16);
// UpdatePaging(1,0);
// }
//}
//===========================================================================
static void UpdatePaging ( BOOL initialize , BOOL updatewriteonly )
{
// SAVE THE CURRENT PAGING SHADOW TABLE
LPBYTE oldshadow [ 256 ] ;
if ( ! ( initialize | | updatewriteonly /*|| fastpaging*/ ) )
CopyMemory ( oldshadow , memshadow , 256 * sizeof ( LPBYTE ) ) ;
// UPDATE THE PAGING TABLES BASED ON THE NEW PAGING SWITCH VALUES
UINT loop ;
if ( initialize )
{
for ( loop = 0x00 ; loop < 0xC0 ; loop + + )
memwrite [ loop ] = mem + ( loop < < 8 ) ;
for ( loop = 0xC0 ; loop < 0xD0 ; loop + + )
memwrite [ loop ] = NULL ;
}
if ( ! updatewriteonly )
{
for ( loop = 0x00 ; loop < 0x02 ; loop + + )
memshadow [ loop ] = SW_ALTZP ? memaux + ( loop < < 8 ) : memmain + ( loop < < 8 ) ;
}
2006-02-25 20:50:29 +00:00
2007-05-28 11:16:42 +00:00
for ( loop = 0x02 ; loop < 0xC0 ; loop + + )
{
memshadow [ loop ] = SW_AUXREAD ? memaux + ( loop < < 8 )
: memmain + ( loop < < 8 ) ;
memwrite [ loop ] = ( ( SW_AUXREAD ! = 0 ) = = ( SW_AUXWRITE ! = 0 ) )
? mem + ( loop < < 8 )
: SW_AUXWRITE ? memaux + ( loop < < 8 )
: memmain + ( loop < < 8 ) ;
}
if ( ! updatewriteonly )
{
for ( loop = 0xC0 ; loop < 0xC8 ; loop + + )
{
const UINT uSlotOffset = ( loop & 0x0f ) * 0x100 ;
if ( loop = = 0xC3 )
memshadow [ loop ] = ( SW_SLOTC3ROM & & SW_SLOTCXROM ) ? pCxRomPeripheral + uSlotOffset // C300..C3FF - Slot 3 ROM (all 0x00's)
: pCxRomInternal + uSlotOffset ; // C300..C3FF - Internal ROM
else
memshadow [ loop ] = SW_SLOTCXROM ? pCxRomPeripheral + uSlotOffset // C000..C7FF - SSC/Disk][/etc
: pCxRomInternal + uSlotOffset ; // C000..C7FF - Internal ROM
}
for ( loop = 0xC8 ; loop < 0xD0 ; loop + + )
{
const UINT uRomOffset = ( loop & 0x0f ) * 0x100 ;
memshadow [ loop ] = pCxRomInternal + uRomOffset ; // C800..CFFF - Internal ROM
}
}
for ( loop = 0xD0 ; loop < 0xE0 ; loop + + )
{
int bankoffset = ( SW_BANK2 ? 0 : 0x1000 ) ;
memshadow [ loop ] = SW_HIGHRAM ? SW_ALTZP ? memaux + ( loop < < 8 ) - bankoffset
: memmain + ( loop < < 8 ) - bankoffset
: memrom + ( ( loop - 0xD0 ) * 0x100 ) ;
memwrite [ loop ] = SW_WRITERAM ? SW_HIGHRAM ? mem + ( loop < < 8 )
: SW_ALTZP ? memaux + ( loop < < 8 ) - bankoffset
: memmain + ( loop < < 8 ) - bankoffset
: NULL ;
}
for ( loop = 0xE0 ; loop < 0x100 ; loop + + )
{
memshadow [ loop ] = SW_HIGHRAM ? SW_ALTZP ? memaux + ( loop < < 8 )
: memmain + ( loop < < 8 )
: memrom + ( ( loop - 0xD0 ) * 0x100 ) ;
memwrite [ loop ] = SW_WRITERAM ? SW_HIGHRAM ? mem + ( loop < < 8 )
: SW_ALTZP ? memaux + ( loop < < 8 )
: memmain + ( loop < < 8 )
: NULL ;
}
if ( SW_80STORE )
{
for ( loop = 0x04 ; loop < 0x08 ; loop + + )
{
memshadow [ loop ] = SW_PAGE2 ? memaux + ( loop < < 8 )
: memmain + ( loop < < 8 ) ;
memwrite [ loop ] = mem + ( loop < < 8 ) ;
}
if ( SW_HIRES )
{
for ( loop = 0x20 ; loop < 0x40 ; loop + + )
{
memshadow [ loop ] = SW_PAGE2 ? memaux + ( loop < < 8 )
: memmain + ( loop < < 8 ) ;
memwrite [ loop ] = mem + ( loop < < 8 ) ;
}
}
}
// MOVE MEMORY BACK AND FORTH AS NECESSARY BETWEEN THE SHADOW AREAS AND
// THE MAIN RAM IMAGE TO KEEP BOTH SETS OF MEMORY CONSISTENT WITH THE NEW
// PAGING SHADOW TABLE
if ( ! updatewriteonly )
{
for ( loop = 0x00 ; loop < 0x100 ; loop + + )
{
if ( initialize | | ( oldshadow [ loop ] ! = memshadow [ loop ] ) )
{
if ( ( ! ( initialize /* || fastpaging*/ ) ) & &
( ( * ( memdirty + loop ) & 1 ) | | ( loop < = 1 ) ) )
{
* ( memdirty + loop ) & = ~ 1 ;
CopyMemory ( oldshadow [ loop ] , mem + ( loop < < 8 ) , 256 ) ;
}
CopyMemory ( mem + ( loop < < 8 ) , memshadow [ loop ] , 256 ) ;
}
}
}
2006-02-25 20:50:29 +00:00
}
//
// ----- ALL GLOBALLY ACCESSIBLE FUNCTIONS ARE BELOW THIS LINE -----
//
//===========================================================================
2007-05-28 11:16:42 +00:00
// TODO: >= Apple2e only?
BYTE __stdcall MemCheckPaging ( WORD , WORD address , BYTE , BYTE , ULONG )
{
address & = 0xFF ;
BOOL result = 0 ;
switch ( address )
{
case 0x11 : result = SW_BANK2 ; break ;
case 0x12 : result = SW_HIGHRAM ; break ;
case 0x13 : result = SW_AUXREAD ; break ;
case 0x14 : result = SW_AUXWRITE ; break ;
case 0x15 : result = ! SW_SLOTCXROM ; break ;
case 0x16 : result = SW_ALTZP ; break ;
case 0x17 : result = SW_SLOTC3ROM ; break ;
case 0x18 : result = SW_80STORE ; break ;
case 0x1C : result = SW_PAGE2 ; break ;
case 0x1D : result = SW_HIRES ; break ;
}
return KeybGetKeycode ( ) | ( result ? 0x80 : 0 ) ;
2006-02-25 20:50:29 +00:00
}
//===========================================================================
2007-05-28 11:16:42 +00:00
void MemDestroy ( )
{
//if (fastpaging)
// MemSetFastPaging(0);
// VirtualFree(memimage,MAX(0x30000,0x10000*1),MEM_DECOMMIT);
VirtualFree ( memaux , 0 , MEM_RELEASE ) ;
VirtualFree ( memmain , 0 , MEM_RELEASE ) ;
VirtualFree ( memdirty , 0 , MEM_RELEASE ) ;
VirtualFree ( memrom , 0 , MEM_RELEASE ) ;
VirtualFree ( memimage , 0 , MEM_RELEASE ) ;
VirtualFree ( pCxRomInternal , 0 , MEM_RELEASE ) ;
VirtualFree ( pCxRomPeripheral , 0 , MEM_RELEASE ) ;
2006-02-25 20:50:29 +00:00
# ifdef RAMWORKS
for ( UINT i = 1 ; i < g_uMaxExPages ; i + + )
{
if ( RWpages [ i ] )
{
VirtualFree ( RWpages [ i ] , 0 , MEM_RELEASE ) ;
RWpages [ i ] = NULL ;
}
}
RWpages [ 0 ] = NULL ;
# endif
2007-05-28 11:16:42 +00:00
memaux = NULL ;
memmain = NULL ;
memdirty = NULL ;
memrom = NULL ;
memimage = NULL ;
pCxRomInternal = NULL ;
pCxRomPeripheral = NULL ;
mem = NULL ;
ZeroMemory ( memwrite , sizeof ( memwrite ) ) ;
ZeroMemory ( memshadow , sizeof ( memshadow ) ) ;
2006-02-25 20:50:29 +00:00
}
2006-03-12 09:05:39 +00:00
//===========================================================================
bool MemGet80Store ( )
{
return SW_80STORE ! = 0 ;
}
2007-05-28 11:16:42 +00:00
//===========================================================================
bool MemCheckSLOTCXROM ( )
{
return SW_SLOTCXROM ? true : false ;
}
2006-02-25 20:50:29 +00:00
//===========================================================================
LPBYTE MemGetAuxPtr ( WORD offset )
{
2007-05-28 11:16:42 +00:00
LPBYTE lpMem = ( memshadow [ ( offset > > 8 ) ] = = ( memaux + ( offset & 0xFF00 ) ) )
2006-02-25 20:50:29 +00:00
? mem + offset
: memaux + offset ;
# ifdef RAMWORKS
if ( ( ( SW_PAGE2 & & SW_80STORE ) | | VideoGetSW80COL ( ) ) & &
( ( ( ( offset & 0xFF00 ) > = 0x0400 ) & &
( ( offset & 0xFF00 ) < = 0700 ) ) | |
( SW_HIRES & & ( ( offset & 0xFF00 ) > = 0x2000 ) & &
( ( offset & 0xFF00 ) < = 0x3F00 ) ) ) ) {
2007-05-28 11:16:42 +00:00
lpMem = ( memshadow [ ( offset > > 8 ) ] = = ( RWpages [ 0 ] + ( offset & 0xFF00 ) ) )
2006-02-25 20:50:29 +00:00
? mem + offset
: RWpages [ 0 ] + offset ;
}
# endif
return lpMem ;
}
//===========================================================================
2007-05-28 11:16:42 +00:00
LPBYTE MemGetMainPtr ( WORD offset )
{
return ( memshadow [ ( offset > > 8 ) ] = = ( memmain + ( offset & 0xFF00 ) ) )
2006-02-25 20:50:29 +00:00
? mem + offset
: memmain + offset ;
}
//===========================================================================
2007-05-28 11:16:42 +00:00
2007-08-06 21:38:35 +00:00
LPBYTE MemGetCxRomPeripheral ( )
{
return pCxRomPeripheral ;
}
//===========================================================================
2007-05-28 11:16:42 +00:00
void MemPreInitialize ( )
{
// Init the I/O handlers
InitIoHandlers ( ) ;
}
//===========================================================================
void MemInitialize ( )
{
const UINT CxRomSize = 4 * 1024 ;
const UINT Apple2RomSize = 12 * 1024 ;
const UINT Apple2eRomSize = Apple2RomSize + CxRomSize ;
2008-06-20 23:47:25 +00:00
//const UINT Pravets82RomSize = 12*1024;
//const UINT Pravets8ARomSize = Pravets82RomSize+CxRomSize;
2007-05-28 11:16:42 +00:00
// ALLOCATE MEMORY FOR THE APPLE MEMORY IMAGE AND ASSOCIATED DATA STRUCTURES
memaux = ( LPBYTE ) VirtualAlloc ( NULL , _6502_MEM_END + 1 , MEM_COMMIT , PAGE_READWRITE ) ;
memmain = ( LPBYTE ) VirtualAlloc ( NULL , _6502_MEM_END + 1 , MEM_COMMIT , PAGE_READWRITE ) ;
memdirty = ( LPBYTE ) VirtualAlloc ( NULL , 0x100 , MEM_COMMIT , PAGE_READWRITE ) ;
memrom = ( LPBYTE ) VirtualAlloc ( NULL , 0x5000 , MEM_COMMIT , PAGE_READWRITE ) ;
// // THE MEMIMAGE BUFFER CAN CONTAIN EITHER MULTIPLE MEMORY IMAGES OR ONE MEMORY IMAGE WITH COMPILER DATA
// memimage = (LPBYTE)VirtualAlloc(NULL,
// MAX(0x30000,MAXIMAGES*0x10000),
// MEM_RESERVE,PAGE_NOACCESS);
memimage = ( LPBYTE ) VirtualAlloc ( NULL , _6502_MEM_END + 1 , MEM_RESERVE , PAGE_NOACCESS ) ;
pCxRomInternal = ( LPBYTE ) VirtualAlloc ( NULL , CxRomSize , MEM_COMMIT , PAGE_READWRITE ) ;
pCxRomPeripheral = ( LPBYTE ) VirtualAlloc ( NULL , CxRomSize , MEM_COMMIT , PAGE_READWRITE ) ;
if ( ! memaux | | ! memdirty | | ! memimage | | ! memmain | | ! memrom | | ! pCxRomInternal | | ! pCxRomPeripheral )
2006-06-27 02:34:46 +00:00
{
MessageBox (
GetDesktopWindow ( ) ,
TEXT ( " The emulator was unable to allocate the memory it " )
TEXT ( " requires. Further execution is not possible. " ) ,
g_pAppTitle ,
MB_ICONSTOP | MB_SETFOREGROUND ) ;
ExitProcess ( 1 ) ;
}
2007-05-28 11:16:42 +00:00
// LPVOID newloc = VirtualAlloc(memimage,0x30000,MEM_COMMIT,PAGE_READWRITE);
LPVOID newloc = VirtualAlloc ( memimage , _6502_MEM_END + 1 , MEM_COMMIT , PAGE_READWRITE ) ;
2006-06-27 02:34:46 +00:00
if ( newloc ! = memimage )
MessageBox (
GetDesktopWindow ( ) ,
TEXT ( " The emulator has detected a bug in your operating " )
TEXT ( " system. While changing the attributes of a memory " )
TEXT ( " object, the operating system also changed its " )
TEXT ( " location. " ) ,
g_pAppTitle ,
MB_ICONEXCLAMATION | MB_SETFOREGROUND ) ;
2006-02-25 20:50:29 +00:00
# ifdef RAMWORKS
// allocate memory for RAMWorks III - up to 8MB
RWpages [ 0 ] = memaux ;
UINT i = 1 ;
2007-05-28 11:16:42 +00:00
while ( ( i < g_uMaxExPages ) & & ( RWpages [ i ] = ( LPBYTE ) VirtualAlloc ( NULL , _6502_MEM_END + 1 , MEM_COMMIT , PAGE_READWRITE ) ) )
2006-02-25 20:50:29 +00:00
i + + ;
# endif
2006-06-27 02:34:46 +00:00
// READ THE APPLE FIRMWARE ROMS INTO THE ROM IMAGE
2007-05-28 11:16:42 +00:00
UINT ROM_SIZE = 0 ;
HRSRC hResInfo = NULL ;
switch ( g_Apple2Type )
{
case A2TYPE_APPLE2 : hResInfo = FindResource ( NULL , MAKEINTRESOURCE ( IDR_APPLE2_ROM ) , " ROM " ) ; ROM_SIZE = Apple2RomSize ; break ;
case A2TYPE_APPLE2PLUS : hResInfo = FindResource ( NULL , MAKEINTRESOURCE ( IDR_APPLE2_PLUS_ROM ) , " ROM " ) ; ROM_SIZE = Apple2RomSize ; break ;
case A2TYPE_APPLE2E : hResInfo = FindResource ( NULL , MAKEINTRESOURCE ( IDR_APPLE2E_ROM ) , " ROM " ) ; ROM_SIZE = Apple2eRomSize ; break ;
case A2TYPE_APPLE2EEHANCED : hResInfo = FindResource ( NULL , MAKEINTRESOURCE ( IDR_APPLE2E_ENHANCED_ROM ) , " ROM " ) ; ROM_SIZE = Apple2eRomSize ; break ;
2008-06-20 23:47:25 +00:00
case A2TYPE_PRAVETS82 : hResInfo = FindResource ( NULL , MAKEINTRESOURCE ( IDR_PRAVETS_82_ROM ) , " ROM " ) ; ROM_SIZE = Apple2RomSize ; break ;
case A2TYPE_PRAVETS8A : hResInfo = FindResource ( NULL , MAKEINTRESOURCE ( IDR_PRAVETS_8C_ROM ) , " ROM " ) ; ROM_SIZE = Apple2eRomSize ; break ;
2007-05-28 11:16:42 +00:00
}
2006-03-13 23:46:57 +00:00
if ( hResInfo = = NULL )
2006-02-26 01:20:36 +00:00
{
2006-06-27 02:34:46 +00:00
TCHAR sRomFileName [ MAX_PATH ] ;
2007-05-28 11:16:42 +00:00
switch ( g_Apple2Type )
{
case A2TYPE_APPLE2 : _tcscpy ( sRomFileName , TEXT ( " APPLE2.ROM " ) ) ; break ;
case A2TYPE_APPLE2PLUS : _tcscpy ( sRomFileName , TEXT ( " APPLE2_PLUS.ROM " ) ) ; break ;
case A2TYPE_APPLE2E : _tcscpy ( sRomFileName , TEXT ( " APPLE2E.ROM " ) ) ; break ;
case A2TYPE_APPLE2EEHANCED : _tcscpy ( sRomFileName , TEXT ( " APPLE2E_ENHANCED.ROM " ) ) ; break ;
2008-06-20 23:47:25 +00:00
case A2TYPE_PRAVETS82 : _tcscpy ( sRomFileName , TEXT ( " PRAVETS82.ROM " ) ) ; break ; //Rom to be changed. Currently an Apple 2E Rom is used, because of the lack of a genuine Pravets82 one.
case A2TYPE_PRAVETS8A : _tcscpy ( sRomFileName , TEXT ( " PRAVETS8C.ROM " ) ) ; break ;
2007-05-28 11:16:42 +00:00
}
2006-06-27 02:34:46 +00:00
TCHAR sText [ MAX_PATH ] ;
2007-05-28 11:16:42 +00:00
wsprintf ( sText , TEXT ( " Unable to open the required firmware ROM data file. \n \n File: %s " ) , sRomFileName ) ;
2006-02-26 01:20:36 +00:00
2006-06-27 02:34:46 +00:00
MessageBox (
GetDesktopWindow ( ) ,
sText ,
g_pAppTitle ,
MB_ICONSTOP | MB_SETFOREGROUND ) ;
2006-02-26 01:20:36 +00:00
ExitProcess ( 1 ) ;
}
2006-03-13 23:46:57 +00:00
DWORD dwResSize = SizeofResource ( NULL , hResInfo ) ;
if ( dwResSize ! = ROM_SIZE )
return ;
HGLOBAL hResData = LoadResource ( NULL , hResInfo ) ;
if ( hResData = = NULL )
return ;
BYTE * pData = ( BYTE * ) LockResource ( hResData ) ; // NB. Don't need to unlock resource
2006-06-27 02:34:46 +00:00
if ( pData = = NULL )
2006-03-13 23:46:57 +00:00
return ;
2007-05-28 11:16:42 +00:00
//
memset ( pCxRomInternal , 0 , CxRomSize ) ;
memset ( pCxRomPeripheral , 0 , CxRomSize ) ;
if ( ROM_SIZE = = Apple2eRomSize )
{
memcpy ( pCxRomInternal , pData , CxRomSize ) ;
pData + = CxRomSize ;
ROM_SIZE - = CxRomSize ;
}
_ASSERT ( ROM_SIZE = = Apple2RomSize ) ;
2008-02-22 21:28:35 +00:00
memcpy ( memrom , pData , Apple2RomSize ) ; // ROM at $D000...$FFFF
const UINT F8RomSize = 0x800 ;
if ( g_hCustomRomF8 ! = INVALID_HANDLE_VALUE )
{
SetFilePointer ( g_hCustomRomF8 , 0 , NULL , FILE_BEGIN ) ;
DWORD uNumBytesRead ;
BOOL bRes = ReadFile ( g_hCustomRomF8 , memrom + Apple2RomSize - F8RomSize , F8RomSize , & uNumBytesRead , NULL ) ;
if ( uNumBytesRead ! = F8RomSize )
{
memcpy ( memrom , pData , Apple2RomSize ) ; // ROM at $D000...$FFFF
bRes = FALSE ;
}
if ( ! bRes )
{
MessageBox ( g_hFrameWindow , " Failed to read custom F8 rom " , TEXT ( " AppleWin Error " ) , MB_OK ) ;
CloseHandle ( g_hCustomRomF8 ) ;
g_hCustomRomF8 = INVALID_HANDLE_VALUE ;
// Failed, so use default rom...
}
}
2008-05-17 23:20:33 +00:00
if ( g_uTheFreezesF8Rom & & IS_APPLE2 )
2008-02-22 21:28:35 +00:00
{
hResInfo = FindResource ( NULL , MAKEINTRESOURCE ( IDR_FREEZES_F8_ROM ) , " ROM " ) ;
if ( hResInfo & & ( SizeofResource ( NULL , hResInfo ) = = 0x800 ) & & ( hResData = LoadResource ( NULL , hResInfo ) ) & & ( pData = ( BYTE * ) LockResource ( hResData ) ) )
{
memcpy ( memrom + Apple2RomSize - F8RomSize , pData , F8RomSize ) ;
}
}
2007-05-28 11:16:42 +00:00
//
2006-02-25 20:50:29 +00:00
2007-05-28 11:16:42 +00:00
const UINT uSlot = 0 ;
RegisterIoHandler ( uSlot , MemSetPaging , MemSetPaging , NULL , NULL , NULL , NULL ) ;
2006-02-25 20:50:29 +00:00
2007-08-06 21:38:35 +00:00
PrintLoadRom ( pCxRomPeripheral , 1 ) ; // $C100 : Parallel printer f/w
sg_SSC . CommInitialize ( pCxRomPeripheral , 2 ) ; // $C200 : SSC
if ( g_Slot4 = = CT_MouseInterface )
sg_Mouse . Initialize ( pCxRomPeripheral , 4 ) ; // $C400 : Mouse f/w
2008-08-19 21:36:31 +00:00
# ifdef SUPPORT_CPM
ConfigureSoftcard ( pCxRomPeripheral , 5 , g_uZ80InSlot5 ) ; // $C500 ; Z80 card
# endif
2007-08-06 21:38:35 +00:00
DiskLoadRom ( pCxRomPeripheral , 6 ) ; // $C600 : Disk][ f/w
HD_Load_Rom ( pCxRomPeripheral , 7 ) ; // $C700 : HDD f/w
2006-02-25 20:50:29 +00:00
2006-06-27 02:34:46 +00:00
MemReset ( ) ;
2006-02-25 20:50:29 +00:00
}
//===========================================================================
2006-06-27 02:34:46 +00:00
// Called by:
2007-05-28 11:16:42 +00:00
// . MemInitialize()
2006-02-25 20:50:29 +00:00
// . ResetMachineState() eg. Power-cycle ('Apple-Go' button)
// . Snapshot_LoadState()
void MemReset ( )
{
2007-05-28 11:16:42 +00:00
//// TURN OFF FAST PAGING IF IT IS CURRENTLY ACTIVE
//MemSetFastPaging(0);
2006-02-25 20:50:29 +00:00
2006-06-27 02:34:46 +00:00
// INITIALIZE THE PAGING TABLES
2007-05-28 11:16:42 +00:00
ZeroMemory ( memshadow , 256 * sizeof ( LPBYTE ) ) ;
ZeroMemory ( memwrite , 256 * sizeof ( LPBYTE ) ) ;
2006-02-25 20:50:29 +00:00
2006-06-27 02:34:46 +00:00
// INITIALIZE THE RAM IMAGES
ZeroMemory ( memaux , 0x10000 ) ;
2006-03-03 18:54:41 +00:00
2006-06-27 02:34:46 +00:00
ZeroMemory ( memmain , 0x10000 ) ;
2006-02-25 20:50:29 +00:00
2006-03-03 18:54:41 +00:00
int iByte ;
2006-03-09 21:10:40 +00:00
if ( g_eMemoryInitPattern = = MIP_FF_FF_00_00 )
2006-03-03 18:54:41 +00:00
{
2006-03-09 21:10:40 +00:00
for ( iByte = 0x0000 ; iByte < 0xC000 ; )
{
memmain [ iByte + + ] = 0xFF ;
memmain [ iByte + + ] = 0xFF ;
2006-03-03 18:54:41 +00:00
2006-03-09 21:10:40 +00:00
iByte + + ;
iByte + + ;
}
2006-03-03 18:54:41 +00:00
}
2006-06-27 02:34:46 +00:00
// SET UP THE MEMORY IMAGE
mem = memimage ;
2007-05-28 11:16:42 +00:00
//image = 0;
2006-02-25 20:50:29 +00:00
2006-06-27 02:34:46 +00:00
// INITIALIZE PAGING, FILLING IN THE 64K MEMORY IMAGE
ResetPaging ( 1 ) ;
2007-05-28 11:16:42 +00:00
// INITIALIZE & RESET THE CPU
// . Do this after ROM has been copied back to mem[], so that PC is correctly init'ed from 6502's reset vector
CpuInitialize ( ) ;
2008-06-20 23:47:25 +00:00
//Sets Caps Lock = false (Pravets 8A/C only)
2008-08-19 21:36:31 +00:00
# ifdef SUPPORT_CPM
Z80_Reset ( ) ;
# endif
2006-02-25 20:50:29 +00:00
}
//===========================================================================
// Call by:
// . Soft-reset (Ctrl+Reset)
// . Snapshot_LoadState()
void MemResetPaging ( )
{
ResetPaging ( 0 ) ;
2008-06-20 23:47:25 +00:00
if ( g_Apple2Type = = A2TYPE_PRAVETS8A )
{
P8CAPS_ON = false ;
TapeWrite ( 0 , 0 , 0 , 0 , 0 ) ;
FrameRefreshStatus ( DRAW_LEDS ) ;
}
2006-02-25 20:50:29 +00:00
}
//===========================================================================
2007-05-28 11:16:42 +00:00
// Called by Disk][ I/O only
BYTE MemReturnRandomData ( BYTE highbit )
{
2006-02-25 20:50:29 +00:00
static const BYTE retval [ 16 ] = { 0x00 , 0x2D , 0x2D , 0x30 , 0x30 , 0x32 , 0x32 , 0x34 ,
0x35 , 0x39 , 0x43 , 0x43 , 0x43 , 0x60 , 0x7F , 0x7F } ;
BYTE r = ( BYTE ) ( rand ( ) & 0xFF ) ;
if ( r < = 170 )
return 0x20 | ( highbit ? 0x80 : 0 ) ;
else
return retval [ r & 15 ] | ( highbit ? 0x80 : 0 ) ;
}
2006-03-12 09:05:39 +00:00
//===========================================================================
2007-08-06 21:38:35 +00:00
BYTE MemReadFloatingBus ( const ULONG uExecutedCycles )
2006-03-12 09:05:39 +00:00
{
2007-08-06 21:38:35 +00:00
return * ( LPBYTE ) ( mem + VideoGetScannerAddress ( NULL , uExecutedCycles ) ) ;
2006-03-12 09:05:39 +00:00
}
//===========================================================================
2007-08-06 21:38:35 +00:00
BYTE MemReadFloatingBus ( const BYTE highbit , const ULONG uExecutedCycles )
2006-03-12 09:05:39 +00:00
{
2007-08-06 21:38:35 +00:00
BYTE r = * ( LPBYTE ) ( mem + VideoGetScannerAddress ( NULL , uExecutedCycles ) ) ;
2006-03-12 09:05:39 +00:00
return ( r & ~ 0x80 ) | ( ( highbit ) ? 0x80 : 0 ) ;
}
2006-02-25 20:50:29 +00:00
//===========================================================================
2007-05-28 11:16:42 +00:00
//void MemSetFastPaging (BOOL on) {
// if (fastpaging && modechanging) {
// modechanging = 0;
// UpdateFastPaging();
// }
// else if (!fastpaging) {
// BackMainImage();
// if (lastimage >= 3)
// VirtualFree(memimage+0x30000,(lastimage-2) << 16,MEM_DECOMMIT);
// }
// fastpaging = on;
// image = 0;
// mem = memimage;
// lastimage = 0;
// imagemode[0] = memmode;
// if (!fastpaging)
// UpdatePaging(1,0);
//}
2006-02-25 20:50:29 +00:00
//===========================================================================
2007-08-06 21:38:35 +00:00
BYTE __stdcall MemSetPaging ( WORD programcounter , WORD address , BYTE write , BYTE value , ULONG nCyclesLeft )
2007-05-28 11:16:42 +00:00
{
address & = 0xFF ;
2006-02-25 20:50:29 +00:00
DWORD lastmemmode = memmode ;
// DETERMINE THE NEW MEMORY PAGING MODE.
if ( ( address > = 0x80 ) & & ( address < = 0x8F ) )
{
BOOL writeram = ( address & 1 ) ;
memmode & = ~ ( MF_BANK2 | MF_HIGHRAM | MF_WRITERAM ) ;
lastwriteram = 1 ; // note: because diags.do doesn't set switches twice!
if ( lastwriteram & & writeram )
memmode | = MF_WRITERAM ;
if ( ! ( address & 8 ) )
memmode | = MF_BANK2 ;
if ( ( ( address & 2 ) > > 1 ) = = ( address & 1 ) )
memmode | = MF_HIGHRAM ;
lastwriteram = writeram ;
}
2007-05-28 11:16:42 +00:00
else if ( ! IS_APPLE2 )
2006-02-25 20:50:29 +00:00
{
switch ( address )
{
case 0x00 : memmode & = ~ MF_80STORE ; break ;
case 0x01 : memmode | = MF_80STORE ; break ;
case 0x02 : memmode & = ~ MF_AUXREAD ; break ;
case 0x03 : memmode | = MF_AUXREAD ; break ;
case 0x04 : memmode & = ~ MF_AUXWRITE ; break ;
case 0x05 : memmode | = MF_AUXWRITE ; break ;
case 0x06 : memmode | = MF_SLOTCXROM ; break ;
case 0x07 : memmode & = ~ MF_SLOTCXROM ; break ;
case 0x08 : memmode & = ~ MF_ALTZP ; break ;
case 0x09 : memmode | = MF_ALTZP ; break ;
case 0x0A : memmode & = ~ MF_SLOTC3ROM ; break ;
case 0x0B : memmode | = MF_SLOTC3ROM ; break ;
case 0x54 : memmode & = ~ MF_PAGE2 ; break ;
case 0x55 : memmode | = MF_PAGE2 ; break ;
case 0x56 : memmode & = ~ MF_HIRES ; break ;
case 0x57 : memmode | = MF_HIRES ; break ;
# ifdef RAMWORKS
case 0x71 : // extended memory aux page number
case 0x73 : // Ramworks III set aux page number
if ( ( value < g_uMaxExPages ) & & RWpages [ value ] )
{
memaux = RWpages [ value ] ;
//memmode &= ~MF_RWPMASK;
//memmode |= value;
2007-05-28 11:16:42 +00:00
//if (fastpaging)
// UpdateFastPaging();
//else
2006-02-25 20:50:29 +00:00
UpdatePaging ( 0 , 0 ) ;
}
break ;
# endif
}
}
// IF THE EMULATED PROGRAM HAS JUST UPDATE THE MEMORY WRITE MODE AND IS
// ABOUT TO UPDATE THE MEMORY READ MODE, HOLD OFF ON ANY PROCESSING UNTIL
// IT DOES SO.
if ( ( address > = 4 ) & & ( address < = 5 ) & &
( ( * ( LPDWORD ) ( mem + programcounter ) & 0x00FFFEFF ) = = 0x00C0028D ) ) {
modechanging = 1 ;
2007-08-06 21:38:35 +00:00
return write ? 0 : MemReadFloatingBus ( 1 , nCyclesLeft ) ;
2006-02-25 20:50:29 +00:00
}
if ( ( address > = 0x80 ) & & ( address < = 0x8F ) & & ( programcounter < 0xC000 ) & &
( ( ( * ( LPDWORD ) ( mem + programcounter ) & 0x00FFFEFF ) = = 0x00C0048D ) | |
( ( * ( LPDWORD ) ( mem + programcounter ) & 0x00FFFEFF ) = = 0x00C0028D ) ) ) {
modechanging = 1 ;
2007-08-06 21:38:35 +00:00
return write ? 0 : MemReadFloatingBus ( 1 , nCyclesLeft ) ;
2006-02-25 20:50:29 +00:00
}
// IF THE MEMORY PAGING MODE HAS CHANGED, UPDATE OUR MEMORY IMAGES AND
// WRITE TABLES.
2007-05-28 11:16:42 +00:00
if ( ( lastmemmode ! = memmode ) | | modechanging )
{
2006-02-25 20:50:29 +00:00
modechanging = 0 ;
2007-05-28 11:16:42 +00:00
if ( ( lastmemmode & MF_SLOTCXROM ) ! = ( memmode & MF_SLOTCXROM ) )
{
if ( SW_SLOTCXROM )
{
// Disable Internal ROM
// . Similar to $CFFF access
// . None of the peripheral cards can be driving the bus - so use the null ROM
memset ( pCxRomPeripheral + 0x800 , 0 , 0x800 ) ;
memset ( mem + 0xC800 , 0 , 0x800 ) ;
g_eExpansionRomType = eExpRomNull ;
g_uPeripheralRomSlot = 0 ;
}
else
{
// Enable Internal ROM
memcpy ( mem + 0xC800 , pCxRomInternal + 0x800 , 0x800 ) ;
g_eExpansionRomType = eExpRomInternal ;
g_uPeripheralRomSlot = 0 ;
}
}
//// IF FAST PAGING IS ACTIVE, WE KEEP MULTIPLE COMPLETE MEMORY IMAGES
//// AND WRITE TABLES, AND SWITCH BETWEEN THEM. THE FAST PAGING VERSION
//// OF THE CPU EMULATOR KEEPS ALL OF THE IMAGES COHERENT.
//if (fastpaging)
// UpdateFastPaging();
2006-02-25 20:50:29 +00:00
// IF FAST PAGING IS NOT ACTIVE THEN WE KEEP ONLY ONE MEMORY IMAGE AND
// WRITE TABLE, AND UPDATE THEM EVERY TIME PAGING IS CHANGED.
2007-05-28 11:16:42 +00:00
//else
2006-02-25 20:50:29 +00:00
UpdatePaging ( 0 , 0 ) ;
}
if ( ( address < = 1 ) | | ( ( address > = 0x54 ) & & ( address < = 0x57 ) ) )
2007-08-06 21:38:35 +00:00
return VideoSetMode ( programcounter , address , write , value , nCyclesLeft ) ;
2006-03-12 09:05:39 +00:00
2007-08-06 21:38:35 +00:00
return write ? 0 : MemReadFloatingBus ( nCyclesLeft ) ;
2006-02-25 20:50:29 +00:00
}
//===========================================================================
2007-05-28 11:16:42 +00:00
//void MemTrimImages () {
// if (fastpaging && (lastimage > 2))
// {
// if (modechanging) {
// modechanging = 0;
// UpdateFastPaging();
// }
// static DWORD trimnumber = 0;
// if ((image != trimnumber) &&
// (image != lastimage) &&
// (trimnumber < lastimage)) {
// imagemode[trimnumber] = imagemode[lastimage];
// VirtualFree(memimage+(lastimage-- << 16),0x10000,MEM_DECOMMIT);
// DWORD realimage = image;
// image = trimnumber;
// mem = memimage+(image << 16);
// memmode = imagemode[image];
// UpdatePaging(1,0);
// image = realimage;
// mem = memimage+(image << 16);
// memmode = imagemode[image];
// }
// if (++trimnumber >= lastimage)
// trimnumber = 0;
// }
//}
2006-02-25 20:50:29 +00:00
//===========================================================================
2007-05-28 11:16:42 +00:00
LPVOID MemGetSlotParameters ( UINT uSlot )
2006-02-25 20:50:29 +00:00
{
2007-05-28 11:16:42 +00:00
_ASSERT ( uSlot < NUM_SLOTS ) ;
return SlotParameters [ uSlot ] ;
2006-02-25 20:50:29 +00:00
}
//===========================================================================
DWORD MemGetSnapshot ( SS_BaseMemory * pSS )
{
pSS - > dwMemMode = memmode ;
pSS - > bLastWriteRam = lastwriteram ;
for ( DWORD dwOffset = 0x0000 ; dwOffset < 0x10000 ; dwOffset + = 0x100 )
{
memcpy ( pSS - > nMemMain + dwOffset , MemGetMainPtr ( ( WORD ) dwOffset ) , 0x100 ) ;
memcpy ( pSS - > nMemAux + dwOffset , MemGetAuxPtr ( ( WORD ) dwOffset ) , 0x100 ) ;
}
return 0 ;
}
DWORD MemSetSnapshot ( SS_BaseMemory * pSS )
{
memmode = pSS - > dwMemMode ;
lastwriteram = pSS - > bLastWriteRam ;
memcpy ( memmain , pSS - > nMemMain , nMemMainSize ) ;
memcpy ( memaux , pSS - > nMemAux , nMemAuxSize ) ;
//
modechanging = 0 ;
UpdatePaging ( 1 , 0 ) ; // Initialize=1, UpdateWriteOnly=0
return 0 ;
}