mirror of
https://github.com/AppleWin/AppleWin.git
synced 2024-07-06 05:28:56 +00:00
Merge from Tom branch to trunk
. Mouse interface now implemented & selectable from UI . Scroll Lock toggle also configurable from UI
This commit is contained in:
parent
9d5c56bc1c
commit
1c5ee1302b
@ -209,6 +209,14 @@
|
|||||||
Name="Source"
|
Name="Source"
|
||||||
Filter=".cpp"
|
Filter=".cpp"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\source\6821.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\source\6821.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\source\Applewin.cpp"
|
RelativePath=".\source\Applewin.cpp"
|
||||||
>
|
>
|
||||||
@ -305,6 +313,14 @@
|
|||||||
RelativePath=".\source\Mockingboard.h"
|
RelativePath=".\source\Mockingboard.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\source\MouseInterface.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\source\MouseInterface.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\source\ParallelPrinter.cpp"
|
RelativePath=".\source\ParallelPrinter.cpp"
|
||||||
>
|
>
|
||||||
@ -673,6 +689,10 @@
|
|||||||
RelativePath=".\source\Common.h"
|
RelativePath=".\source\Common.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\resource\MouseInterface.rom"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\resource\resource.h"
|
RelativePath=".\resource\resource.h"
|
||||||
>
|
>
|
||||||
|
@ -75,10 +75,10 @@ IDB_DEBUG_FONT_7X8 BITMAP "Debug_Font.bmp"
|
|||||||
// Dialog
|
// Dialog
|
||||||
//
|
//
|
||||||
|
|
||||||
IDD_PROPPAGE_CONFIG DIALOG 0, 0, 210, 221
|
IDD_PROPPAGE_CONFIG DIALOGEX 0, 0, 210, 221
|
||||||
STYLE DS_SETFONT | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_CAPTION | WS_SYSMENU
|
STYLE DS_SETFONT | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_CAPTION | WS_SYSMENU
|
||||||
CAPTION "Configuration"
|
CAPTION "Configuration"
|
||||||
FONT 8, "MS Sans Serif"
|
FONT 8, "MS Sans Serif", 0, 0, 0x0
|
||||||
BEGIN
|
BEGIN
|
||||||
GROUPBOX "Emulation Speed Control",IDC_STATIC,5,115,200,85
|
GROUPBOX "Emulation Speed Control",IDC_STATIC,5,115,200,85
|
||||||
CONTROL "Use &Authentic Machine Speed",IDC_AUTHENTIC_SPEED,
|
CONTROL "Use &Authentic Machine Speed",IDC_AUTHENTIC_SPEED,
|
||||||
@ -98,6 +98,7 @@ BEGIN
|
|||||||
COMBOBOX IDC_SERIALPORT,45,48,100,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
COMBOBOX IDC_SERIALPORT,45,48,100,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||||
PUSHBUTTON "Monochrome Color...",IDC_MONOCOLOR,15,90,80,14
|
PUSHBUTTON "Monochrome Color...",IDC_MONOCOLOR,15,90,80,14
|
||||||
PUSHBUTTON "Ethernet Settings...",IDC_ETHERNET,15,70,78,14
|
PUSHBUTTON "Ethernet Settings...",IDC_ETHERNET,15,70,78,14
|
||||||
|
CONTROL "Mouse interface in slot 4",IDC_MOUSE_IN_SLOT4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,206,106,10
|
||||||
END
|
END
|
||||||
|
|
||||||
IDD_PROPPAGE_INPUT DIALOGEX 0, 0, 210, 221
|
IDD_PROPPAGE_INPUT DIALOGEX 0, 0, 210, 221
|
||||||
@ -117,6 +118,8 @@ BEGIN
|
|||||||
LTEXT "Y-trim:",IDC_STATIC,115,72,28,8
|
LTEXT "Y-trim:",IDC_STATIC,115,72,28,8
|
||||||
CTEXT "0",IDC_STATIC,137,65,24,20,SS_CENTERIMAGE
|
CTEXT "0",IDC_STATIC,137,65,24,20,SS_CENTERIMAGE
|
||||||
CONTROL "Spin1",IDC_SPIN_YTRIM,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNLEFT | UDS_AUTOBUDDY,161,69,10,14
|
CONTROL "Spin1",IDC_SPIN_YTRIM,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNLEFT | UDS_AUTOBUDDY,161,69,10,14
|
||||||
|
CONTROL "Scroll Lock acts as toggle for full-speed CPU",IDC_SCROLLLOCK_TOGGLE,
|
||||||
|
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,9,114,166,10
|
||||||
LTEXT "(Shift+Insert during emulation)",IDC_STATIC,89,166,94,8
|
LTEXT "(Shift+Insert during emulation)",IDC_STATIC,89,166,94,8
|
||||||
END
|
END
|
||||||
|
|
||||||
@ -207,8 +210,8 @@ DISK_ICON ICON "DISK.ICO"
|
|||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,13,2,0
|
FILEVERSION 1,13,3,0
|
||||||
PRODUCTVERSION 1,13,2,0
|
PRODUCTVERSION 1,13,3,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
@ -226,12 +229,12 @@ BEGIN
|
|||||||
VALUE "Comments", "http://applewin.berlios.de"
|
VALUE "Comments", "http://applewin.berlios.de"
|
||||||
VALUE "CompanyName", "Michael O'Brien, Oliver Schmidt, Tom Charlesworth"
|
VALUE "CompanyName", "Michael O'Brien, Oliver Schmidt, Tom Charlesworth"
|
||||||
VALUE "FileDescription", "Apple //e Emulator for Windows"
|
VALUE "FileDescription", "Apple //e Emulator for Windows"
|
||||||
VALUE "FileVersion", "1, 13, 2, 0"
|
VALUE "FileVersion", "1, 13, 3, 0"
|
||||||
VALUE "InternalName", "APPLEWIN"
|
VALUE "InternalName", "APPLEWIN"
|
||||||
VALUE "LegalCopyright", "© 1994-2007 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis"
|
VALUE "LegalCopyright", "© 1994-2007 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis"
|
||||||
VALUE "OriginalFilename", "APPLEWIN.EXE"
|
VALUE "OriginalFilename", "APPLEWIN.EXE"
|
||||||
VALUE "ProductName", "Apple //e Emulator"
|
VALUE "ProductName", "Apple //e Emulator"
|
||||||
VALUE "ProductVersion", "1, 13, 2, 0"
|
VALUE "ProductVersion", "1, 13, 3, 0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
@ -263,6 +266,7 @@ IDR_SSC_FW FIRMWARE "SSC.rom"
|
|||||||
IDR_HDDRVR_FW FIRMWARE "Hddrvr.bin"
|
IDR_HDDRVR_FW FIRMWARE "Hddrvr.bin"
|
||||||
IDR_PRINTDRVR_FW FIRMWARE "Parallel.rom"
|
IDR_PRINTDRVR_FW FIRMWARE "Parallel.rom"
|
||||||
IDR_MOCKINGBOARD_D_FW FIRMWARE "Mockingboard-D.rom"
|
IDR_MOCKINGBOARD_D_FW FIRMWARE "Mockingboard-D.rom"
|
||||||
|
IDR_MOUSEINTERFACE_FW FIRMWARE "MouseInterface.rom"
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
@ -272,7 +276,7 @@ IDR_MOCKINGBOARD_D_FW FIRMWARE "Mockingboard-D.rom"
|
|||||||
IDR_APPLE2_ROM ROM "Apple2.rom"
|
IDR_APPLE2_ROM ROM "Apple2.rom"
|
||||||
IDR_APPLE2_PLUS_ROM ROM "Apple2_Plus.rom"
|
IDR_APPLE2_PLUS_ROM ROM "Apple2_Plus.rom"
|
||||||
IDR_APPLE2E_ROM ROM "Apple2e.rom"
|
IDR_APPLE2E_ROM ROM "Apple2e.rom"
|
||||||
IDR_APPLE2E_ENHANCED_ROM ROM "Apple2e_Enhanced.rom"
|
IDR_APPLE2E_ENHANCED_ROM ROM "Apple2e_Enhanced.rom"
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#define IDR_DISK2_FW 133
|
#define IDR_DISK2_FW 133
|
||||||
#define IDR_SSC_FW 134
|
#define IDR_SSC_FW 134
|
||||||
#define IDR_MOCKINGBOARD_D_FW 135
|
#define IDR_MOCKINGBOARD_D_FW 135
|
||||||
|
#define IDR_MOUSEINTERFACE_FW 136
|
||||||
#define IDC_KEYB_BUFFER_ENABLE 1005
|
#define IDC_KEYB_BUFFER_ENABLE 1005
|
||||||
#define IDC_SAVESTATE 1006
|
#define IDC_SAVESTATE 1006
|
||||||
#define IDC_SAVESTATE_ON_EXIT 1007
|
#define IDC_SAVESTATE_ON_EXIT 1007
|
||||||
@ -72,6 +73,8 @@
|
|||||||
#define IDS_OK 1040
|
#define IDS_OK 1040
|
||||||
#define IDS_CANCEL 1041
|
#define IDS_CANCEL 1041
|
||||||
#define IDC_ETHERNET 1042
|
#define IDC_ETHERNET 1042
|
||||||
|
#define IDC_SCROLLLOCK_TOGGLE 1043
|
||||||
|
#define IDC_MOUSE_IN_SLOT4 1044
|
||||||
#define IDM_EXIT 40001
|
#define IDM_EXIT 40001
|
||||||
#define IDM_HELP 40002
|
#define IDM_HELP 40002
|
||||||
#define IDM_ABOUT 40003
|
#define IDM_ABOUT 40003
|
||||||
@ -84,9 +87,9 @@
|
|||||||
#ifdef APSTUDIO_INVOKED
|
#ifdef APSTUDIO_INVOKED
|
||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
#define _APS_NO_MFC 1
|
#define _APS_NO_MFC 1
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 136
|
#define _APS_NEXT_RESOURCE_VALUE 137
|
||||||
#define _APS_NEXT_COMMAND_VALUE 40007
|
#define _APS_NEXT_COMMAND_VALUE 40007
|
||||||
#define _APS_NEXT_CONTROL_VALUE 1043
|
#define _APS_NEXT_CONTROL_VALUE 1045
|
||||||
#define _APS_NEXT_SYMED_VALUE 101
|
#define _APS_NEXT_SYMED_VALUE 101
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
531
source/6821.cpp
Normal file
531
source/6821.cpp
Normal file
@ -0,0 +1,531 @@
|
|||||||
|
// Based on MAME's 6821pia.c
|
||||||
|
// - by Kyle Kim (Apple in PC)
|
||||||
|
|
||||||
|
//
|
||||||
|
// From mame.txt (http://www.mame.net/readme.html)
|
||||||
|
//
|
||||||
|
// VI. Reuse of Source Code
|
||||||
|
// --------------------------
|
||||||
|
// This chapter might not apply to specific portions of MAME (e.g. CPU
|
||||||
|
// emulators) which bear different copyright notices.
|
||||||
|
// The source code cannot be used in a commercial product without the written
|
||||||
|
// authorization of the authors. Use in non-commercial products is allowed, and
|
||||||
|
// indeed encouraged. If you use portions of the MAME source code in your
|
||||||
|
// program, however, you must make the full source code freely available as
|
||||||
|
// well.
|
||||||
|
// Usage of the _information_ contained in the source code is free for any use.
|
||||||
|
// However, given the amount of time and energy it took to collect this
|
||||||
|
// information, if you find new information we would appreciate if you made it
|
||||||
|
// freely available as well.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "6821.h"
|
||||||
|
|
||||||
|
// Ctrl-A(B) register bit mask define
|
||||||
|
/*
|
||||||
|
0 1
|
||||||
|
bit0 IRQ1_DISABLED IRQ1_ENABLED
|
||||||
|
bit1 C1_HIGH_TO_LOW C1_LOW_TO_HIGH
|
||||||
|
bit2 DDR_SELECTED OUTPUT_SELECTED
|
||||||
|
|
||||||
|
bit3 RESET_C2 SET_C2 ( C2_OUTPUT & C2_SETMODE )
|
||||||
|
bit3 STROBE_C1_RESET STROBE_E_RESET ( C2_OUTPUT & C2_STROBE_MODE )
|
||||||
|
bit4 C2_STROBE_MODE C2_SETMODE ( C2_OUTPUT )
|
||||||
|
|
||||||
|
bit3 IRQ2_DISABLED IRQ2_ENABLED ( C2_INPUT )
|
||||||
|
bit4 C2_HIGH_TO_LOW C2_HIGH_TO_LOW ( C2_INPUT )
|
||||||
|
bit5 C2_INPUT C2_OUTPUT
|
||||||
|
*/
|
||||||
|
#define PIA_IRQ1 0x80
|
||||||
|
#define PIA_IRQ2 0x40
|
||||||
|
#define SET_IRQ1(c) c |= PIA_IRQ1;
|
||||||
|
#define SET_IRQ2(c) c |= PIA_IRQ2;
|
||||||
|
#define CLEAR_IRQ1(c) c &= ~PIA_IRQ1;
|
||||||
|
#define CLEAR_IRQ2(c) c &= ~PIA_IRQ2;
|
||||||
|
#define IRQ1(c) ( c & PIA_IRQ1 )
|
||||||
|
#define IRQ2(c) ( c & PIA_IRQ2 )
|
||||||
|
|
||||||
|
#define IRQ1_ENABLED(c) ( c & 0x01 )
|
||||||
|
#define IRQ1_DISABLED(c) !( c & 0x01 )
|
||||||
|
#define C1_LOW_TO_HIGH(c) ( c & 0x02 )
|
||||||
|
#define C1_HIGH_TO_LOW(c) !( c & 0x02 )
|
||||||
|
#define OUTPUT_SELECTED(c) ( c & 0x04 )
|
||||||
|
#define DDR_SELECTED(c) !( c & 0x04 )
|
||||||
|
#define IRQ2_ENABLED(c) ( c & 0x08 )
|
||||||
|
#define IRQ2_DISABLED(c) !( c & 0x08 )
|
||||||
|
#define STROBE_E_RESET(c) ( c & 0x08 )
|
||||||
|
#define STROBE_C1_RESET(c) !( c & 0x08 )
|
||||||
|
#define SET_C2(c) ( c & 0x08 )
|
||||||
|
#define RESET_C2(c) !( c & 0x08 )
|
||||||
|
#define C2_LOW_TO_HIGH(c) ( c & 0x10 )
|
||||||
|
#define C2_HIGH_TO_LOW(c) !( c & 0x10 )
|
||||||
|
#define C2_SET_MODE(c) ( c & 0x10 )
|
||||||
|
#define C2_STROBE_MODE(c) !( c & 0x10 )
|
||||||
|
#define C2_OUTPUT(c) ( c & 0x20 )
|
||||||
|
#define C2_INPUT(c) !( c & 0x20 )
|
||||||
|
|
||||||
|
#define PIA_W_CALLBACK(st, val) \
|
||||||
|
if ( st.func ) st.func( this, st.objTo, 0, val )
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
C6821::C6821()
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
m_stOutA.objTo = NULL;
|
||||||
|
m_stOutA.func = NULL;
|
||||||
|
m_stOutB.objTo = NULL;
|
||||||
|
m_stOutB.func = NULL;
|
||||||
|
m_stOutCA2.objTo = NULL;
|
||||||
|
m_stOutCA2.func = NULL;
|
||||||
|
m_stOutCB2.objTo = NULL;
|
||||||
|
m_stOutCB2.func = NULL;
|
||||||
|
m_stOutIRQA.objTo = NULL;
|
||||||
|
m_stOutIRQA.func = NULL;
|
||||||
|
m_stOutIRQB.objTo = NULL;
|
||||||
|
m_stOutIRQB.func = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
C6821::~C6821()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void C6821::SetListenerA(void *objTo, mem_write_handler func)
|
||||||
|
{
|
||||||
|
m_stOutA.objTo = objTo;
|
||||||
|
m_stOutA.func = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
void C6821::SetListenerB(void *objTo, mem_write_handler func)
|
||||||
|
{
|
||||||
|
m_stOutB.objTo = objTo;
|
||||||
|
m_stOutB.func = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
void C6821::SetListenerCA2(void *objTo, mem_write_handler func)
|
||||||
|
{
|
||||||
|
m_stOutCA2.objTo = objTo;
|
||||||
|
m_stOutCA2.func = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
void C6821::SetListenerCB2(void *objTo, mem_write_handler func)
|
||||||
|
{
|
||||||
|
m_stOutCB2.objTo = objTo;
|
||||||
|
m_stOutCB2.func = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
BYTE C6821::Read(BYTE byRS)
|
||||||
|
{
|
||||||
|
BYTE retval = 0;
|
||||||
|
byRS &= 3;
|
||||||
|
switch ( byRS )
|
||||||
|
{
|
||||||
|
/******************* port A output/DDR read *******************/
|
||||||
|
case PIA_DDRA:
|
||||||
|
// read output register
|
||||||
|
if ( OUTPUT_SELECTED(m_byCTLA) )
|
||||||
|
{
|
||||||
|
// combine input and output values
|
||||||
|
retval = ( m_byOA & m_byDDRA ) | ( m_byIA & ~m_byDDRA );
|
||||||
|
// IRQ flags implicitly cleared by a read
|
||||||
|
CLEAR_IRQ1( m_byCTLA );
|
||||||
|
CLEAR_IRQ1( m_byCTLB );
|
||||||
|
UpdateInterrupts();
|
||||||
|
// CA2 is configured as output and in read strobe mode
|
||||||
|
if ( C2_OUTPUT(m_byCTLA) && C2_STROBE_MODE(m_byCTLA) )
|
||||||
|
{
|
||||||
|
// this will cause a transition low; call the output function if we're currently high
|
||||||
|
if ( m_byOCA2 )
|
||||||
|
PIA_W_CALLBACK( m_stOutCA2, 0 );
|
||||||
|
m_byOCA2 = 0;
|
||||||
|
|
||||||
|
// if the CA2 strobe is cleared by the E, reset it right away
|
||||||
|
if ( STROBE_E_RESET( m_byCTLA ) )
|
||||||
|
{
|
||||||
|
PIA_W_CALLBACK( m_stOutCA2, 1 );
|
||||||
|
m_byOCA2 = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// read DDR register
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retval = m_byDDRA;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/******************* port B output/DDR read *******************/
|
||||||
|
case PIA_DDRB:
|
||||||
|
|
||||||
|
// read output register
|
||||||
|
if ( OUTPUT_SELECTED( m_byCTLB ) )
|
||||||
|
{
|
||||||
|
// combine input and output values
|
||||||
|
retval = ( m_byOB & m_byDDRB ) + ( m_byIB & ~m_byDDRB );
|
||||||
|
|
||||||
|
// IRQ flags implicitly cleared by a read
|
||||||
|
CLEAR_IRQ2( m_byCTLA );
|
||||||
|
CLEAR_IRQ2( m_byCTLB );
|
||||||
|
UpdateInterrupts();
|
||||||
|
}
|
||||||
|
/* read DDR register */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retval = m_byDDRB;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/******************* port A control read *******************/
|
||||||
|
case PIA_CTLA:
|
||||||
|
// read control register
|
||||||
|
retval = m_byCTLA;
|
||||||
|
// when CA2 is an output, IRQA2 = 0, and is not affected by CA2 transitions.
|
||||||
|
if ( C2_OUTPUT( m_byCTLA ) )
|
||||||
|
retval &= ~PIA_IRQ2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/******************* port B control read *******************/
|
||||||
|
case PIA_CTLB:
|
||||||
|
retval = m_byCTLB;
|
||||||
|
// when CB2 is an output, IRQB2 = 0, and is not affected by CB2 transitions.
|
||||||
|
if ( C2_OUTPUT( m_byCTLB ) )
|
||||||
|
retval &= ~PIA_IRQ2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void C6821::Write(BYTE byRS, BYTE byData)
|
||||||
|
{
|
||||||
|
byRS &= 3;
|
||||||
|
|
||||||
|
switch( byRS )
|
||||||
|
{
|
||||||
|
/******************* port A output/DDR write *******************/
|
||||||
|
case PIA_DDRA:
|
||||||
|
|
||||||
|
// write output register
|
||||||
|
if ( OUTPUT_SELECTED( m_byCTLA ) )
|
||||||
|
{
|
||||||
|
// update the output value
|
||||||
|
m_byOA = byData;
|
||||||
|
|
||||||
|
// send it to the output function
|
||||||
|
if ( m_byDDRA )
|
||||||
|
PIA_W_CALLBACK( m_stOutA, m_byOA & m_byDDRA );
|
||||||
|
}
|
||||||
|
|
||||||
|
// write DDR register
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( m_byDDRA != byData )
|
||||||
|
{
|
||||||
|
m_byDDRA = byData;
|
||||||
|
|
||||||
|
// send it to the output function
|
||||||
|
if ( m_byDDRA )
|
||||||
|
PIA_W_CALLBACK( m_stOutA, m_byOA & m_byDDRA );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/******************* port B output/DDR write *******************/
|
||||||
|
case PIA_DDRB:
|
||||||
|
|
||||||
|
// write output register
|
||||||
|
if ( OUTPUT_SELECTED( m_byCTLB ) )
|
||||||
|
{
|
||||||
|
// update the output value
|
||||||
|
m_byOB = byData;
|
||||||
|
|
||||||
|
// send it to the output function
|
||||||
|
if ( m_byDDRB )
|
||||||
|
PIA_W_CALLBACK( m_stOutB, m_byOB & m_byDDRB );
|
||||||
|
|
||||||
|
// CB2 is configured as output and in write strobe mode
|
||||||
|
if ( C2_OUTPUT( m_byCTLB ) && C2_STROBE_MODE( m_byCTLB ) )
|
||||||
|
{
|
||||||
|
// this will cause a transition low; call the output function if we're currently high
|
||||||
|
if ( m_byOCB2 )
|
||||||
|
PIA_W_CALLBACK( m_stOutCB2, 0 );
|
||||||
|
m_byOCB2 = 0;
|
||||||
|
|
||||||
|
// if the CB2 strobe is cleared by the E, reset it right away
|
||||||
|
if ( STROBE_E_RESET( m_byCTLB ) )
|
||||||
|
{
|
||||||
|
PIA_W_CALLBACK( m_stOutCB2, 1 );
|
||||||
|
m_byOCB2 = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// write DDR register
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( m_byDDRB != byData )
|
||||||
|
{
|
||||||
|
m_byDDRB = byData;
|
||||||
|
|
||||||
|
// send it to the output function
|
||||||
|
if ( m_byDDRB )
|
||||||
|
PIA_W_CALLBACK( m_stOutB, m_byOB & m_byDDRB );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/******************* port A control write *******************/
|
||||||
|
case PIA_CTLA:
|
||||||
|
// Bit 7 and 6 read only
|
||||||
|
byData &= 0x3f;
|
||||||
|
|
||||||
|
// CA2 is configured as output and in set/reset mode
|
||||||
|
if ( C2_OUTPUT( byData ) )
|
||||||
|
{
|
||||||
|
// determine the new value
|
||||||
|
int temp = SET_C2( byData ) ? 1 : 0;
|
||||||
|
|
||||||
|
// if this creates a transition, call the CA2 output function
|
||||||
|
if ( m_byOCA2 ^ temp)
|
||||||
|
PIA_W_CALLBACK( m_stOutCA2, temp );
|
||||||
|
|
||||||
|
// set the new value
|
||||||
|
m_byOCA2 = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the control register
|
||||||
|
m_byCTLA = ( m_byCTLA & ~0x3F ) | byData;
|
||||||
|
|
||||||
|
// update externals
|
||||||
|
UpdateInterrupts();
|
||||||
|
break;
|
||||||
|
|
||||||
|
/******************* port B control write *******************/
|
||||||
|
case PIA_CTLB:
|
||||||
|
|
||||||
|
/* Bit 7 and 6 read only - PD 16/01/00 */
|
||||||
|
|
||||||
|
byData &= 0x3f;
|
||||||
|
|
||||||
|
// CB2 is configured as output and in set/reset mode
|
||||||
|
if ( C2_OUTPUT( byData ) )
|
||||||
|
{
|
||||||
|
// determine the new value
|
||||||
|
int temp = SET_C2( byData ) ? 1 : 0;
|
||||||
|
|
||||||
|
// if this creates a transition, call the CA2 output function
|
||||||
|
if ( m_byOCB2 ^ temp)
|
||||||
|
PIA_W_CALLBACK( m_stOutCB2, temp );
|
||||||
|
|
||||||
|
// set the new value
|
||||||
|
m_byOCB2 = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the control register
|
||||||
|
m_byCTLB = ( m_byCTLB & ~0x3F ) | byData;
|
||||||
|
|
||||||
|
// update externals
|
||||||
|
UpdateInterrupts();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void C6821::Reset()
|
||||||
|
{
|
||||||
|
m_byIA = 0;
|
||||||
|
m_byCA1 = 0;
|
||||||
|
m_byICA2 = 0;
|
||||||
|
m_byOA = 0;
|
||||||
|
m_byOCA2 = 0;
|
||||||
|
m_byDDRA = 0;
|
||||||
|
m_byCTLA = 0;
|
||||||
|
m_byIRQAState = 0;
|
||||||
|
|
||||||
|
m_byIB = 0;
|
||||||
|
m_byCB1 = 0;
|
||||||
|
m_byICB2 = 0;
|
||||||
|
m_byOB = 0;
|
||||||
|
m_byOCB2 = 0;
|
||||||
|
m_byDDRB = 0;
|
||||||
|
m_byCTLB = 0;
|
||||||
|
m_byIRQBState = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void C6821::UpdateInterrupts()
|
||||||
|
{
|
||||||
|
BYTE byNewState;
|
||||||
|
|
||||||
|
// start with IRQ A
|
||||||
|
byNewState = 0;
|
||||||
|
if ( ( IRQ1( m_byCTLA ) && IRQ1_ENABLED( m_byCTLA ) ) ||
|
||||||
|
( IRQ2( m_byCTLA ) && IRQ2_ENABLED( m_byCTLA ) ) )
|
||||||
|
byNewState = 1;
|
||||||
|
|
||||||
|
if ( byNewState != m_byIRQAState )
|
||||||
|
{
|
||||||
|
m_byIRQAState = byNewState;
|
||||||
|
PIA_W_CALLBACK( m_stOutIRQA, m_byIRQAState );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* then do IRQ B */
|
||||||
|
byNewState = 0;
|
||||||
|
if ( ( IRQ1( m_byCTLB ) && IRQ1_ENABLED( m_byCTLB ) ) ||
|
||||||
|
( IRQ2( m_byCTLB ) && IRQ2_ENABLED( m_byCTLB ) ) )
|
||||||
|
byNewState = 1;
|
||||||
|
|
||||||
|
if ( byNewState != m_byIRQBState )
|
||||||
|
{
|
||||||
|
m_byIRQBState = byNewState;
|
||||||
|
PIA_W_CALLBACK( m_stOutIRQB, m_byIRQBState );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void C6821::SetCA1(BYTE byData)
|
||||||
|
{
|
||||||
|
byData = byData ? 1 : 0;
|
||||||
|
|
||||||
|
// the new state has caused a transition
|
||||||
|
if ( m_byCA1 ^ byData )
|
||||||
|
{
|
||||||
|
// handle the active transition
|
||||||
|
if ( ( byData && C1_LOW_TO_HIGH( m_byCTLA ) ) ||
|
||||||
|
( !byData && C1_HIGH_TO_LOW( m_byCTLA ) ) )
|
||||||
|
{
|
||||||
|
// mark the IRQ
|
||||||
|
SET_IRQ1(m_byCTLA);
|
||||||
|
|
||||||
|
// update externals
|
||||||
|
UpdateInterrupts();
|
||||||
|
|
||||||
|
// CA2 is configured as output and in read strobe mode and cleared by a CA1 transition
|
||||||
|
if ( C2_OUTPUT( m_byCTLA ) && C2_STROBE_MODE( m_byCTLA ) && STROBE_C1_RESET( m_byCTLA ) )
|
||||||
|
{
|
||||||
|
// call the CA2 output function
|
||||||
|
if ( !m_byOCA2 )
|
||||||
|
PIA_W_CALLBACK( m_stOutCA2, 1 );
|
||||||
|
|
||||||
|
// clear CA2
|
||||||
|
m_byOCA2 = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the new value for CA1
|
||||||
|
m_byCA1 = byData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void C6821::SetCA2(BYTE byData)
|
||||||
|
{
|
||||||
|
byData = byData ? 1 : 0;
|
||||||
|
|
||||||
|
// CA2 is in input mode
|
||||||
|
if ( C2_INPUT( m_byCTLA ) )
|
||||||
|
{
|
||||||
|
// the new state has caused a transition
|
||||||
|
if ( m_byICA2 ^ byData )
|
||||||
|
{
|
||||||
|
// handle the active transition
|
||||||
|
if ( ( byData && C2_LOW_TO_HIGH( m_byCTLA ) ) ||
|
||||||
|
( !byData && C2_HIGH_TO_LOW( m_byCTLA ) ) )
|
||||||
|
{
|
||||||
|
// mark the IRQ
|
||||||
|
SET_IRQ2( m_byCTLA );
|
||||||
|
|
||||||
|
// update externals
|
||||||
|
UpdateInterrupts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the new value for CA2
|
||||||
|
m_byICA2 = byData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void C6821::SetCB1(BYTE byData)
|
||||||
|
{
|
||||||
|
byData = byData ? 1 : 0;
|
||||||
|
|
||||||
|
// the new state has caused a transition
|
||||||
|
if ( m_byCB1 ^ byData )
|
||||||
|
{
|
||||||
|
// handle the active transition
|
||||||
|
if ( ( byData && C1_LOW_TO_HIGH( m_byCTLB ) ) ||
|
||||||
|
( !byData && C1_HIGH_TO_LOW( m_byCTLB ) ) )
|
||||||
|
{
|
||||||
|
// mark the IRQ
|
||||||
|
SET_IRQ1( m_byCTLB );
|
||||||
|
|
||||||
|
// update externals
|
||||||
|
UpdateInterrupts();
|
||||||
|
|
||||||
|
// CB2 is configured as output and in read strobe mode and cleared by a CA1 transition
|
||||||
|
if ( C2_OUTPUT( m_byCTLB ) && C2_STROBE_MODE( m_byCTLB ) && STROBE_C1_RESET( m_byCTLB ) )
|
||||||
|
{
|
||||||
|
// the IRQ1 flag must have also been cleared
|
||||||
|
if ( !IRQ1( m_byCTLB ) )
|
||||||
|
{
|
||||||
|
// call the CB2 output function
|
||||||
|
if ( !m_byOCB2 )
|
||||||
|
PIA_W_CALLBACK( m_stOutCB2, 1 );
|
||||||
|
|
||||||
|
// clear CB2
|
||||||
|
m_byOCB2 = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the new value for CA1
|
||||||
|
m_byCB1 = byData;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void C6821::SetCB2(BYTE byData)
|
||||||
|
{
|
||||||
|
byData = byData ? 1 : 0;
|
||||||
|
|
||||||
|
// CA2 is in input mode
|
||||||
|
if ( C2_INPUT( m_byCTLB ) )
|
||||||
|
{
|
||||||
|
// the new state has caused a transition
|
||||||
|
if ( m_byICB2 ^ byData )
|
||||||
|
{
|
||||||
|
// handle the active transition
|
||||||
|
if ( ( byData && C2_LOW_TO_HIGH( m_byCTLB ) ) ||
|
||||||
|
( !byData && C2_HIGH_TO_LOW( m_byCTLB ) ) )
|
||||||
|
{
|
||||||
|
// mark the IRQ
|
||||||
|
SET_IRQ2( m_byCTLB );
|
||||||
|
|
||||||
|
// update externals
|
||||||
|
UpdateInterrupts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the new value for CA2
|
||||||
|
m_byICB2 = byData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void C6821::SetPA(BYTE byData)
|
||||||
|
{
|
||||||
|
m_byIA = byData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void C6821::SetPB(BYTE byData)
|
||||||
|
{
|
||||||
|
m_byIB = byData;
|
||||||
|
}
|
||||||
|
|
||||||
|
BYTE C6821::GetPA()
|
||||||
|
{
|
||||||
|
return m_byOA & m_byDDRA;
|
||||||
|
}
|
||||||
|
|
||||||
|
BYTE C6821::GetPB()
|
||||||
|
{
|
||||||
|
return m_byOB & m_byDDRB;
|
||||||
|
}
|
68
source/6821.h
Normal file
68
source/6821.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// Motorola MC6821 PIA
|
||||||
|
|
||||||
|
typedef void (*mem_write_handler) (void* objFrom, void* objTo, int nAddr, BYTE byData);
|
||||||
|
|
||||||
|
typedef struct _STWriteHandler
|
||||||
|
{
|
||||||
|
void* objTo;
|
||||||
|
mem_write_handler func;
|
||||||
|
} STWriteHandler;
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
#define PIA_DDRA 0
|
||||||
|
#define PIA_CTLA 1
|
||||||
|
#define PIA_DDRB 2
|
||||||
|
#define PIA_CTLB 3
|
||||||
|
|
||||||
|
class C6821
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
C6821();
|
||||||
|
virtual ~C6821();
|
||||||
|
|
||||||
|
BYTE GetPB();
|
||||||
|
BYTE GetPA();
|
||||||
|
void SetPB(BYTE byData);
|
||||||
|
void SetPA(BYTE byData);
|
||||||
|
void SetCA1( BYTE byData );
|
||||||
|
void SetCA2( BYTE byData );
|
||||||
|
void SetCB1( BYTE byData );
|
||||||
|
void SetCB2( BYTE byData );
|
||||||
|
void Reset();
|
||||||
|
BYTE Read( BYTE byRS );
|
||||||
|
void Write( BYTE byRS, BYTE byData );
|
||||||
|
|
||||||
|
void UpdateInterrupts();
|
||||||
|
|
||||||
|
void SetListenerA( void *objTo, mem_write_handler func );
|
||||||
|
void SetListenerB( void *objTo, mem_write_handler func );
|
||||||
|
void SetListenerCA2( void *objTo, mem_write_handler func );
|
||||||
|
void SetListenerCB2( void *objTo, mem_write_handler func );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
BYTE m_byIA;
|
||||||
|
BYTE m_byCA1;
|
||||||
|
BYTE m_byICA2;
|
||||||
|
BYTE m_byOA;
|
||||||
|
BYTE m_byOCA2;
|
||||||
|
BYTE m_byDDRA;
|
||||||
|
BYTE m_byCTLA;
|
||||||
|
BYTE m_byIRQAState;
|
||||||
|
|
||||||
|
BYTE m_byIB;
|
||||||
|
BYTE m_byCB1;
|
||||||
|
BYTE m_byICB2;
|
||||||
|
BYTE m_byOB;
|
||||||
|
BYTE m_byOCB2;
|
||||||
|
BYTE m_byDDRB;
|
||||||
|
BYTE m_byCTLB;
|
||||||
|
BYTE m_byIRQBState;
|
||||||
|
|
||||||
|
STWriteHandler m_stOutA;
|
||||||
|
STWriteHandler m_stOutB;
|
||||||
|
STWriteHandler m_stOutCA2;
|
||||||
|
STWriteHandler m_stOutCB2;
|
||||||
|
STWriteHandler m_stOutIRQA;
|
||||||
|
STWriteHandler m_stOutIRQB;
|
||||||
|
};
|
@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
#pragma hdrstop
|
#pragma hdrstop
|
||||||
|
#include "MouseInterface.h"
|
||||||
|
|
||||||
char VERSIONSTRING[] = "xx.yy.zz.ww";
|
char VERSIONSTRING[] = "xx.yy.zz.ww";
|
||||||
|
|
||||||
@ -64,7 +65,10 @@ DWORD g_dwCyclesThisFrame = 0;
|
|||||||
FILE* g_fh = NULL;
|
FILE* g_fh = NULL;
|
||||||
bool g_bDisableDirectSound = false;
|
bool g_bDisableDirectSound = false;
|
||||||
|
|
||||||
CSuperSerialCard sg_SSC;
|
CSuperSerialCard sg_SSC;
|
||||||
|
CMouseInterface sg_Mouse;
|
||||||
|
|
||||||
|
UINT g_Slot4 = CT_Mockingboard; // CT_Mockingboard or CT_MouseInterface
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
@ -95,8 +99,12 @@ void ContinueExecution()
|
|||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
bool bScrollLock_FullSpeed = g_uScrollLockToggle
|
||||||
|
? g_bScrollLock_FullSpeed
|
||||||
|
: (GetKeyState(VK_SCROLL) < 0);
|
||||||
|
|
||||||
g_bFullSpeed = ( (g_dwSpeed == SPEED_MAX) ||
|
g_bFullSpeed = ( (g_dwSpeed == SPEED_MAX) ||
|
||||||
(GetKeyState(VK_SCROLL) < 0) ||
|
bScrollLock_FullSpeed ||
|
||||||
(DiskIsSpinning() && enhancedisk && !Spkr_IsActive() && !MB_IsActive()) );
|
(DiskIsSpinning() && enhancedisk && !Spkr_IsActive() && !MB_IsActive()) );
|
||||||
|
|
||||||
if(g_bFullSpeed)
|
if(g_bFullSpeed)
|
||||||
@ -198,7 +206,7 @@ void ContinueExecution()
|
|||||||
pageflipping--;
|
pageflipping--;
|
||||||
}
|
}
|
||||||
|
|
||||||
MB_EndOfFrame();
|
MB_EndOfVideoFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -390,6 +398,10 @@ void LoadConfiguration ()
|
|||||||
|
|
||||||
DWORD dwTmp;
|
DWORD dwTmp;
|
||||||
|
|
||||||
|
if(LOAD(TEXT(REGVALUE_MOUSE_IN_SLOT4), &dwTmp))
|
||||||
|
g_uMouseInSlot4 = dwTmp;
|
||||||
|
g_Slot4 = g_uMouseInSlot4 ? CT_MouseInterface : CT_Mockingboard;
|
||||||
|
|
||||||
if(LOAD(TEXT(REGVALUE_SPKR_VOLUME), &dwTmp))
|
if(LOAD(TEXT(REGVALUE_SPKR_VOLUME), &dwTmp))
|
||||||
SpkrSetVolume(dwTmp, PSP_GetVolumeMax());
|
SpkrSetVolume(dwTmp, PSP_GetVolumeMax());
|
||||||
|
|
||||||
@ -416,6 +428,9 @@ void LoadConfiguration ()
|
|||||||
if(LOAD(TEXT(REGVALUE_PDL_YTRIM), &dwTmp))
|
if(LOAD(TEXT(REGVALUE_PDL_YTRIM), &dwTmp))
|
||||||
JoySetTrim((short)dwTmp, false);
|
JoySetTrim((short)dwTmp, false);
|
||||||
|
|
||||||
|
if(LOAD(TEXT(REGVALUE_SCROLLLOCK_TOGGLE), &dwTmp))
|
||||||
|
g_uScrollLockToggle = dwTmp;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
char szFilename[MAX_PATH] = {0};
|
char szFilename[MAX_PATH] = {0};
|
||||||
@ -706,7 +721,9 @@ int APIENTRY WinMain (HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
|
|||||||
|
|
||||||
// ENTER THE MAIN MESSAGE LOOP
|
// ENTER THE MAIN MESSAGE LOOP
|
||||||
EnterMessageLoop();
|
EnterMessageLoop();
|
||||||
|
|
||||||
MB_Reset();
|
MB_Reset();
|
||||||
|
sg_Mouse.Uninitialize(); // Maybe restarting due to switching slot-4 card from mouse to MB
|
||||||
}
|
}
|
||||||
while (restart);
|
while (restart);
|
||||||
|
|
||||||
|
@ -33,4 +33,6 @@ extern DWORD g_dwCyclesThisFrame;
|
|||||||
extern FILE* g_fh; // Filehandle for log file
|
extern FILE* g_fh; // Filehandle for log file
|
||||||
extern bool g_bDisableDirectSound; // Cmd line switch: don't init DS (so no MB support)
|
extern bool g_bDisableDirectSound; // Cmd line switch: don't init DS (so no MB support)
|
||||||
|
|
||||||
|
extern UINT g_Slot4; // Mockingboard or Mouse in slot4
|
||||||
|
|
||||||
void SetCurrentCLK6502();
|
void SetCurrentCLK6502();
|
||||||
|
199
source/CPU.cpp
199
source/CPU.cpp
@ -86,6 +86,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
#pragma hdrstop
|
#pragma hdrstop
|
||||||
|
#include "MouseInterface.h"
|
||||||
|
|
||||||
#define AF_SIGN 0x80
|
#define AF_SIGN 0x80
|
||||||
#define AF_OVERFLOW 0x40
|
#define AF_OVERFLOW 0x40
|
||||||
@ -112,7 +113,11 @@ unsigned __int64 g_nCumulativeCycles = 0;
|
|||||||
static ULONG g_nCyclesSubmitted; // Number of cycles submitted to CpuExecute()
|
static ULONG g_nCyclesSubmitted; // Number of cycles submitted to CpuExecute()
|
||||||
static ULONG g_nCyclesExecuted;
|
static ULONG g_nCyclesExecuted;
|
||||||
|
|
||||||
static signed long g_uInternalExecutedCycles;
|
//static signed long g_uInternalExecutedCycles;
|
||||||
|
// TODO: Use IRQ_CHECK_TIMEOUT=128 when running at full-speed else with IRQ_CHECK_TIMEOUT=1
|
||||||
|
// - What about when running benchmark?
|
||||||
|
static const int IRQ_CHECK_TIMEOUT = 128;
|
||||||
|
static signed int g_nIrqCheckTimeout = IRQ_CHECK_TIMEOUT;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
@ -143,7 +148,7 @@ static volatile BOOL g_bNmiFlank = FALSE; // Positive going flank on NMI line
|
|||||||
| (flagz ? AF_ZERO : 0) \
|
| (flagz ? AF_ZERO : 0) \
|
||||||
| AF_RESERVED | AF_BREAK;
|
| AF_RESERVED | AF_BREAK;
|
||||||
// CYC(a): This can be optimised, as only certain opcodes will affect uExtraCycles
|
// CYC(a): This can be optimised, as only certain opcodes will affect uExtraCycles
|
||||||
#define CYC(a) uExecutedCycles += (a)+uExtraCycles; MB_UpdateCycles((a)+uExtraCycles);
|
#define CYC(a) uExecutedCycles += (a)+uExtraCycles; g_nIrqCheckTimeout -= (a)+uExtraCycles;
|
||||||
#define POP (*(mem+((regs.sp >= 0x1FF) ? (regs.sp = 0x100) : ++regs.sp)))
|
#define POP (*(mem+((regs.sp >= 0x1FF) ? (regs.sp = 0x100) : ++regs.sp)))
|
||||||
#define PUSH(a) *(mem+regs.sp--) = (a); \
|
#define PUSH(a) *(mem+regs.sp--) = (a); \
|
||||||
if (regs.sp < 0x100) \
|
if (regs.sp < 0x100) \
|
||||||
@ -227,6 +232,10 @@ static volatile BOOL g_bNmiFlank = FALSE; // Positive going flank on NMI line
|
|||||||
else \
|
else \
|
||||||
addr = *(LPWORD)(mem+base);
|
addr = *(LPWORD)(mem+base);
|
||||||
#define REL addr = (signed char)*(mem+regs.pc++);
|
#define REL addr = (signed char)*(mem+regs.pc++);
|
||||||
|
|
||||||
|
// Optimiation note:
|
||||||
|
// . Opcodes that generate zero-page addresses can't be accessing $C000..$CFFF
|
||||||
|
// so they could be paired with special READZP/WRITEZP macros (instead of READ/WRITE)
|
||||||
#define ZPG addr = *(mem+regs.pc++);
|
#define ZPG addr = *(mem+regs.pc++);
|
||||||
#define ZPGX addr = ((*(mem+regs.pc++))+regs.x) & 0xFF;
|
#define ZPGX addr = ((*(mem+regs.pc++))+regs.x) & 0xFF;
|
||||||
#define ZPGY addr = ((*(mem+regs.pc++))+regs.y) & 0xFF;
|
#define ZPGY addr = ((*(mem+regs.pc++))+regs.y) & 0xFF;
|
||||||
@ -783,7 +792,7 @@ UINT g_nMean = 0;
|
|||||||
UINT g_nMin = 0xFFFFFFFF;
|
UINT g_nMin = 0xFFFFFFFF;
|
||||||
UINT g_nMax = 0;
|
UINT g_nMax = 0;
|
||||||
|
|
||||||
static inline void DoIrqProfiling(DWORD uCycles)
|
static __forceinline void DoIrqProfiling(DWORD uCycles)
|
||||||
{
|
{
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
if(regs.ps & AF_INTERRUPT)
|
if(regs.ps & AF_INTERRUPT)
|
||||||
@ -814,8 +823,75 @@ static inline void DoIrqProfiling(DWORD uCycles)
|
|||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
|
static __forceinline int Fetch(BYTE& iOpcode, ULONG uExecutedCycles)
|
||||||
|
{
|
||||||
|
//g_uInternalExecutedCycles = uExecutedCycles;
|
||||||
|
|
||||||
|
// iOpcode = *(mem+regs.pc);
|
||||||
|
iOpcode = ((regs.pc & 0xF000) == 0xC000)
|
||||||
|
? IORead[(regs.pc>>4) & 0xFF](regs.pc,regs.pc,0,0,uExecutedCycles) // Fetch opcode from I/O memory, but params are still from mem[]
|
||||||
|
: *(mem+regs.pc);
|
||||||
|
|
||||||
|
if (CheckDebugBreak( iOpcode ))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
regs.pc++;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//#define ENABLE_NMI_SUPPORT // Not used - so don't enable
|
||||||
|
static __forceinline void NMI(ULONG& uExecutedCycles, UINT& uExtraCycles, BOOL& flagc, BOOL& flagn, BOOL& flagv, BOOL& flagz)
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_NMI_SUPPORT
|
||||||
|
if(g_bNmiFlank)
|
||||||
|
{
|
||||||
|
// NMI signals are only serviced once
|
||||||
|
g_bNmiFlank = FALSE;
|
||||||
|
g_nCycleIrqStart = g_nCumulativeCycles + uExecutedCycles;
|
||||||
|
PUSH(regs.pc >> 8)
|
||||||
|
PUSH(regs.pc & 0xFF)
|
||||||
|
EF_TO_AF
|
||||||
|
PUSH(regs.ps & ~AF_BREAK)
|
||||||
|
regs.ps = regs.ps | AF_INTERRUPT & ~AF_DECIMAL;
|
||||||
|
regs.pc = * (WORD*) (mem+0xFFFA);
|
||||||
|
CYC(7)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static __forceinline void IRQ(ULONG& uExecutedCycles, UINT& uExtraCycles, BOOL& flagc, BOOL& flagn, BOOL& flagv, BOOL& flagz)
|
||||||
|
{
|
||||||
|
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 + uExecutedCycles;
|
||||||
|
PUSH(regs.pc >> 8)
|
||||||
|
PUSH(regs.pc & 0xFF)
|
||||||
|
EF_TO_AF
|
||||||
|
PUSH(regs.ps & ~AF_BREAK)
|
||||||
|
regs.ps = regs.ps | AF_INTERRUPT & ~AF_DECIMAL;
|
||||||
|
regs.pc = * (WORD*) (mem+0xFFFE);
|
||||||
|
CYC(7)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static __forceinline void CheckInterruptSources(ULONG uExecutedCycles)
|
||||||
|
{
|
||||||
|
if (g_nIrqCheckTimeout < 0)
|
||||||
|
{
|
||||||
|
MB_UpdateCycles(uExecutedCycles);
|
||||||
|
sg_Mouse.SetVBlank(VideoGetVbl(uExecutedCycles));
|
||||||
|
g_nIrqCheckTimeout = IRQ_CHECK_TIMEOUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
static DWORD Cpu65C02 (DWORD uTotalCycles)
|
static DWORD Cpu65C02 (DWORD uTotalCycles)
|
||||||
{
|
{
|
||||||
|
// Optimisation:
|
||||||
|
// . Copy the global /regs/ vars to stack-based local vars
|
||||||
|
// (Oliver Schmidt says this gives a performance gain, see email - The real deal: "1.10.5")
|
||||||
WORD addr;
|
WORD addr;
|
||||||
BOOL flagc; // must always be 0 or 1, no other values allowed
|
BOOL flagc; // must always be 0 or 1, no other values allowed
|
||||||
BOOL flagn; // must always be 0 or 0x80.
|
BOOL flagn; // must always be 0 or 0x80.
|
||||||
@ -825,26 +901,19 @@ static DWORD Cpu65C02 (DWORD uTotalCycles)
|
|||||||
WORD temp2;
|
WORD temp2;
|
||||||
WORD val;
|
WORD val;
|
||||||
AF_TO_EF
|
AF_TO_EF
|
||||||
DWORD uExecutedCycles = 0;
|
ULONG uExecutedCycles = 0;
|
||||||
BOOL bSlowerOnPagecross; // Set if opcode writes to memory (eg. ASL, STA)
|
BOOL bSlowerOnPagecross; // Set if opcode writes to memory (eg. ASL, STA)
|
||||||
WORD base;
|
WORD base;
|
||||||
bool bBreakOnInvalid = false;
|
bool bBreakOnInvalid = false;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
g_uInternalExecutedCycles = uExecutedCycles;
|
UINT uExtraCycles = 0;
|
||||||
USHORT uExtraCycles = 0;
|
BYTE iOpcode;
|
||||||
|
|
||||||
// BYTE iOpcode = *(mem+regs.pc);
|
if (!Fetch(iOpcode, uExecutedCycles))
|
||||||
BYTE iOpcode = ((regs.pc & 0xF000) == 0xC000)
|
|
||||||
? IORead[(regs.pc>>4) & 0xFF](regs.pc,regs.pc,0,0,uExecutedCycles) // Fetch opcode from I/O memory, but params are still from mem[]
|
|
||||||
: *(mem+regs.pc);
|
|
||||||
|
|
||||||
if (CheckDebugBreak( iOpcode ))
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
regs.pc++;
|
|
||||||
|
|
||||||
switch (iOpcode)
|
switch (iOpcode)
|
||||||
{
|
{
|
||||||
case 0x00: BRK CYC(7) break;
|
case 0x00: BRK CYC(7) break;
|
||||||
@ -1105,32 +1174,10 @@ static DWORD Cpu65C02 (DWORD uTotalCycles)
|
|||||||
case 0xFF: INV NOP CYC(2) break;
|
case 0xFF: INV NOP CYC(2) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(g_bNmiFlank)
|
|
||||||
{
|
|
||||||
// NMI signals are only serviced once
|
|
||||||
g_bNmiFlank = FALSE;
|
|
||||||
g_nCycleIrqStart = g_nCumulativeCycles + uExecutedCycles;
|
|
||||||
PUSH(regs.pc >> 8)
|
|
||||||
PUSH(regs.pc & 0xFF)
|
|
||||||
EF_TO_AF
|
|
||||||
PUSH(regs.ps & ~AF_BREAK)
|
|
||||||
regs.ps = regs.ps | AF_INTERRUPT & ~AF_DECIMAL;
|
|
||||||
regs.pc = * (WORD*) (mem+0xFFFA);
|
|
||||||
CYC(7)
|
|
||||||
}
|
|
||||||
|
|
||||||
if(g_bmIRQ && !(regs.ps & AF_INTERRUPT))
|
CheckInterruptSources(uExecutedCycles);
|
||||||
{
|
NMI(uExecutedCycles, uExtraCycles, flagc, flagn, flagv, flagz);
|
||||||
// IRQ signals are deasserted when a specific r/w operation is done on device
|
IRQ(uExecutedCycles, uExtraCycles, flagc, flagn, flagv, flagz);
|
||||||
g_nCycleIrqStart = g_nCumulativeCycles + uExecutedCycles;
|
|
||||||
PUSH(regs.pc >> 8)
|
|
||||||
PUSH(regs.pc & 0xFF)
|
|
||||||
EF_TO_AF
|
|
||||||
PUSH(regs.ps & ~AF_BREAK)
|
|
||||||
regs.ps = regs.ps | AF_INTERRUPT & ~AF_DECIMAL;
|
|
||||||
regs.pc = * (WORD*) (mem+0xFFFE);
|
|
||||||
CYC(7)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bBreakOnInvalid)
|
if (bBreakOnInvalid)
|
||||||
break;
|
break;
|
||||||
@ -1154,26 +1201,19 @@ static DWORD Cpu6502 (DWORD uTotalCycles)
|
|||||||
WORD temp2;
|
WORD temp2;
|
||||||
WORD val;
|
WORD val;
|
||||||
AF_TO_EF
|
AF_TO_EF
|
||||||
DWORD uExecutedCycles = 0;
|
ULONG uExecutedCycles = 0;
|
||||||
BOOL bSlowerOnPagecross; // Set if opcode writes to memory (eg. ASL, STA)
|
BOOL bSlowerOnPagecross; // Set if opcode writes to memory (eg. ASL, STA)
|
||||||
WORD base;
|
WORD base;
|
||||||
bool bBreakOnInvalid = false;
|
bool bBreakOnInvalid = false;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
g_uInternalExecutedCycles = uExecutedCycles;
|
UINT uExtraCycles = 0;
|
||||||
USHORT uExtraCycles = 0;
|
BYTE iOpcode;
|
||||||
|
|
||||||
// BYTE iOpcode = *(mem+regs.pc);
|
if (!Fetch(iOpcode, uExecutedCycles))
|
||||||
BYTE iOpcode = ((regs.pc & 0xF000) == 0xC000)
|
|
||||||
? IORead[(regs.pc>>4) & 0xFF](regs.pc,regs.pc,0,0,uExecutedCycles)
|
|
||||||
: *(mem+regs.pc);
|
|
||||||
|
|
||||||
if (CheckDebugBreak( iOpcode ))
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
regs.pc++;
|
|
||||||
|
|
||||||
switch (iOpcode)
|
switch (iOpcode)
|
||||||
{
|
{
|
||||||
case 0x00: BRK CYC(7) break;
|
case 0x00: BRK CYC(7) break;
|
||||||
@ -1434,32 +1474,9 @@ static DWORD Cpu6502 (DWORD uTotalCycles)
|
|||||||
case 0xFF: INV ABSX INS CYC(7) break;
|
case 0xFF: INV ABSX INS CYC(7) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(g_bNmiFlank && !regs.bJammed)
|
CheckInterruptSources(uExecutedCycles);
|
||||||
{
|
NMI(uExecutedCycles, uExtraCycles, flagc, flagn, flagv, flagz);
|
||||||
// NMI signals are only serviced once
|
IRQ(uExecutedCycles, uExtraCycles, flagc, flagn, flagv, flagz);
|
||||||
g_bNmiFlank = FALSE;
|
|
||||||
g_nCycleIrqStart = g_nCumulativeCycles + uExecutedCycles;
|
|
||||||
PUSH(regs.pc >> 8)
|
|
||||||
PUSH(regs.pc & 0xFF)
|
|
||||||
EF_TO_AF
|
|
||||||
PUSH(regs.ps & ~AF_BREAK)
|
|
||||||
regs.ps = regs.ps | AF_INTERRUPT;
|
|
||||||
regs.pc = * (WORD*) (mem+0xFFFA);
|
|
||||||
CYC(7)
|
|
||||||
}
|
|
||||||
|
|
||||||
if(g_bmIRQ && !(regs.ps & AF_INTERRUPT) && !regs.bJammed)
|
|
||||||
{
|
|
||||||
// IRQ signals are deasserted when a specific r/w operation is done on device
|
|
||||||
g_nCycleIrqStart = g_nCumulativeCycles + uExecutedCycles;
|
|
||||||
PUSH(regs.pc >> 8)
|
|
||||||
PUSH(regs.pc & 0xFF)
|
|
||||||
EF_TO_AF
|
|
||||||
PUSH(regs.ps & ~AF_BREAK)
|
|
||||||
regs.ps = regs.ps | AF_INTERRUPT;
|
|
||||||
regs.pc = * (WORD*) (mem+0xFFFE);
|
|
||||||
CYC(7)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bBreakOnInvalid)
|
if (bBreakOnInvalid)
|
||||||
break;
|
break;
|
||||||
@ -1502,10 +1519,11 @@ void CpuDestroy ()
|
|||||||
// g_nCyclesExecuted
|
// g_nCyclesExecuted
|
||||||
// g_nCumulativeCycles
|
// g_nCumulativeCycles
|
||||||
//
|
//
|
||||||
void CpuCalcCycles(ULONG nCyclesExecuted)
|
void CpuCalcCycles(ULONG nExecutedCycles)
|
||||||
{
|
{
|
||||||
// Calc # of cycles executed since this func was last called
|
// Calc # of cycles executed since this func was last called
|
||||||
ULONG nCycles = nCyclesExecuted - g_nCyclesExecuted;
|
ULONG nCycles = nExecutedCycles - g_nCyclesExecuted;
|
||||||
|
_ASSERT( (LONG)nCycles >= 0 );
|
||||||
|
|
||||||
g_nCyclesExecuted += nCycles;
|
g_nCyclesExecuted += nCycles;
|
||||||
g_nCumulativeCycles += nCycles;
|
g_nCumulativeCycles += nCycles;
|
||||||
@ -1513,11 +1531,26 @@ void CpuCalcCycles(ULONG nCyclesExecuted)
|
|||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
ULONG CpuGetCyclesThisFrame()
|
// Old method with g_uInternalExecutedCycles runs faster!
|
||||||
|
// Old vs New
|
||||||
|
// - 68.0,69.0MHz vs 66.7, 67.2MHz (with check for VBL IRQ every opcode)
|
||||||
|
// - 89.6,88.9MHz vs 87.2, 87.9MHz (without check for VBL IRQ)
|
||||||
|
// - 75.9, 78.5MHz (with check for VBL IRQ every 128 cycles)
|
||||||
|
// - 137.9,135.6MHz (with check for VBL IRQ & MB_Update every 128 cycles)
|
||||||
|
|
||||||
|
#if 0 // TODO: Measure perf increase by using this new method
|
||||||
|
ULONG CpuGetCyclesThisFrame(ULONG) // Old func using g_uInternalExecutedCycles
|
||||||
{
|
{
|
||||||
CpuCalcCycles(g_uInternalExecutedCycles);
|
CpuCalcCycles(g_uInternalExecutedCycles);
|
||||||
return g_dwCyclesThisFrame + g_nCyclesExecuted;
|
return g_dwCyclesThisFrame + g_nCyclesExecuted;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
ULONG CpuGetCyclesThisFrame(ULONG nExecutedCycles)
|
||||||
|
{
|
||||||
|
CpuCalcCycles(nExecutedCycles);
|
||||||
|
return g_dwCyclesThisFrame + g_nCyclesExecuted;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
@ -1528,11 +1561,19 @@ DWORD CpuExecute (DWORD uCycles)
|
|||||||
g_nCyclesSubmitted = uCycles;
|
g_nCyclesSubmitted = uCycles;
|
||||||
g_nCyclesExecuted = 0;
|
g_nCyclesExecuted = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
MB_StartOfCpuExecute();
|
||||||
|
|
||||||
if (uCycles == 0) // Do single step
|
if (uCycles == 0) // Do single step
|
||||||
uExecutedCycles = InternalCpuExecute(0);
|
uExecutedCycles = InternalCpuExecute(0);
|
||||||
else // Do multi-opcode emulation
|
else // Do multi-opcode emulation
|
||||||
uExecutedCycles = InternalCpuExecute(uCycles);
|
uExecutedCycles = InternalCpuExecute(uCycles);
|
||||||
|
|
||||||
|
MB_UpdateCycles(uExecutedCycles); // Update 6522s (NB. Do this before updating g_nCumulativeCycles below)
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
UINT nRemainingCycles = uExecutedCycles - g_nCyclesExecuted;
|
UINT nRemainingCycles = uExecutedCycles - g_nCyclesExecuted;
|
||||||
g_nCumulativeCycles += nRemainingCycles;
|
g_nCumulativeCycles += nRemainingCycles;
|
||||||
|
|
||||||
|
@ -14,9 +14,9 @@ extern regsrec regs;
|
|||||||
extern unsigned __int64 g_nCumulativeCycles;
|
extern unsigned __int64 g_nCumulativeCycles;
|
||||||
|
|
||||||
void CpuDestroy ();
|
void CpuDestroy ();
|
||||||
void CpuCalcCycles(ULONG nCyclesLeft);
|
void CpuCalcCycles(ULONG nExecutedCycles);
|
||||||
DWORD CpuExecute (DWORD);
|
DWORD CpuExecute (DWORD);
|
||||||
ULONG CpuGetCyclesThisFrame();
|
ULONG CpuGetCyclesThisFrame(ULONG nExecutedCycles);
|
||||||
void CpuInitialize ();
|
void CpuInitialize ();
|
||||||
void CpuSetupBenchmark ();
|
void CpuSetupBenchmark ();
|
||||||
void CpuIrqReset();
|
void CpuIrqReset();
|
||||||
|
@ -80,6 +80,8 @@ enum AppMode_e
|
|||||||
#define REGVALUE_HDD_IMAGE2 "Harddisk Image 2"
|
#define REGVALUE_HDD_IMAGE2 "Harddisk Image 2"
|
||||||
#define REGVALUE_PDL_XTRIM "PDL X-Trim"
|
#define REGVALUE_PDL_XTRIM "PDL X-Trim"
|
||||||
#define REGVALUE_PDL_YTRIM "PDL Y-Trim"
|
#define REGVALUE_PDL_YTRIM "PDL Y-Trim"
|
||||||
|
#define REGVALUE_SCROLLLOCK_TOGGLE "ScrollLock Toggle"
|
||||||
|
#define REGVALUE_MOUSE_IN_SLOT4 "Mouse in slot 4"
|
||||||
|
|
||||||
// Preferences
|
// Preferences
|
||||||
#define REGVALUE_PREF_START_DIR TEXT("Starting Directory")
|
#define REGVALUE_PREF_START_DIR TEXT("Starting Directory")
|
||||||
@ -95,7 +97,7 @@ typedef BYTE (__stdcall *iofunction)(WORD nPC, WORD nAddr, BYTE nWriteFlag, BYTE
|
|||||||
|
|
||||||
typedef struct _IMAGE__ { int unused; } *HIMAGE;
|
typedef struct _IMAGE__ { int unused; } *HIMAGE;
|
||||||
|
|
||||||
enum eIRQSRC {IS_6522=0, IS_SPEECH, IS_SSC};
|
enum eIRQSRC {IS_6522=0, IS_SPEECH, IS_SSC, IS_MOUSE};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
@ -115,3 +117,6 @@ enum eApple2Type {
|
|||||||
// A2TYPE_APPLE2C=APPLE2C_MASK, // Placeholder
|
// A2TYPE_APPLE2C=APPLE2C_MASK, // Placeholder
|
||||||
A2TYPE_MAX
|
A2TYPE_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum eBUTTON {BUTTON0=0, BUTTON1};
|
||||||
|
enum eBUTTONSTATE {BUTTON_UP=0, BUTTON_DOWN};
|
||||||
|
@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
#pragma hdrstop
|
#pragma hdrstop
|
||||||
|
#include "MouseInterface.h"
|
||||||
#include "..\resource\resource.h"
|
#include "..\resource\resource.h"
|
||||||
|
|
||||||
#define ENABLE_MENU 0
|
#define ENABLE_MENU 0
|
||||||
@ -90,6 +91,8 @@ void SetFullScreenMode ();
|
|||||||
void SetNormalMode ();
|
void SetNormalMode ();
|
||||||
void SetUsingCursor (BOOL);
|
void SetUsingCursor (BOOL);
|
||||||
|
|
||||||
|
bool g_bScrollLock_FullSpeed = false;
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
void CreateGdiObjects () {
|
void CreateGdiObjects () {
|
||||||
ZeroMemory(buttonbitmap,BUTTONS*sizeof(HBITMAP));
|
ZeroMemory(buttonbitmap,BUTTONS*sizeof(HBITMAP));
|
||||||
@ -609,7 +612,9 @@ LRESULT CALLBACK FrameWndProc (
|
|||||||
SoundCore_SetFade(FADE_IN);
|
SoundCore_SetFade(FADE_IN);
|
||||||
}
|
}
|
||||||
else if (wparam == VK_CAPITAL)
|
else if (wparam == VK_CAPITAL)
|
||||||
|
{
|
||||||
KeybToggleCapsLock();
|
KeybToggleCapsLock();
|
||||||
|
}
|
||||||
else if (wparam == VK_PAUSE)
|
else if (wparam == VK_PAUSE)
|
||||||
{
|
{
|
||||||
SetUsingCursor(0);
|
SetUsingCursor(0);
|
||||||
@ -632,6 +637,10 @@ LRESULT CALLBACK FrameWndProc (
|
|||||||
VideoRedrawScreen();
|
VideoRedrawScreen();
|
||||||
g_bResetTiming = true;
|
g_bResetTiming = true;
|
||||||
}
|
}
|
||||||
|
else if ((wparam == VK_SCROLL) && g_uScrollLockToggle)
|
||||||
|
{
|
||||||
|
g_bScrollLock_FullSpeed = !g_bScrollLock_FullSpeed;
|
||||||
|
}
|
||||||
else if ((g_nAppMode == MODE_RUNNING) || (g_nAppMode == MODE_LOGO) || (g_nAppMode == MODE_STEPPING))
|
else if ((g_nAppMode == MODE_RUNNING) || (g_nAppMode == MODE_LOGO) || (g_nAppMode == MODE_STEPPING))
|
||||||
{
|
{
|
||||||
// Note about Alt Gr (Right-Alt):
|
// Note about Alt Gr (Right-Alt):
|
||||||
@ -654,37 +663,53 @@ LRESULT CALLBACK FrameWndProc (
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_KEYUP:
|
case WM_KEYUP:
|
||||||
if ((wparam >= VK_F1) && (wparam <= VK_F8) && (buttondown == (int)wparam-VK_F1)) {
|
if ((wparam >= VK_F1) && (wparam <= VK_F8) && (buttondown == (int)wparam-VK_F1))
|
||||||
buttondown = -1;
|
{
|
||||||
if (fullscreen)
|
buttondown = -1;
|
||||||
EraseButton(wparam-VK_F1);
|
if (fullscreen)
|
||||||
else
|
EraseButton(wparam-VK_F1);
|
||||||
DrawButton((HDC)0,wparam-VK_F1);
|
else
|
||||||
ProcessButtonClick(wparam-VK_F1);
|
DrawButton((HDC)0,wparam-VK_F1);
|
||||||
}
|
ProcessButtonClick(wparam-VK_F1);
|
||||||
else
|
}
|
||||||
JoyProcessKey((int)wparam,((lparam & 0x01000000) != 0),0,0);
|
else
|
||||||
break;
|
{
|
||||||
|
JoyProcessKey((int)wparam,((lparam & 0x01000000) != 0),0,0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case WM_LBUTTONDOWN:
|
case WM_LBUTTONDOWN:
|
||||||
if (buttondown == -1) {
|
if (buttondown == -1)
|
||||||
|
{
|
||||||
int x = LOWORD(lparam);
|
int x = LOWORD(lparam);
|
||||||
int y = HIWORD(lparam);
|
int y = HIWORD(lparam);
|
||||||
if ((x >= buttonx) &&
|
if ((x >= buttonx) &&
|
||||||
(y >= buttony) &&
|
(y >= buttony) &&
|
||||||
(y <= buttony+BUTTONS*BUTTONCY)) {
|
(y <= buttony+BUTTONS*BUTTONCY))
|
||||||
|
{
|
||||||
buttonactive = buttondown = (y-buttony-1)/BUTTONCY;
|
buttonactive = buttondown = (y-buttony-1)/BUTTONCY;
|
||||||
DrawButton((HDC)0,buttonactive);
|
DrawButton((HDC)0,buttonactive);
|
||||||
SetCapture(window);
|
SetCapture(window);
|
||||||
}
|
}
|
||||||
else if (usingcursor)
|
else if (usingcursor)
|
||||||
|
{
|
||||||
if (wparam & (MK_CONTROL | MK_SHIFT))
|
if (wparam & (MK_CONTROL | MK_SHIFT))
|
||||||
|
{
|
||||||
SetUsingCursor(0);
|
SetUsingCursor(0);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
JoySetButton(0,1);
|
{
|
||||||
else if ((x < buttonx) && JoyUsingMouse() &&
|
if (sg_Mouse.Active())
|
||||||
((g_nAppMode == MODE_RUNNING) || (g_nAppMode == MODE_STEPPING)))
|
sg_Mouse.SetButton(BUTTON0, BUTTON_DOWN);
|
||||||
|
else
|
||||||
|
JoySetButton(BUTTON0, BUTTON_DOWN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( ((x < buttonx) && JoyUsingMouse() && ((g_nAppMode == MODE_RUNNING) || (g_nAppMode == MODE_STEPPING))) ||
|
||||||
|
(sg_Mouse.Active()) )
|
||||||
|
{
|
||||||
SetUsingCursor(1);
|
SetUsingCursor(1);
|
||||||
|
}
|
||||||
DebuggerMouseClick( x, y );
|
DebuggerMouseClick( x, y );
|
||||||
}
|
}
|
||||||
RelayEvent(WM_LBUTTONDOWN,wparam,lparam);
|
RelayEvent(WM_LBUTTONDOWN,wparam,lparam);
|
||||||
@ -704,7 +729,12 @@ LRESULT CALLBACK FrameWndProc (
|
|||||||
buttonactive = -1;
|
buttonactive = -1;
|
||||||
}
|
}
|
||||||
else if (usingcursor)
|
else if (usingcursor)
|
||||||
JoySetButton(0,0);
|
{
|
||||||
|
if (sg_Mouse.Active())
|
||||||
|
sg_Mouse.SetButton(BUTTON0, BUTTON_UP);
|
||||||
|
else
|
||||||
|
JoySetButton(BUTTON0, BUTTON_UP);
|
||||||
|
}
|
||||||
RelayEvent(WM_LBUTTONUP,wparam,lparam);
|
RelayEvent(WM_LBUTTONUP,wparam,lparam);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -730,10 +760,13 @@ LRESULT CALLBACK FrameWndProc (
|
|||||||
if (buttonover != -1)
|
if (buttonover != -1)
|
||||||
DrawButton((HDC)0,buttonover);
|
DrawButton((HDC)0,buttonover);
|
||||||
}
|
}
|
||||||
else if (usingcursor) {
|
else if (usingcursor)
|
||||||
|
{
|
||||||
DrawCrosshairs(x,y);
|
DrawCrosshairs(x,y);
|
||||||
JoySetPosition(x-viewportx-2,VIEWPORTCX-4,
|
if (sg_Mouse.Active())
|
||||||
y-viewporty-2,VIEWPORTCY-4);
|
sg_Mouse.SetPosition(x-viewportx-2, VIEWPORTCX-4, y-viewporty-2, VIEWPORTCY-4);
|
||||||
|
else
|
||||||
|
JoySetPosition(x-viewportx-2, VIEWPORTCX-4, y-viewporty-2, VIEWPORTCY-4);
|
||||||
}
|
}
|
||||||
RelayEvent(WM_MOUSEMOVE,wparam,lparam);
|
RelayEvent(WM_MOUSEMOVE,wparam,lparam);
|
||||||
break;
|
break;
|
||||||
@ -832,7 +865,10 @@ LRESULT CALLBACK FrameWndProc (
|
|||||||
}
|
}
|
||||||
if (usingcursor)
|
if (usingcursor)
|
||||||
{
|
{
|
||||||
JoySetButton(1,(message == WM_RBUTTONDOWN));
|
if (sg_Mouse.Active())
|
||||||
|
sg_Mouse.SetButton(BUTTON1, (message == WM_RBUTTONDOWN) ? BUTTON_DOWN : BUTTON_UP);
|
||||||
|
else
|
||||||
|
JoySetButton(BUTTON1, (message == WM_RBUTTONDOWN) ? BUTTON_DOWN : BUTTON_UP);
|
||||||
}
|
}
|
||||||
RelayEvent(message,wparam,lparam);
|
RelayEvent(message,wparam,lparam);
|
||||||
break;
|
break;
|
||||||
|
@ -25,3 +25,5 @@ LRESULT CALLBACK FrameWndProc (
|
|||||||
UINT message,
|
UINT message,
|
||||||
WPARAM wparam,
|
WPARAM wparam,
|
||||||
LPARAM lparam );
|
LPARAM lparam );
|
||||||
|
|
||||||
|
extern bool g_bScrollLock_FullSpeed;
|
||||||
|
@ -217,7 +217,6 @@ static LPCTSTR HD_DiskGetName (int nDrive)
|
|||||||
static BYTE __stdcall HD_IO_EMUL (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);
|
static BYTE __stdcall HD_IO_EMUL (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);
|
||||||
|
|
||||||
static const DWORD HDDRVR_SIZE = 0x100;
|
static const DWORD HDDRVR_SIZE = 0x100;
|
||||||
static LPBYTE lpMemC000 = NULL;
|
|
||||||
|
|
||||||
bool HD_CardIsEnabled()
|
bool HD_CardIsEnabled()
|
||||||
{
|
{
|
||||||
@ -231,13 +230,14 @@ void HD_SetEnabled(bool bEnabled)
|
|||||||
|
|
||||||
g_bHD_Enabled = bEnabled;
|
g_bHD_Enabled = bEnabled;
|
||||||
|
|
||||||
if(lpMemC000 == NULL) // This will be NULL when called after loading value from Registry
|
LPBYTE pCxRomPeripheral = MemGetCxRomPeripheral();
|
||||||
|
if(pCxRomPeripheral == NULL) // This will be NULL when called after loading value from Registry
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(g_bHD_Enabled)
|
if(g_bHD_Enabled)
|
||||||
HD_Load_Rom(lpMemC000, g_uSlot);
|
HD_Load_Rom(pCxRomPeripheral, g_uSlot);
|
||||||
else
|
else
|
||||||
memset(lpMemC000 + g_uSlot*256, 0, HDDRVR_SIZE);
|
memset(pCxRomPeripheral + g_uSlot*256, 0, HDDRVR_SIZE);
|
||||||
|
|
||||||
RegisterIoHandler(g_uSlot, HD_IO_EMUL, HD_IO_EMUL, NULL, NULL, NULL, NULL);
|
RegisterIoHandler(g_uSlot, HD_IO_EMUL, HD_IO_EMUL, NULL, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
@ -249,8 +249,6 @@ LPCTSTR HD_GetFullName (int nDrive)
|
|||||||
|
|
||||||
VOID HD_Load_Rom(LPBYTE pCxRomPeripheral, UINT uSlot)
|
VOID HD_Load_Rom(LPBYTE pCxRomPeripheral, UINT uSlot)
|
||||||
{
|
{
|
||||||
lpMemC000 = pCxRomPeripheral; // Keep a copy for HD_SetEnabled()
|
|
||||||
|
|
||||||
if(!g_bHD_Enabled)
|
if(!g_bHD_Enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
#pragma hdrstop
|
#pragma hdrstop
|
||||||
|
#include "MouseInterface.h"
|
||||||
|
|
||||||
#define BUTTONTIME 5000
|
#define BUTTONTIME 5000
|
||||||
|
|
||||||
@ -365,7 +366,7 @@ BOOL JoyProcessKey (int virtkey, BOOL extended, BOOL down, BOOL autorep)
|
|||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
BYTE __stdcall JoyReadButton (WORD, WORD address, BYTE, BYTE, ULONG)
|
BYTE __stdcall JoyReadButton (WORD, WORD address, BYTE, BYTE, ULONG nCyclesLeft)
|
||||||
{
|
{
|
||||||
address &= 0xFF;
|
address &= 0xFF;
|
||||||
|
|
||||||
@ -397,7 +398,7 @@ BYTE __stdcall JoyReadButton (WORD, WORD address, BYTE, BYTE, ULONG)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
return MemReadFloatingBus(pressed);
|
return MemReadFloatingBus(pressed, nCyclesLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
@ -433,7 +434,7 @@ BYTE __stdcall JoyReadPosition (WORD programcounter, WORD address, BYTE, BYTE, U
|
|||||||
|
|
||||||
BOOL nPdlCntrActive = g_nCumulativeCycles <= (g_nJoyCntrResetCycle + (unsigned __int64) ((double)nPdlPos * PDL_CNTR_INTERVAL));
|
BOOL nPdlCntrActive = g_nCumulativeCycles <= (g_nJoyCntrResetCycle + (unsigned __int64) ((double)nPdlPos * PDL_CNTR_INTERVAL));
|
||||||
|
|
||||||
return MemReadFloatingBus(nPdlCntrActive);
|
return MemReadFloatingBus(nPdlCntrActive, nCyclesLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
@ -455,13 +456,13 @@ BYTE __stdcall JoyResetPosition (WORD, WORD, BYTE, BYTE, ULONG nCyclesLeft)
|
|||||||
if(joyinfo[joytype[1]].device == DEVICE_JOYSTICK)
|
if(joyinfo[joytype[1]].device == DEVICE_JOYSTICK)
|
||||||
CheckJoystick1();
|
CheckJoystick1();
|
||||||
|
|
||||||
return MemReadFloatingBus();
|
return MemReadFloatingBus(nCyclesLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
// Called when mouse is being used as a joystick && mouse button changes
|
// Called when mouse is being used as a joystick && mouse button changes
|
||||||
void JoySetButton (int number, BOOL down)
|
void JoySetButton (eBUTTON number, eBUTTONSTATE down)
|
||||||
{
|
{
|
||||||
if (number > 1) // Sanity check on mouse button #
|
if (number > 1) // Sanity check on mouse button #
|
||||||
return;
|
return;
|
||||||
@ -473,7 +474,7 @@ void JoySetButton (int number, BOOL down)
|
|||||||
// If it is 2nd joystick that is being emulated with mouse, then re-map button #
|
// If it is 2nd joystick that is being emulated with mouse, then re-map button #
|
||||||
if(joyinfo[joytype[1]].device == DEVICE_MOUSE)
|
if(joyinfo[joytype[1]].device == DEVICE_MOUSE)
|
||||||
{
|
{
|
||||||
number = 1; // 2nd joystick controls Apple button #1
|
number = BUTTON1; // 2nd joystick controls Apple button #1
|
||||||
}
|
}
|
||||||
|
|
||||||
setbutton[number] = down;
|
setbutton[number] = down;
|
||||||
@ -507,6 +508,15 @@ BOOL JoySetEmulationType (HWND window, DWORD newtype, int nJoystickNumber)
|
|||||||
else if ((joyinfo[newtype].device == DEVICE_MOUSE) &&
|
else if ((joyinfo[newtype].device == DEVICE_MOUSE) &&
|
||||||
(joyinfo[joytype[nJoystickNumber]].device != DEVICE_MOUSE))
|
(joyinfo[joytype[nJoystickNumber]].device != DEVICE_MOUSE))
|
||||||
{
|
{
|
||||||
|
if (sg_Mouse.Active())
|
||||||
|
{
|
||||||
|
MessageBox(window,
|
||||||
|
TEXT("Mouse interface card is enabled - unable to use mouse for joystick emulation."),
|
||||||
|
TEXT("Configuration"),
|
||||||
|
MB_ICONEXCLAMATION | MB_SETFOREGROUND);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
MessageBox(window,
|
MessageBox(window,
|
||||||
TEXT("To begin emulating a joystick with your mouse, move ")
|
TEXT("To begin emulating a joystick with your mouse, move ")
|
||||||
TEXT("the mouse cursor over the emulated screen of a running ")
|
TEXT("the mouse cursor over the emulated screen of a running ")
|
||||||
|
@ -7,7 +7,7 @@ extern DWORD joytype[2];
|
|||||||
void JoyInitialize ();
|
void JoyInitialize ();
|
||||||
BOOL JoyProcessKey (int,BOOL,BOOL,BOOL);
|
BOOL JoyProcessKey (int,BOOL,BOOL,BOOL);
|
||||||
void JoyReset ();
|
void JoyReset ();
|
||||||
void JoySetButton (int,BOOL);
|
void JoySetButton (eBUTTON,eBUTTONSTATE);
|
||||||
BOOL JoySetEmulationType (HWND,DWORD,int);
|
BOOL JoySetEmulationType (HWND,DWORD,int);
|
||||||
void JoySetPosition (int,int,int,int);
|
void JoySetPosition (int,int,int,int);
|
||||||
void JoyUpdatePosition ();
|
void JoyUpdatePosition ();
|
||||||
|
@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
#pragma hdrstop
|
#pragma hdrstop
|
||||||
|
#include "MouseInterface.h"
|
||||||
#include "..\resource\resource.h"
|
#include "..\resource\resource.h"
|
||||||
|
|
||||||
#define MF_80STORE 0x00000001
|
#define MF_80STORE 0x00000001
|
||||||
@ -362,15 +363,15 @@ static UINT g_uPeripheralRomSlot = 0;
|
|||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
BYTE __stdcall IO_Null(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles)
|
BYTE __stdcall IO_Null(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCyclesLeft)
|
||||||
{
|
{
|
||||||
if (!write)
|
if (!write)
|
||||||
return MemReadFloatingBus();
|
return MemReadFloatingBus(nCyclesLeft);
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BYTE __stdcall IO_Annunciator(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles)
|
BYTE __stdcall IO_Annunciator(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCyclesLeft)
|
||||||
{
|
{
|
||||||
// Apple//e ROM:
|
// Apple//e ROM:
|
||||||
// . PC=FA6F: LDA $C058 (SETAN0)
|
// . PC=FA6F: LDA $C058 (SETAN0)
|
||||||
@ -387,7 +388,7 @@ BYTE __stdcall IO_Annunciator(WORD programcounter, WORD address, BYTE write, BYT
|
|||||||
// - Reset when 6502 accesses $CFFF
|
// - Reset when 6502 accesses $CFFF
|
||||||
// . Enable2 = I/O STROBE' (6502 accesses [$C800..$CFFF])
|
// . Enable2 = I/O STROBE' (6502 accesses [$C800..$CFFF])
|
||||||
|
|
||||||
BYTE __stdcall IORead_Cxxx(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles)
|
BYTE __stdcall IORead_Cxxx(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCyclesLeft)
|
||||||
{
|
{
|
||||||
if (address == 0xCFFF)
|
if (address == 0xCFFF)
|
||||||
{
|
{
|
||||||
@ -483,12 +484,12 @@ BYTE __stdcall IORead_Cxxx(WORD programcounter, WORD address, BYTE write, BYTE v
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((g_eExpansionRomType == eExpRomNull) && (address >= 0xC800))
|
if ((g_eExpansionRomType == eExpRomNull) && (address >= 0xC800))
|
||||||
return IO_Null(programcounter, address, write, value, nCycles);
|
return IO_Null(programcounter, address, write, value, nCyclesLeft);
|
||||||
else
|
else
|
||||||
return mem[address];
|
return mem[address];
|
||||||
}
|
}
|
||||||
|
|
||||||
BYTE __stdcall IOWrite_Cxxx(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles)
|
BYTE __stdcall IOWrite_Cxxx(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCyclesLeft)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -865,6 +866,13 @@ LPBYTE MemGetMainPtr (WORD offset)
|
|||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
|
LPBYTE MemGetCxRomPeripheral()
|
||||||
|
{
|
||||||
|
return pCxRomPeripheral;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
void MemPreInitialize ()
|
void MemPreInitialize ()
|
||||||
{
|
{
|
||||||
// Init the I/O handlers
|
// Init the I/O handlers
|
||||||
@ -989,10 +997,12 @@ void MemInitialize()
|
|||||||
const UINT uSlot = 0;
|
const UINT uSlot = 0;
|
||||||
RegisterIoHandler(uSlot, MemSetPaging, MemSetPaging, NULL, NULL, NULL, NULL);
|
RegisterIoHandler(uSlot, MemSetPaging, MemSetPaging, NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
PrintLoadRom(pCxRomPeripheral, 1); // $C100 : Parallel printer f/w
|
PrintLoadRom(pCxRomPeripheral, 1); // $C100 : Parallel printer f/w
|
||||||
sg_SSC.CommInitialize(pCxRomPeripheral, 2); // $C200 : SSC
|
sg_SSC.CommInitialize(pCxRomPeripheral, 2); // $C200 : SSC
|
||||||
DiskLoadRom(pCxRomPeripheral, 6); // $C600 : Disk][ f/w
|
if (g_Slot4 == CT_MouseInterface)
|
||||||
HD_Load_Rom(pCxRomPeripheral, 7); // $C700 : HDD f/w
|
sg_Mouse.Initialize(pCxRomPeripheral, 4); // $C400 : Mouse f/w
|
||||||
|
DiskLoadRom(pCxRomPeripheral, 6); // $C600 : Disk][ f/w
|
||||||
|
HD_Load_Rom(pCxRomPeripheral, 7); // $C700 : HDD f/w
|
||||||
|
|
||||||
MemReset();
|
MemReset();
|
||||||
}
|
}
|
||||||
@ -1069,16 +1079,16 @@ BYTE MemReturnRandomData (BYTE highbit)
|
|||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
BYTE MemReadFloatingBus()
|
BYTE MemReadFloatingBus(const ULONG uExecutedCycles)
|
||||||
{
|
{
|
||||||
return*(LPBYTE)(mem + VideoGetScannerAddress());
|
return*(LPBYTE)(mem + VideoGetScannerAddress(NULL, uExecutedCycles));
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
BYTE MemReadFloatingBus(BYTE const highbit)
|
BYTE MemReadFloatingBus(const BYTE highbit, const ULONG uExecutedCycles)
|
||||||
{
|
{
|
||||||
BYTE r = *(LPBYTE)(mem + VideoGetScannerAddress());
|
BYTE r = *(LPBYTE)(mem + VideoGetScannerAddress(NULL, uExecutedCycles));
|
||||||
return (r & ~0x80) | ((highbit) ? 0x80 : 0);
|
return (r & ~0x80) | ((highbit) ? 0x80 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1103,7 +1113,7 @@ BYTE MemReadFloatingBus(BYTE const highbit)
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
BYTE __stdcall MemSetPaging (WORD programcounter, WORD address, BYTE write, BYTE value, ULONG)
|
BYTE __stdcall MemSetPaging (WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCyclesLeft)
|
||||||
{
|
{
|
||||||
address &= 0xFF;
|
address &= 0xFF;
|
||||||
DWORD lastmemmode = memmode;
|
DWORD lastmemmode = memmode;
|
||||||
@ -1166,13 +1176,13 @@ BYTE __stdcall MemSetPaging (WORD programcounter, WORD address, BYTE write, BYTE
|
|||||||
if ((address >= 4) && (address <= 5) &&
|
if ((address >= 4) && (address <= 5) &&
|
||||||
((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0028D)) {
|
((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0028D)) {
|
||||||
modechanging = 1;
|
modechanging = 1;
|
||||||
return write ? 0 : MemReadFloatingBus(1);
|
return write ? 0 : MemReadFloatingBus(1, nCyclesLeft);
|
||||||
}
|
}
|
||||||
if ((address >= 0x80) && (address <= 0x8F) && (programcounter < 0xC000) &&
|
if ((address >= 0x80) && (address <= 0x8F) && (programcounter < 0xC000) &&
|
||||||
(((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0048D) ||
|
(((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0048D) ||
|
||||||
((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0028D))) {
|
((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0028D))) {
|
||||||
modechanging = 1;
|
modechanging = 1;
|
||||||
return write ? 0 : MemReadFloatingBus(1);
|
return write ? 0 : MemReadFloatingBus(1, nCyclesLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
// IF THE MEMORY PAGING MODE HAS CHANGED, UPDATE OUR MEMORY IMAGES AND
|
// IF THE MEMORY PAGING MODE HAS CHANGED, UPDATE OUR MEMORY IMAGES AND
|
||||||
@ -1216,9 +1226,9 @@ BYTE __stdcall MemSetPaging (WORD programcounter, WORD address, BYTE write, BYTE
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((address <= 1) || ((address >= 0x54) && (address <= 0x57)))
|
if ((address <= 1) || ((address >= 0x54) && (address <= 0x57)))
|
||||||
return VideoSetMode(programcounter,address,write,value,0);
|
return VideoSetMode(programcounter,address,write,value,nCyclesLeft);
|
||||||
|
|
||||||
return write ? 0 : MemReadFloatingBus();
|
return write ? 0 : MemReadFloatingBus(nCyclesLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
@ -26,10 +26,11 @@ bool MemGet80Store();
|
|||||||
bool MemCheckSLOTCXROM();
|
bool MemCheckSLOTCXROM();
|
||||||
LPBYTE MemGetAuxPtr (WORD);
|
LPBYTE MemGetAuxPtr (WORD);
|
||||||
LPBYTE MemGetMainPtr (WORD);
|
LPBYTE MemGetMainPtr (WORD);
|
||||||
|
LPBYTE MemGetCxRomPeripheral();
|
||||||
void MemPreInitialize ();
|
void MemPreInitialize ();
|
||||||
void MemInitialize ();
|
void MemInitialize ();
|
||||||
BYTE MemReadFloatingBus();
|
BYTE MemReadFloatingBus(const ULONG uExecutedCycles);
|
||||||
BYTE MemReadFloatingBus(BYTE highbit);
|
BYTE MemReadFloatingBus(const BYTE highbit, const ULONG uExecutedCycles);
|
||||||
void MemReset ();
|
void MemReset ();
|
||||||
void MemResetPaging ();
|
void MemResetPaging ();
|
||||||
BYTE MemReturnRandomData (BYTE highbit);
|
BYTE MemReturnRandomData (BYTE highbit);
|
||||||
|
@ -145,6 +145,7 @@ static SY6522_AY8910 g_MB[NUM_AY8910];
|
|||||||
// Timer vars
|
// Timer vars
|
||||||
static ULONG g_n6522TimerPeriod = 0;
|
static ULONG g_n6522TimerPeriod = 0;
|
||||||
static USHORT g_nMBTimerDevice = 0; // SY6522 device# which is generating timer IRQ
|
static USHORT g_nMBTimerDevice = 0; // SY6522 device# which is generating timer IRQ
|
||||||
|
static UINT64 g_uLastCumulativeCycles = 0;
|
||||||
|
|
||||||
// SSI263 vars:
|
// SSI263 vars:
|
||||||
static USHORT g_nSSI263Device = 0; // SSI263 device# which is generating phoneme-complete IRQ
|
static USHORT g_nSSI263Device = 0; // SSI263 device# which is generating phoneme-complete IRQ
|
||||||
@ -1307,8 +1308,11 @@ void MB_Initialize()
|
|||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
const UINT uSlot4 = 4;
|
if (g_Slot4 == CT_Mockingboard)
|
||||||
RegisterIoHandler(uSlot4, PhasorIO, PhasorIO, MB_Read, MB_Write, NULL, NULL);
|
{
|
||||||
|
const UINT uSlot4 = 4;
|
||||||
|
RegisterIoHandler(uSlot4, PhasorIO, PhasorIO, MB_Read, MB_Write, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
const UINT uSlot5 = 5;
|
const UINT uSlot5 = 5;
|
||||||
RegisterIoHandler(uSlot5, PhasorIO, PhasorIO, MB_Read, MB_Write, NULL, NULL);
|
RegisterIoHandler(uSlot5, PhasorIO, PhasorIO, MB_Read, MB_Write, NULL, NULL);
|
||||||
@ -1354,7 +1358,7 @@ void MB_Reset()
|
|||||||
|
|
||||||
static BYTE __stdcall MB_Read(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULONG nCyclesLeft)
|
static BYTE __stdcall MB_Read(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULONG nCyclesLeft)
|
||||||
{
|
{
|
||||||
CpuCalcCycles(nCyclesLeft);
|
MB_UpdateCycles(nCyclesLeft);
|
||||||
|
|
||||||
if(!IS_APPLE2 && !MemCheckSLOTCXROM())
|
if(!IS_APPLE2 && !MemCheckSLOTCXROM())
|
||||||
return mem[nAddr];
|
return mem[nAddr];
|
||||||
@ -1404,7 +1408,7 @@ static BYTE __stdcall MB_Read(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULO
|
|||||||
|
|
||||||
static BYTE __stdcall MB_Write(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULONG nCyclesLeft)
|
static BYTE __stdcall MB_Write(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULONG nCyclesLeft)
|
||||||
{
|
{
|
||||||
CpuCalcCycles(nCyclesLeft);
|
MB_UpdateCycles(nCyclesLeft);
|
||||||
|
|
||||||
if(!IS_APPLE2 && !MemCheckSLOTCXROM())
|
if(!IS_APPLE2 && !MemCheckSLOTCXROM())
|
||||||
return 0;
|
return 0;
|
||||||
@ -1502,8 +1506,14 @@ void MB_Demute()
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Called by CpuExecute() before doing CPU emulation
|
||||||
|
void MB_StartOfCpuExecute()
|
||||||
|
{
|
||||||
|
g_uLastCumulativeCycles = g_nCumulativeCycles;
|
||||||
|
}
|
||||||
|
|
||||||
// Called by ContinueExecution() at the end of every video frame
|
// Called by ContinueExecution() at the end of every video frame
|
||||||
void MB_EndOfFrame()
|
void MB_EndOfVideoFrame()
|
||||||
{
|
{
|
||||||
if(g_SoundcardType == SC_NONE)
|
if(g_SoundcardType == SC_NONE)
|
||||||
return;
|
return;
|
||||||
@ -1514,13 +1524,20 @@ void MB_EndOfFrame()
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Called by InternalCpuExecute() after every opcode
|
// Called by InternalCpuExecute() after every N opcodes
|
||||||
// OLD: Called by CpuExecute() & CpuCalcCycles()
|
// OLD: Called by InternalCpuExecute() after every opcode
|
||||||
void MB_UpdateCycles(USHORT nClocks)
|
// OLD: void MB_UpdateCycles(USHORT nClocks)
|
||||||
|
void MB_UpdateCycles(ULONG uExecutedCycles)
|
||||||
{
|
{
|
||||||
if(g_SoundcardType == SC_NONE)
|
if(g_SoundcardType == SC_NONE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
CpuCalcCycles(uExecutedCycles);
|
||||||
|
UINT64 uCycles = g_nCumulativeCycles - g_uLastCumulativeCycles;
|
||||||
|
g_uLastCumulativeCycles = g_nCumulativeCycles;
|
||||||
|
_ASSERT(uCycles < 0x10000);
|
||||||
|
USHORT nClocks = (USHORT) uCycles;
|
||||||
|
|
||||||
for(int i=0; i<NUM_SY6522; i++)
|
for(int i=0; i<NUM_SY6522; i++)
|
||||||
{
|
{
|
||||||
SY6522_AY8910* pMB = &g_MB[i];
|
SY6522_AY8910* pMB = &g_MB[i];
|
||||||
|
@ -9,9 +9,10 @@ void MB_Destroy();
|
|||||||
void MB_Reset();
|
void MB_Reset();
|
||||||
void MB_Mute();
|
void MB_Mute();
|
||||||
void MB_Demute();
|
void MB_Demute();
|
||||||
void MB_EndOfFrame();
|
void MB_StartOfCpuExecute();
|
||||||
|
void MB_EndOfVideoFrame();
|
||||||
void MB_CheckIRQ();
|
void MB_CheckIRQ();
|
||||||
void MB_UpdateCycles(USHORT nClocks);
|
void MB_UpdateCycles(ULONG uExecutedCycles);
|
||||||
eSOUNDCARDTYPE MB_GetSoundcardType();
|
eSOUNDCARDTYPE MB_GetSoundcardType();
|
||||||
void MB_SetSoundcardType(eSOUNDCARDTYPE NewSoundcardType);
|
void MB_SetSoundcardType(eSOUNDCARDTYPE NewSoundcardType);
|
||||||
double MB_GetFramePeriod();
|
double MB_GetFramePeriod();
|
||||||
|
431
source/MouseInterface.cpp
Normal file
431
source/MouseInterface.cpp
Normal file
@ -0,0 +1,431 @@
|
|||||||
|
// Based on Apple in PC's mousecard.cpp
|
||||||
|
// - Permission given by Kyle Kim to reuse in AppleWin
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#pragma hdrstop
|
||||||
|
#include "..\resource\resource.h"
|
||||||
|
#include "MouseInterface.h"
|
||||||
|
|
||||||
|
// Sets mouse mode
|
||||||
|
#define MOUSE_SET 0x00
|
||||||
|
// Reads mouse position
|
||||||
|
#define MOUSE_READ 0x10
|
||||||
|
// Services mouse interrupt
|
||||||
|
#define MOUSE_SERV 0x20
|
||||||
|
// Clears mouse positions to 0 (for delta mode)
|
||||||
|
#define MOUSE_CLEAR 0x30
|
||||||
|
// Sets mouse position to a user-defined pos
|
||||||
|
#define MOUSE_POS 0x40
|
||||||
|
// Resets mouse clamps to default values
|
||||||
|
// Sets mouse position to 0,0
|
||||||
|
#define MOUSE_INIT 0x50
|
||||||
|
// Sets mouse bounds in a window
|
||||||
|
#define MOUSE_CLAMP 0x60
|
||||||
|
// Sets mouse to upper-left corner of clamp win
|
||||||
|
#define MOUSE_HOME 0x70
|
||||||
|
|
||||||
|
// Set VBL Timing : 0x90 is 60Hz, 0x91 is 50Hz
|
||||||
|
#define MOUSE_TIME 0x90
|
||||||
|
|
||||||
|
#define BIT0 0x01
|
||||||
|
#define BIT1 0x02
|
||||||
|
#define BIT2 0x04
|
||||||
|
#define BIT3 0x08
|
||||||
|
#define BIT4 0x10
|
||||||
|
#define BIT5 0x20
|
||||||
|
#define BIT6 0x40
|
||||||
|
#define BIT7 0x80
|
||||||
|
|
||||||
|
WRITE_HANDLER( M6821_Listener_B )
|
||||||
|
{
|
||||||
|
((CMouseInterface*)objTo)->On6821_B( byData );
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE_HANDLER( M6821_Listener_A )
|
||||||
|
{
|
||||||
|
((CMouseInterface*)objTo)->On6821_A( byData );
|
||||||
|
}
|
||||||
|
|
||||||
|
//CALLBACK_HANDLER( MouseHandler )
|
||||||
|
//{
|
||||||
|
// ((CMouseInterface*)objTo)->OnMouseEvent();
|
||||||
|
//}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
CMouseInterface::CMouseInterface() :
|
||||||
|
m_pSlotRom(NULL)
|
||||||
|
{
|
||||||
|
m_6821.SetListenerB( this, M6821_Listener_B );
|
||||||
|
m_6821.SetListenerA( this, M6821_Listener_A );
|
||||||
|
// g_cDIMouse.SetMouseListener( this, MouseHandler );
|
||||||
|
m_by6821A = 0;
|
||||||
|
m_by6821B = 0x40; // Set PB6
|
||||||
|
m_6821.SetPB(m_by6821B);
|
||||||
|
m_bVBL = FALSE;
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
m_iX = 0;
|
||||||
|
m_iMinX = 0;
|
||||||
|
m_iMaxX = 1023;
|
||||||
|
m_iRangeX = 0;
|
||||||
|
|
||||||
|
m_iY = 0;
|
||||||
|
m_iMinY = 0;
|
||||||
|
m_iMaxY = 1023;
|
||||||
|
m_iRangeY = 0;
|
||||||
|
|
||||||
|
m_bButtons[0] = m_bButtons[1] = FALSE;
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
Reset();
|
||||||
|
memset( m_byBuff, 0, sizeof( m_byBuff ) );
|
||||||
|
m_bActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMouseInterface::~CMouseInterface()
|
||||||
|
{
|
||||||
|
delete [] m_pSlotRom;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
void CMouseInterface::Initialize(LPBYTE pCxRomPeripheral, UINT uSlot)
|
||||||
|
{
|
||||||
|
const UINT FW_SIZE = 2*1024;
|
||||||
|
|
||||||
|
HRSRC hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_MOUSEINTERFACE_FW), "FIRMWARE");
|
||||||
|
if(hResInfo == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DWORD dwResSize = SizeofResource(NULL, hResInfo);
|
||||||
|
if(dwResSize != FW_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;
|
||||||
|
|
||||||
|
m_uSlot = uSlot;
|
||||||
|
|
||||||
|
if (m_pSlotRom == NULL)
|
||||||
|
{
|
||||||
|
m_pSlotRom = new BYTE [FW_SIZE];
|
||||||
|
|
||||||
|
if (m_pSlotRom)
|
||||||
|
memcpy(m_pSlotRom, pData, FW_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
SetSlotRom();
|
||||||
|
RegisterIoHandler(uSlot, &CMouseInterface::IORead, &CMouseInterface::IOWrite, NULL, NULL, this, NULL);
|
||||||
|
m_bActive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMouseInterface::SetSlotRom()
|
||||||
|
{
|
||||||
|
LPBYTE pCxRomPeripheral = MemGetCxRomPeripheral();
|
||||||
|
if (pCxRomPeripheral == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UINT uOffset = (m_by6821B << 7) & 0x0700;
|
||||||
|
memcpy(pCxRomPeripheral+m_uSlot*256, m_pSlotRom+uOffset, 256);
|
||||||
|
if (mem)
|
||||||
|
memcpy(mem+0xC000+m_uSlot*256, m_pSlotRom+uOffset, 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
BYTE __stdcall CMouseInterface::IORead(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValue, ULONG nCyclesLeft)
|
||||||
|
{
|
||||||
|
UINT uSlot = ((uAddr & 0xff) >> 4) - 8;
|
||||||
|
CMouseInterface* pMouseIF = (CMouseInterface*) MemGetSlotParameters(uSlot);
|
||||||
|
|
||||||
|
BYTE byRS;
|
||||||
|
byRS = uAddr & 3;
|
||||||
|
return pMouseIF->m_6821.Read( byRS );
|
||||||
|
}
|
||||||
|
|
||||||
|
BYTE __stdcall CMouseInterface::IOWrite(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValue, ULONG nCyclesLeft)
|
||||||
|
{
|
||||||
|
UINT uSlot = ((uAddr & 0xff) >> 4) - 8;
|
||||||
|
CMouseInterface* pMouseIF = (CMouseInterface*) MemGetSlotParameters(uSlot);
|
||||||
|
|
||||||
|
BYTE byRS;
|
||||||
|
byRS = uAddr & 3;
|
||||||
|
pMouseIF->m_6821.Write( byRS, uValue );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
void CMouseInterface::On6821_A(BYTE byData)
|
||||||
|
{
|
||||||
|
m_by6821A = byData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMouseInterface::On6821_B(BYTE byData)
|
||||||
|
{
|
||||||
|
BYTE byDiff = ( m_by6821B ^ byData ) & 0x3E;
|
||||||
|
|
||||||
|
if ( byDiff )
|
||||||
|
{
|
||||||
|
m_by6821B &= ~0x3E;
|
||||||
|
m_by6821B |= byData & 0x3E;
|
||||||
|
if ( byDiff & BIT5 ) // Write to 0285 chip
|
||||||
|
{
|
||||||
|
if ( byData & BIT5 )
|
||||||
|
m_by6821B |= BIT7; // OK, I'm ready to read from MC6821
|
||||||
|
else // Clock Activate for read
|
||||||
|
{
|
||||||
|
m_byBuff[m_nBuffPos++] = m_by6821A;
|
||||||
|
if ( m_nBuffPos == 1 )
|
||||||
|
OnCommand();
|
||||||
|
if ( m_nBuffPos == m_nDataLen || m_nBuffPos > 7 )
|
||||||
|
{
|
||||||
|
OnWrite(); // Have written all, Commit the command.
|
||||||
|
m_nBuffPos = 0;
|
||||||
|
}
|
||||||
|
m_by6821B &= ~BIT7; // for next reading
|
||||||
|
m_6821.SetPB( m_by6821B );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if ( byDiff & BIT4 ) // Read from 0285 chip ?
|
||||||
|
{
|
||||||
|
if ( byData & BIT4 )
|
||||||
|
m_by6821B &= ~BIT6; // OK, I'll prepare next value
|
||||||
|
else // Clock Activate for write
|
||||||
|
{
|
||||||
|
if ( m_nBuffPos ) // if m_nBuffPos is 0, something goes wrong!
|
||||||
|
m_nBuffPos++;
|
||||||
|
if ( m_nBuffPos == m_nDataLen || m_nBuffPos > 7 )
|
||||||
|
m_nBuffPos = 0; // Have read all, ready for next command.
|
||||||
|
else
|
||||||
|
m_6821.SetPA( m_byBuff[m_nBuffPos] );
|
||||||
|
m_by6821B |= BIT6; // for next writing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_6821.SetPB( m_by6821B );
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
SetSlotRom(); // Update Cn00 ROM page
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CMouseInterface::OnCommand()
|
||||||
|
{
|
||||||
|
//char szDbg[256];
|
||||||
|
switch( m_byBuff[0] & 0xF0 )
|
||||||
|
{
|
||||||
|
case MOUSE_SET:
|
||||||
|
m_nDataLen = 1;
|
||||||
|
m_byMode = m_byBuff[0] & 0x0F;
|
||||||
|
break;
|
||||||
|
case MOUSE_READ: // Read
|
||||||
|
m_nDataLen = 6;
|
||||||
|
m_byState &= 0x20;
|
||||||
|
m_nX = m_iX;
|
||||||
|
m_nY = m_iY;
|
||||||
|
if ( m_bBtn0 ) m_byState |= 0x40; // Previous Button 0
|
||||||
|
if ( m_bBtn1 ) m_byState |= 0x01; // Previous Button 1
|
||||||
|
m_bBtn0 = m_bButtons[0];
|
||||||
|
m_bBtn1 = m_bButtons[1];
|
||||||
|
if ( m_bBtn0 ) m_byState |= 0x80; // Current Button 0
|
||||||
|
if ( m_bBtn1 ) m_byState |= 0x10; // Current Button 1
|
||||||
|
m_byBuff[1] = m_nX & 0xFF;
|
||||||
|
m_byBuff[2] = ( m_nX >> 8 ) & 0xFF;
|
||||||
|
m_byBuff[3] = m_nY & 0xFF;
|
||||||
|
m_byBuff[4] = ( m_nY >> 8 ) & 0xFF;
|
||||||
|
m_byBuff[5] = m_byState; // button 0/1 interrupt status
|
||||||
|
m_byState &= ~0x20;
|
||||||
|
//sprintf(szDbg, "[MOUSE-READ] IRQ=0x%02X X=(0x%02X-0x%02X) Y=(0x%02X-0x%02X) \n", m_byBuff[5], m_byBuff[1], m_byBuff[2], m_byBuff[3], m_byBuff[4]); OutputDebugString(szDbg);
|
||||||
|
break;
|
||||||
|
case MOUSE_SERV:
|
||||||
|
m_nDataLen = 2;
|
||||||
|
m_byBuff[1] = m_byState & ~0x20; // reason of interrupt
|
||||||
|
CpuIrqDeassert(IS_MOUSE);
|
||||||
|
//sprintf(szDbg, "[MOUSE-SERV] IRQ=0x%02X\n", m_byBuff[1]); OutputDebugString(szDbg);
|
||||||
|
break;
|
||||||
|
case MOUSE_CLEAR:
|
||||||
|
Reset();
|
||||||
|
m_nDataLen = 1;
|
||||||
|
break;
|
||||||
|
case MOUSE_POS:
|
||||||
|
m_nDataLen = 5;
|
||||||
|
break;
|
||||||
|
case MOUSE_INIT:
|
||||||
|
m_nDataLen = 3;
|
||||||
|
m_byBuff[1] = 0xFF; // I don't know what it is
|
||||||
|
break;
|
||||||
|
case MOUSE_CLAMP:
|
||||||
|
m_nDataLen = 5;
|
||||||
|
break;
|
||||||
|
case MOUSE_HOME:
|
||||||
|
m_nDataLen = 1;
|
||||||
|
SetPosition( 0, 0 );
|
||||||
|
break;
|
||||||
|
case MOUSE_TIME: // 0x90
|
||||||
|
switch( m_byBuff[0] & 0x0C )
|
||||||
|
{
|
||||||
|
case 0x00: m_nDataLen = 1; break; // write cmd ( #$90 is DATATIME 60Hz, #$91 is 50Hz )
|
||||||
|
case 0x04: m_nDataLen = 3; break; // write cmd, $0478, $04F8
|
||||||
|
case 0x08: m_nDataLen = 2; break; // write cmd, $0578
|
||||||
|
case 0x0C: m_nDataLen = 4; break; // write cmd, $0478, $04F8, $0578
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0xA0:
|
||||||
|
m_nDataLen = 2;
|
||||||
|
break;
|
||||||
|
case 0xB0:
|
||||||
|
case 0xC0:
|
||||||
|
m_nDataLen = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
m_nDataLen = 1;
|
||||||
|
//TRACE( "CMD : UNKNOWN CMD : #$%02X\n", m_byBuff[0] );
|
||||||
|
//_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_6821.SetPA( m_byBuff[1] );
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMouseInterface::OnWrite()
|
||||||
|
{
|
||||||
|
int nMin, nMax;
|
||||||
|
switch( m_byBuff[0] & 0xF0 )
|
||||||
|
{
|
||||||
|
case MOUSE_CLAMP:
|
||||||
|
nMin = ( m_byBuff[3] << 8 ) | m_byBuff[1];
|
||||||
|
nMax = ( m_byBuff[4] << 8 ) | m_byBuff[2];
|
||||||
|
if ( m_byBuff[0] & 1 ) // Clamp Y
|
||||||
|
ClampY( nMin, nMax );
|
||||||
|
else // Clamp X
|
||||||
|
ClampX( nMin, nMax );
|
||||||
|
break;
|
||||||
|
case MOUSE_POS:
|
||||||
|
m_nX = ( m_byBuff[2] << 8 ) | m_byBuff[1];
|
||||||
|
m_nY = ( m_byBuff[4] << 8 ) | m_byBuff[3];
|
||||||
|
SetPosition( m_nX, m_nY );
|
||||||
|
break;
|
||||||
|
case MOUSE_INIT:
|
||||||
|
m_nX = 0;
|
||||||
|
m_nY = 0;
|
||||||
|
ClampX( 0, 1023 );
|
||||||
|
ClampY( 0, 1023 );
|
||||||
|
SetPosition( 0, 0 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMouseInterface::OnMouseEvent()
|
||||||
|
{
|
||||||
|
int byState = 0;
|
||||||
|
|
||||||
|
if ( !( m_byMode & 1 ) ) // Mouse Off
|
||||||
|
return;
|
||||||
|
|
||||||
|
BOOL bBtn0 = m_bButtons[0];
|
||||||
|
BOOL bBtn1 = m_bButtons[1];
|
||||||
|
if ( m_nX != m_iX || m_nY != m_iY )
|
||||||
|
byState |= 0x22; // X/Y moved since last READMOUSE | Movement interrupt
|
||||||
|
if ( m_bBtn0 != bBtn0 || m_bBtn1 != bBtn1 )
|
||||||
|
byState |= 0x04; // Button 0/1 interrupt
|
||||||
|
if ( m_bVBL )
|
||||||
|
byState |= 0x08;
|
||||||
|
byState &= m_byMode & 0x2E;
|
||||||
|
|
||||||
|
if ( byState & 0x0E )
|
||||||
|
{
|
||||||
|
//char szDbg[256];
|
||||||
|
//sprintf(szDbg, "[MOUSE] 0x%02X, %04d(%04d), %04d(%04d), %d\n", byState, m_iX, m_nX, m_iY, m_nY, bBtn0); OutputDebugString(szDbg);
|
||||||
|
m_byState |= byState;
|
||||||
|
CpuIrqAssert(IS_MOUSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMouseInterface::SetVBlank(bool bVBL)
|
||||||
|
{
|
||||||
|
if ( m_bVBL != bVBL )
|
||||||
|
{
|
||||||
|
m_bVBL = bVBL;
|
||||||
|
if ( m_bVBL ) // Rising edge
|
||||||
|
OnMouseEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMouseInterface::Reset()
|
||||||
|
{
|
||||||
|
m_nBuffPos = 0;
|
||||||
|
m_nDataLen = 1;
|
||||||
|
|
||||||
|
m_byMode = 0;
|
||||||
|
m_byState = 0;
|
||||||
|
m_nX = 0;
|
||||||
|
m_nY = 0;
|
||||||
|
m_bBtn0 = 0;
|
||||||
|
m_bBtn1 = 0;
|
||||||
|
ClampX( 0, 1023 );
|
||||||
|
ClampY( 0, 1023 );
|
||||||
|
SetPosition( 0, 0 );
|
||||||
|
|
||||||
|
// CpuIrqDeassert(IS_MOUSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
void CMouseInterface::ClampX(int iMinX, int iMaxX)
|
||||||
|
{
|
||||||
|
if ( iMinX < 0 || iMinX > iMaxX )
|
||||||
|
return;
|
||||||
|
m_iMaxX = iMaxX;
|
||||||
|
m_iMinX = iMinX;
|
||||||
|
if ( m_iX > m_iMaxX ) m_iX = m_iMaxX; else if ( m_iX < m_iMinX ) m_iX = m_iMinX;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMouseInterface::ClampY(int iMinY, int iMaxY)
|
||||||
|
{
|
||||||
|
if ( iMinY < 0 || iMinY > iMaxY )
|
||||||
|
return;
|
||||||
|
m_iMaxY = iMaxY;
|
||||||
|
m_iMinY = iMinY;
|
||||||
|
if ( m_iY > m_iMaxY ) m_iY = m_iMaxY; else if ( m_iY < m_iMinX ) m_iY = m_iMinY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMouseInterface::SetPosition(int xvalue, int yvalue)
|
||||||
|
{
|
||||||
|
if ((m_iRangeX == 0) || (m_iRangeY == 0))
|
||||||
|
{
|
||||||
|
m_iX = m_iMinX;
|
||||||
|
m_iY = m_iMinY;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_iX = (UINT) ((xvalue*m_iMaxX) / m_iRangeX);
|
||||||
|
m_iY = (UINT) ((yvalue*m_iMaxY) / m_iRangeY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMouseInterface::SetPosition(int xvalue, int xrange, int yvalue, int yrange)
|
||||||
|
{
|
||||||
|
m_iRangeX = (UINT) xrange;
|
||||||
|
m_iRangeY = (UINT) yrange;
|
||||||
|
|
||||||
|
SetPosition(xvalue, yvalue);
|
||||||
|
OnMouseEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMouseInterface::SetButton(eBUTTON Button, eBUTTONSTATE State)
|
||||||
|
{
|
||||||
|
m_bButtons[Button]= (State == BUTTON_DOWN) ? TRUE : FALSE;
|
||||||
|
OnMouseEvent();
|
||||||
|
}
|
79
source/MouseInterface.h
Normal file
79
source/MouseInterface.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#include "6821.h"
|
||||||
|
#include "Common.h"
|
||||||
|
|
||||||
|
#define WRITE_HANDLER(func) void func( void* objFrom, void* objTo, int nAddr, BYTE byData )
|
||||||
|
#define CALLBACK_HANDLER(func) void func( void* objFrom, void* objTo, LPARAM lParam )
|
||||||
|
|
||||||
|
extern class CMouseInterface sg_Mouse;
|
||||||
|
|
||||||
|
class CMouseInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CMouseInterface();
|
||||||
|
virtual ~CMouseInterface();
|
||||||
|
|
||||||
|
void Initialize(LPBYTE pCxRomPeripheral, UINT uSlot);
|
||||||
|
void Uninitialize(){ m_bActive = false; }
|
||||||
|
void SetSlotRom();
|
||||||
|
static BYTE __stdcall IORead(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValue, ULONG nCyclesLeft);
|
||||||
|
static BYTE __stdcall IOWrite(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValue, ULONG nCyclesLeft);
|
||||||
|
|
||||||
|
void SetPosition(int xvalue, int xrange, int yvalue, int yrange);
|
||||||
|
void SetButton(eBUTTON Button, eBUTTONSTATE State);
|
||||||
|
bool Active() { return m_bActive; }
|
||||||
|
void SetVBlank(bool bVBL);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void On6821_A(BYTE byData);
|
||||||
|
void On6821_B(BYTE byData);
|
||||||
|
void OnCommand();
|
||||||
|
void OnWrite();
|
||||||
|
void OnMouseEvent();
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
friend WRITE_HANDLER( M6821_Listener_A );
|
||||||
|
friend WRITE_HANDLER( M6821_Listener_B );
|
||||||
|
//friend CALLBACK_HANDLER( MouseHandler );
|
||||||
|
|
||||||
|
void SetPosition(int xvalue, int yvalue);
|
||||||
|
void ClampX(int iMinX, int iMaxX);
|
||||||
|
void ClampY(int iMinY, int iMaxY);
|
||||||
|
|
||||||
|
|
||||||
|
C6821 m_6821;
|
||||||
|
|
||||||
|
int m_nDataLen;
|
||||||
|
BYTE m_byMode;
|
||||||
|
|
||||||
|
BYTE m_by6821B;
|
||||||
|
BYTE m_by6821A;
|
||||||
|
BYTE m_byBuff[8]; // m_byBuff[0] is mode byte
|
||||||
|
int m_nBuffPos;
|
||||||
|
|
||||||
|
BYTE m_byState;
|
||||||
|
int m_nX;
|
||||||
|
int m_nY;
|
||||||
|
BOOL m_bBtn0;
|
||||||
|
BOOL m_bBtn1;
|
||||||
|
|
||||||
|
bool m_bVBL;
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
UINT m_iX;
|
||||||
|
UINT m_iRangeX;
|
||||||
|
UINT m_iMinX;
|
||||||
|
UINT m_iMaxX;
|
||||||
|
UINT m_iY;
|
||||||
|
UINT m_iRangeY;
|
||||||
|
UINT m_iMinY;
|
||||||
|
UINT m_iMaxY;
|
||||||
|
|
||||||
|
BOOL m_bButtons[2];
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
bool m_bActive;
|
||||||
|
LPBYTE m_pSlotRom;
|
||||||
|
UINT m_uSlot;
|
||||||
|
};
|
@ -101,6 +101,9 @@ enum {PG_CONFIG=0, PG_INPUT, PG_SOUND, PG_SAVESTATE, PG_DISK, PG_NUM_SHEETS};
|
|||||||
|
|
||||||
UINT g_nLastPage = PG_CONFIG;
|
UINT g_nLastPage = PG_CONFIG;
|
||||||
|
|
||||||
|
UINT g_uScrollLockToggle = 0;
|
||||||
|
UINT g_uMouseInSlot4 = 0;
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
static void FillComboBox (HWND window, int controlid, LPCTSTR choices, int currentchoice)
|
static void FillComboBox (HWND window, int controlid, LPCTSTR choices, int currentchoice)
|
||||||
@ -224,15 +227,17 @@ static void ConfigDlg_OK(HWND window, BOOL afterclose)
|
|||||||
if (NewApple2Type != g_Apple2Type)
|
if (NewApple2Type != g_Apple2Type)
|
||||||
{
|
{
|
||||||
if (MessageBox(window,
|
if (MessageBox(window,
|
||||||
TEXT(
|
TEXT(
|
||||||
"You have changed the emulated computer "
|
"You have changed the emulated computer "
|
||||||
"type. This change will not take effect "
|
"type. This change will not take effect "
|
||||||
"until the next time you restart the "
|
"until the next time you restart the "
|
||||||
"emulator.\n\n"
|
"emulator.\n\n"
|
||||||
"Would you like to restart the emulator now?"),
|
"Would you like to restart the emulator now?"),
|
||||||
TEXT("Configuration"),
|
TEXT("Configuration"),
|
||||||
MB_ICONQUESTION | MB_YESNO | MB_SETFOREGROUND) == IDYES)
|
MB_ICONQUESTION | MB_YESNO | MB_SETFOREGROUND) == IDYES)
|
||||||
|
{
|
||||||
afterclose = WM_USER_RESTART;
|
afterclose = WM_USER_RESTART;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (videotype != newvidtype)
|
if (videotype != newvidtype)
|
||||||
@ -257,6 +262,7 @@ static void ConfigDlg_OK(HWND window, BOOL afterclose)
|
|||||||
SAVE(TEXT("Custom Speed") ,IsDlgButtonChecked(window,IDC_CUSTOM_SPEED));
|
SAVE(TEXT("Custom Speed") ,IsDlgButtonChecked(window,IDC_CUSTOM_SPEED));
|
||||||
SAVE(TEXT("Emulation Speed") ,g_dwSpeed);
|
SAVE(TEXT("Emulation Speed") ,g_dwSpeed);
|
||||||
SAVE(TEXT("Video Emulation") ,videotype);
|
SAVE(TEXT("Video Emulation") ,videotype);
|
||||||
|
SAVE(TEXT(REGVALUE_MOUSE_IN_SLOT4),g_uMouseInSlot4);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
@ -332,6 +338,31 @@ static BOOL CALLBACK ConfigDlgProc (HWND window,
|
|||||||
VideoChooseColor();
|
VideoChooseColor();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IDC_MOUSE_IN_SLOT4:
|
||||||
|
UINT uNewState = IsDlgButtonChecked(window, IDC_MOUSE_IN_SLOT4) ? 1 : 0;
|
||||||
|
LPCSTR pMsg = uNewState ?
|
||||||
|
TEXT("The emulator needs to restart as the slot configuration has changed.\n")
|
||||||
|
TEXT("Also Mockingboard/Phasor cards won't be available in slot 4.\n\n")
|
||||||
|
TEXT("Would you like to restart the emulator now?")
|
||||||
|
:
|
||||||
|
TEXT("The emulator needs to restart as the slot configuration has changed.\n")
|
||||||
|
TEXT("(Mockingboard/Phasor cards will now be available in slot 4.)\n\n")
|
||||||
|
TEXT("Would you like to restart the emulator now?");
|
||||||
|
if (MessageBox(window,
|
||||||
|
pMsg,
|
||||||
|
TEXT("Configuration"),
|
||||||
|
MB_ICONQUESTION | MB_YESNO | MB_SETFOREGROUND) == IDYES)
|
||||||
|
{
|
||||||
|
g_uMouseInSlot4 = uNewState;
|
||||||
|
afterclose = WM_USER_RESTART;
|
||||||
|
PropSheet_PressButton(GetParent(window), PSBTN_OK);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CheckDlgButton(window, IDC_MOUSE_IN_SLOT4, g_uMouseInSlot4 ? BST_CHECKED : BST_UNCHECKED);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
case IDC_RECALIBRATE:
|
case IDC_RECALIBRATE:
|
||||||
RegSaveValue(TEXT(""),TEXT("RunningOnOS"),0,0);
|
RegSaveValue(TEXT(""),TEXT("RunningOnOS"),0,0);
|
||||||
@ -384,6 +415,8 @@ static BOOL CALLBACK ConfigDlgProc (HWND window,
|
|||||||
EnableTrackbar(window, custom);
|
EnableTrackbar(window, custom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CheckDlgButton(window, IDC_MOUSE_IN_SLOT4, g_uMouseInSlot4 ? BST_CHECKED : BST_UNCHECKED);
|
||||||
|
|
||||||
afterclose = 0;
|
afterclose = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -444,6 +477,7 @@ static void InputDlg_OK(HWND window, BOOL afterclose)
|
|||||||
SAVE(TEXT("Joystick 1 Emulation"),joytype[1]);
|
SAVE(TEXT("Joystick 1 Emulation"),joytype[1]);
|
||||||
SAVE(TEXT(REGVALUE_PDL_XTRIM),JoyGetTrim(true));
|
SAVE(TEXT(REGVALUE_PDL_XTRIM),JoyGetTrim(true));
|
||||||
SAVE(TEXT(REGVALUE_PDL_YTRIM),JoyGetTrim(false));
|
SAVE(TEXT(REGVALUE_PDL_YTRIM),JoyGetTrim(false));
|
||||||
|
SAVE(TEXT(REGVALUE_SCROLLLOCK_TOGGLE),g_uScrollLockToggle);
|
||||||
// SAVE(TEXT(REGVALUE_KEYB_BUFFER_ENABLE),KeybGetBufferMode() ? 1 : 0);
|
// SAVE(TEXT(REGVALUE_KEYB_BUFFER_ENABLE),KeybGetBufferMode() ? 1 : 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -527,11 +561,14 @@ static BOOL CALLBACK InputDlgProc (HWND window,
|
|||||||
InitJoystickChoices(window, JN_JOYSTICK0, IDC_JOYSTICK0); // Re-init joy0 list
|
InitJoystickChoices(window, JN_JOYSTICK0, IDC_JOYSTICK0); // Re-init joy0 list
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// case IDC_KEYB_BUFFER_ENABLE:
|
case IDC_SCROLLLOCK_TOGGLE:
|
||||||
// break;
|
g_uScrollLockToggle = IsDlgButtonChecked(window, IDC_SCROLLLOCK_TOGGLE) ? 1 : 0;
|
||||||
|
break;
|
||||||
case IDC_PASTE_FROM_CLIPBOARD:
|
case IDC_PASTE_FROM_CLIPBOARD:
|
||||||
ClipboardInitiatePaste();
|
ClipboardInitiatePaste();
|
||||||
break;
|
break;
|
||||||
|
// case IDC_KEYB_BUFFER_ENABLE:
|
||||||
|
// break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -548,6 +585,7 @@ static BOOL CALLBACK InputDlgProc (HWND window,
|
|||||||
SendDlgItemMessage(window, IDC_SPIN_XTRIM, UDM_SETPOS, 0, MAKELONG(JoyGetTrim(true),0));
|
SendDlgItemMessage(window, IDC_SPIN_XTRIM, UDM_SETPOS, 0, MAKELONG(JoyGetTrim(true),0));
|
||||||
SendDlgItemMessage(window, IDC_SPIN_YTRIM, UDM_SETPOS, 0, MAKELONG(JoyGetTrim(false),0));
|
SendDlgItemMessage(window, IDC_SPIN_YTRIM, UDM_SETPOS, 0, MAKELONG(JoyGetTrim(false),0));
|
||||||
|
|
||||||
|
CheckDlgButton(window, IDC_SCROLLLOCK_TOGGLE, g_uScrollLockToggle ? BST_CHECKED : BST_UNCHECKED);
|
||||||
// CheckDlgButton(window, IDC_KEYB_BUFFER_ENABLE, KeybGetBufferMode() ? BST_CHECKED : BST_UNCHECKED);
|
// CheckDlgButton(window, IDC_KEYB_BUFFER_ENABLE, KeybGetBufferMode() ? BST_CHECKED : BST_UNCHECKED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -675,6 +713,11 @@ static BOOL CALLBACK SoundDlgProc (HWND window,
|
|||||||
|
|
||||||
CheckRadioButton(window, IDC_MB_ENABLE, IDC_SOUNDCARD_DISABLE, nID);
|
CheckRadioButton(window, IDC_MB_ENABLE, IDC_SOUNDCARD_DISABLE, nID);
|
||||||
|
|
||||||
|
if (g_uMouseInSlot4)
|
||||||
|
{
|
||||||
|
EnableWindow(GetDlgItem(window, IDC_PHASOR_ENABLE), FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
afterclose = 0;
|
afterclose = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -734,7 +777,18 @@ static int SaveStateSelectImage(HWND hWindow, TCHAR* pszTitle, bool bSave)
|
|||||||
TCHAR szDirectory[MAX_PATH] = TEXT("");
|
TCHAR szDirectory[MAX_PATH] = TEXT("");
|
||||||
TCHAR szFilename[MAX_PATH];
|
TCHAR szFilename[MAX_PATH];
|
||||||
|
|
||||||
strcpy(szFilename, Snapshot_GetFilename());
|
// Attempt to use drive1's image name as the name for the .aws file
|
||||||
|
LPCTSTR pDiskName0 = DiskGetName(0);
|
||||||
|
if (pDiskName0 && pDiskName0[0])
|
||||||
|
{
|
||||||
|
strcpy(szFilename, pDiskName0);
|
||||||
|
strcpy(&szFilename[strlen(pDiskName0)], ".aws");
|
||||||
|
// NB. OK'ing this property sheet will call Snapshot_SetFilename() with this new filename
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strcpy(szFilename, Snapshot_GetFilename());
|
||||||
|
}
|
||||||
|
|
||||||
RegLoadString(TEXT("Preferences"),REGVALUE_PREF_START_DIR,1,szDirectory,MAX_PATH);
|
RegLoadString(TEXT("Preferences"),REGVALUE_PREF_START_DIR,1,szDirectory,MAX_PATH);
|
||||||
|
|
||||||
|
@ -6,3 +6,6 @@ bool PSP_SaveStateSelectImage(HWND hWindow, bool bSave);
|
|||||||
void ui_tfe_settings_dialog(HWND hwnd);
|
void ui_tfe_settings_dialog(HWND hwnd);
|
||||||
void * get_tfe_interface(void);
|
void * get_tfe_interface(void);
|
||||||
void get_tfe_enabled(int *tfe_enabled);
|
void get_tfe_enabled(int *tfe_enabled);
|
||||||
|
|
||||||
|
extern UINT g_uScrollLockToggle;
|
||||||
|
extern UINT g_uMouseInSlot4;
|
||||||
|
@ -87,10 +87,6 @@ CSuperSerialCard::CSuperSerialCard()
|
|||||||
memset(&m_o, 0, sizeof(m_o));
|
memset(&m_o, 0, sizeof(m_o));
|
||||||
}
|
}
|
||||||
|
|
||||||
CSuperSerialCard::~CSuperSerialCard()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
// TODO: Serial Comms - UI Property Sheet Page:
|
// TODO: Serial Comms - UI Property Sheet Page:
|
||||||
|
@ -23,7 +23,7 @@ class CSuperSerialCard
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CSuperSerialCard();
|
CSuperSerialCard();
|
||||||
~CSuperSerialCard();
|
virtual ~CSuperSerialCard() {}
|
||||||
|
|
||||||
void CommInitialize(LPBYTE pCxRomPeripheral, UINT uSlot);
|
void CommInitialize(LPBYTE pCxRomPeripheral, UINT uSlot);
|
||||||
void CommReset();
|
void CommReset();
|
||||||
|
@ -492,7 +492,7 @@ BYTE __stdcall SpkrToggle (WORD, WORD, BYTE, BYTE, ULONG nCyclesLeft)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return MemReadFloatingBus();
|
return MemReadFloatingBus(nCyclesLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
@ -802,7 +802,7 @@ static ULONG Spkr_SubmitWaveBuffer_FullSpeed(short* pSpeakerBuffer, ULONG nNumSa
|
|||||||
|
|
||||||
static ULONG Spkr_SubmitWaveBuffer(short* pSpeakerBuffer, ULONG nNumSamples)
|
static ULONG Spkr_SubmitWaveBuffer(short* pSpeakerBuffer, ULONG nNumSamples)
|
||||||
{
|
{
|
||||||
char szDbg[200];
|
//char szDbg[200];
|
||||||
nDbgSpkrCnt++;
|
nDbgSpkrCnt++;
|
||||||
|
|
||||||
if(!SpeakerVoice.bActive)
|
if(!SpeakerVoice.bActive)
|
||||||
@ -838,7 +838,7 @@ static ULONG Spkr_SubmitWaveBuffer(short* pSpeakerBuffer, ULONG nNumSamples)
|
|||||||
|
|
||||||
dwByteOffset = dwCurrentPlayCursor + (g_dwDSSpkrBufferSize/8)*3; // Ideal: 0.375 is between 0.25 & 0.50 full
|
dwByteOffset = dwCurrentPlayCursor + (g_dwDSSpkrBufferSize/8)*3; // Ideal: 0.375 is between 0.25 & 0.50 full
|
||||||
dwByteOffset %= g_dwDSSpkrBufferSize;
|
dwByteOffset %= g_dwDSSpkrBufferSize;
|
||||||
sprintf(szDbg, "[Submit] PC=%08X, WC=%08X, Diff=%08X, Off=%08X [REINIT]\n", dwCurrentPlayCursor, dwCurrentWriteCursor, dwCurrentWriteCursor-dwCurrentPlayCursor, dwByteOffset); OutputDebugString(szDbg);
|
//sprintf(szDbg, "[Submit] PC=%08X, WC=%08X, Diff=%08X, Off=%08X [REINIT]\n", dwCurrentPlayCursor, dwCurrentWriteCursor, dwCurrentWriteCursor-dwCurrentPlayCursor, dwByteOffset); OutputDebugString(szDbg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -849,7 +849,7 @@ static ULONG Spkr_SubmitWaveBuffer(short* pSpeakerBuffer, ULONG nNumSamples)
|
|||||||
// |-----PxxxxxW-----|
|
// |-----PxxxxxW-----|
|
||||||
if((dwByteOffset > dwCurrentPlayCursor) && (dwByteOffset < dwCurrentWriteCursor))
|
if((dwByteOffset > dwCurrentPlayCursor) && (dwByteOffset < dwCurrentWriteCursor))
|
||||||
{
|
{
|
||||||
sprintf(szDbg, "[Submit] PC=%08X, WC=%08X, Diff=%08X, Off=%08X, NS=%08X xxx\n", dwCurrentPlayCursor, dwCurrentWriteCursor, dwCurrentWriteCursor-dwCurrentPlayCursor, dwByteOffset, nNumSamples); OutputDebugString(szDbg);
|
//sprintf(szDbg, "[Submit] PC=%08X, WC=%08X, Diff=%08X, Off=%08X, NS=%08X xxx\n", dwCurrentPlayCursor, dwCurrentWriteCursor, dwCurrentWriteCursor-dwCurrentPlayCursor, dwByteOffset, nNumSamples); OutputDebugString(szDbg);
|
||||||
dwByteOffset = dwCurrentWriteCursor;
|
dwByteOffset = dwCurrentWriteCursor;
|
||||||
nNumSamplesError = 0;
|
nNumSamplesError = 0;
|
||||||
bBufferError = true;
|
bBufferError = true;
|
||||||
@ -860,7 +860,7 @@ static ULONG Spkr_SubmitWaveBuffer(short* pSpeakerBuffer, ULONG nNumSamples)
|
|||||||
// |xxW----------Pxxx|
|
// |xxW----------Pxxx|
|
||||||
if((dwByteOffset > dwCurrentPlayCursor) || (dwByteOffset < dwCurrentWriteCursor))
|
if((dwByteOffset > dwCurrentPlayCursor) || (dwByteOffset < dwCurrentWriteCursor))
|
||||||
{
|
{
|
||||||
sprintf(szDbg, "[Submit] PC=%08X, WC=%08X, Diff=%08X, Off=%08X, NS=%08X XXX\n", dwCurrentPlayCursor, dwCurrentWriteCursor, dwCurrentWriteCursor-dwCurrentPlayCursor, dwByteOffset, nNumSamples); OutputDebugString(szDbg);
|
//sprintf(szDbg, "[Submit] PC=%08X, WC=%08X, Diff=%08X, Off=%08X, NS=%08X XXX\n", dwCurrentPlayCursor, dwCurrentWriteCursor, dwCurrentWriteCursor-dwCurrentPlayCursor, dwByteOffset, nNumSamples); OutputDebugString(szDbg);
|
||||||
dwByteOffset = dwCurrentWriteCursor;
|
dwByteOffset = dwCurrentWriteCursor;
|
||||||
nNumSamplesError = 0;
|
nNumSamplesError = 0;
|
||||||
bBufferError = true;
|
bBufferError = true;
|
||||||
|
@ -147,6 +147,7 @@ enum SS_CARDTYPE
|
|||||||
CT_GenericPrinter,
|
CT_GenericPrinter,
|
||||||
CT_GenericHDD, // Hard disk
|
CT_GenericHDD, // Hard disk
|
||||||
CT_GenericClock,
|
CT_GenericClock,
|
||||||
|
CT_MouseInterface,
|
||||||
};
|
};
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1570,11 +1570,11 @@ void VideoBenchmark () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
BYTE __stdcall VideoCheckMode (WORD, WORD address, BYTE, BYTE, ULONG)
|
BYTE __stdcall VideoCheckMode (WORD, WORD address, BYTE, BYTE, ULONG nCyclesLeft)
|
||||||
{
|
{
|
||||||
address &= 0xFF;
|
address &= 0xFF;
|
||||||
if (address == 0x7F)
|
if (address == 0x7F)
|
||||||
return MemReadFloatingBus(SW_DHIRES != 0);
|
return MemReadFloatingBus(SW_DHIRES != 0, nCyclesLeft);
|
||||||
else {
|
else {
|
||||||
BOOL result = 0;
|
BOOL result = 0;
|
||||||
switch (address) {
|
switch (address) {
|
||||||
@ -1601,7 +1601,7 @@ void VideoCheckPage (BOOL force) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
BYTE __stdcall VideoCheckVbl (WORD, WORD, BYTE, BYTE, ULONG)
|
BYTE __stdcall VideoCheckVbl (WORD, WORD, BYTE, BYTE, ULONG nCyclesLeft)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
// Drol expects = 80
|
// Drol expects = 80
|
||||||
@ -1644,7 +1644,7 @@ BYTE __stdcall VideoCheckVbl (WORD, WORD, BYTE, BYTE, ULONG)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
bool bVblBar;
|
bool bVblBar;
|
||||||
VideoGetScannerAddress(&bVblBar);
|
VideoGetScannerAddress(&bVblBar, nCyclesLeft);
|
||||||
BYTE r = KeybGetKeycode();
|
BYTE r = KeybGetKeycode();
|
||||||
return (r & ~0x80) | ((bVblBar) ? 0x80 : 0);
|
return (r & ~0x80) | ((bVblBar) ? 0x80 : 0);
|
||||||
}
|
}
|
||||||
@ -2042,7 +2042,7 @@ void VideoResetState () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
BYTE __stdcall VideoSetMode (WORD, WORD address, BYTE write, BYTE, ULONG)
|
BYTE __stdcall VideoSetMode (WORD, WORD address, BYTE write, BYTE, ULONG nCyclesLeft)
|
||||||
{
|
{
|
||||||
address &= 0xFF;
|
address &= 0xFF;
|
||||||
DWORD oldpage2 = SW_PAGE2;
|
DWORD oldpage2 = SW_PAGE2;
|
||||||
@ -2097,7 +2097,7 @@ BYTE __stdcall VideoSetMode (WORD, WORD address, BYTE write, BYTE, ULONG)
|
|||||||
}
|
}
|
||||||
lastpageflip = emulmsec;
|
lastpageflip = emulmsec;
|
||||||
}
|
}
|
||||||
return MemReadFloatingBus();
|
return MemReadFloatingBus(nCyclesLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
@ -2160,11 +2160,11 @@ DWORD VideoSetSnapshot(SS_IO_Video* pSS)
|
|||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
WORD VideoGetScannerAddress(bool* pbVblBar_OUT)
|
WORD VideoGetScannerAddress(bool* pbVblBar_OUT, const DWORD uExecutedCycles)
|
||||||
{
|
{
|
||||||
// get video scanner position
|
// get video scanner position
|
||||||
//
|
//
|
||||||
int nCycles = CpuGetCyclesThisFrame();
|
int nCycles = CpuGetCyclesThisFrame(uExecutedCycles);
|
||||||
|
|
||||||
// machine state switches
|
// machine state switches
|
||||||
//
|
//
|
||||||
@ -2270,3 +2270,39 @@ WORD VideoGetScannerAddress(bool* pbVblBar_OUT)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
|
// Derived from VideoGetScannerAddress()
|
||||||
|
bool VideoGetVbl(const DWORD uExecutedCycles)
|
||||||
|
{
|
||||||
|
// get video scanner position
|
||||||
|
//
|
||||||
|
int nCycles = CpuGetCyclesThisFrame(uExecutedCycles);
|
||||||
|
|
||||||
|
// calculate video parameters according to display standard
|
||||||
|
//
|
||||||
|
int nScanLines = bVideoScannerNTSC ? kNTSCScanLines : kPALScanLines;
|
||||||
|
|
||||||
|
// calculate vertical scanning state
|
||||||
|
//
|
||||||
|
int nVLine = nCycles / kHClocks; // which vertical scanning line
|
||||||
|
int nVState = kVLine0State + nVLine; // V state bits
|
||||||
|
if ((nVLine >= kVPresetLine)) // check for previous vertical state preset
|
||||||
|
{
|
||||||
|
nVState -= nScanLines; // compensate for preset
|
||||||
|
}
|
||||||
|
int v_3 = (nVState >> 6) & 1;
|
||||||
|
int v_4 = (nVState >> 7) & 1;
|
||||||
|
|
||||||
|
// update VBL' state
|
||||||
|
//
|
||||||
|
if (v_4 & v_3) // VBL?
|
||||||
|
{
|
||||||
|
return false; // Y: VBL' is false
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true; // N: VBL' is true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
@ -63,7 +63,8 @@ void VideoRedrawScreen ();
|
|||||||
void VideoRefreshScreen ();
|
void VideoRefreshScreen ();
|
||||||
void VideoReinitialize ();
|
void VideoReinitialize ();
|
||||||
void VideoResetState ();
|
void VideoResetState ();
|
||||||
WORD VideoGetScannerAddress(bool* pbVblBar_OUT = NULL);
|
WORD VideoGetScannerAddress(bool* pbVblBar_OUT, const DWORD uExecutedCycles);
|
||||||
|
bool VideoGetVbl(DWORD uExecutedCycles);
|
||||||
void VideoUpdateVbl (DWORD dwCyclesThisFrame);
|
void VideoUpdateVbl (DWORD dwCyclesThisFrame);
|
||||||
void VideoUpdateFlash();
|
void VideoUpdateFlash();
|
||||||
bool VideoGetSW80COL();
|
bool VideoGetSW80COL();
|
||||||
|
Loading…
Reference in New Issue
Block a user