2015-10-24 12:56:00 +00:00
/*
AppleWin : An Apple //e emulator for Windows
Copyright ( C ) 1994 - 1996 , Michael O ' Brien
Copyright ( C ) 1999 - 2001 , Oliver Schmidt
Copyright ( C ) 2002 - 2005 , Tom Charlesworth
Copyright ( C ) 2006 - 2007 , Tom Charlesworth , Michael Pohoreski
AppleWin is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
AppleWin is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with AppleWin ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
/* Description: main
*
* Author : Various
*/
/* Adaptation for SDL and POSIX (l) by beom beotiger, Nov-Dec 2007, krez beotiger March 2012 AD */
/*
Linappple - pie was adapted in OCT 2015 for use with Retropie .
By Mark Ormond .
*/
# include "stdafx.h"
//#pragma hdrstop
# include "MouseInterface.h"
// for time logging
# include <time.h>
# include <sys/time.h>
# include <curl/curl.h>
# include <stdlib.h>
# include <getopt.h>
2015-10-27 23:10:50 +00:00
# include <strings.h>
# include <fstream>
2015-10-24 12:56:00 +00:00
//char VERSIONSTRING[] = "xx.yy.zz.ww";
TCHAR * g_pAppTitle = TITLE_APPLE_2E_ENHANCED ;
eApple2Type g_Apple2Type = A2TYPE_APPLE2EEHANCED ;
int opt ;
2015-10-27 23:10:50 +00:00
bool argdisks = false ;
bool argdisks2 = false ;
bool autoboot = false ;
2015-10-30 20:31:40 +00:00
bool fullscreenboot = false ;
2015-11-02 22:03:02 +00:00
bool disablecursor = false ;
2015-10-24 12:56:00 +00:00
BOOL behind = 0 ; // Redundant
DWORD cumulativecycles = 0 ; // Wraps after ~1hr 9mins
DWORD cyclenum = 0 ; // Used by SpkrToggle() for non-wave sound
DWORD emulmsec = 0 ;
static DWORD emulmsec_frac = 0 ;
bool g_bFullSpeed = false ;
bool hddenabled = false ;
static bool g_uMouseInSlot4 = false ; // not any mouse in slot4??--bb
2015-10-27 23:10:50 +00:00
//char *MASTER_DISK="/opt/retropie/emulators/linapple/Master.dsk";
char * Disk1 = " blank.dsk " ;
char * Disk2 = " blank.dsk " ;
2015-10-24 12:56:00 +00:00
// Win32
//HINSTANCE g_hInstance = (HINSTANCE)0;
AppMode_e g_nAppMode = MODE_LOGO ;
// Default screen sizes
// SCREEN_WIDTH & SCREEN_HEIGHT defined in Frame.h
UINT g_ScreenWidth = SCREEN_WIDTH ;
UINT g_ScreenHeight = SCREEN_HEIGHT ;
//static int lastmode = MODE_LOGO; -- not used???
DWORD needsprecision = 0 ; // Redundant
//TCHAR g_sProgramDir[MAX_PATH] = TEXT("");
TCHAR g_sCurrentDir [ MAX_PATH ] = TEXT ( " " ) ; // Also Starting Dir for Slot6 disk images?? --bb
TCHAR g_sHDDDir [ MAX_PATH ] = TEXT ( " " ) ; // starting dir for HDV (Apple][ HDD) images?? --bb
TCHAR g_sSaveStateDir [ MAX_PATH ] = TEXT ( " " ) ; // starting dir for states --bb
TCHAR g_sParallelPrinterFile [ MAX_PATH ] = TEXT ( " Printer.txt " ) ; // default file name for Parallel printer
// FTP Variables
TCHAR g_sFTPLocalDir [ MAX_PATH ] = TEXT ( " " ) ; // FTP Local Dir, see linapple.conf for details
TCHAR g_sFTPServer [ MAX_PATH ] = TEXT ( " " ) ; // full path to default FTP server
TCHAR g_sFTPServerHDD [ MAX_PATH ] = TEXT ( " " ) ; // full path to default FTP server
//TCHAR g_sFTPUser[256] = TEXT("anonymous"); // user name
//TCHAR g_sFTPPass[256] = TEXT("mymail@hotmail.com"); // password
TCHAR g_sFTPUserPass [ 512 ] = TEXT ( " anonymous:mymail@hotmail.com " ) ; // full login line
bool g_bResetTiming = false ; // Redundant
BOOL restart = 0 ;
// several parameters affecting the speed of emulated CPU
DWORD g_dwSpeed = SPEED_NORMAL ; // Affected by Config dialog's speed slider bar
double g_fCurrentCLK6502 = CLK_6502 ; // Affected by Config dialog's speed slider bar
static double g_fMHz = 1.0 ; // Affected by Config dialog's speed slider bar
int g_nCpuCyclesFeedback = 0 ;
DWORD g_dwCyclesThisFrame = 0 ;
FILE * g_fh = NULL ; // file for logging, let's use stderr instead?
bool g_bDisableDirectSound = false ; // direct sound, use SDL Sound, or SDL_mixer???
CSuperSerialCard sg_SSC ;
CMouseInterface sg_Mouse ;
UINT g_Slot4 = CT_Mockingboard ; // CT_Mockingboard or CT_MouseInterface
CURL * g_curl = NULL ; // global easy curl resourse
//===========================================================================
// ???? what is DBG_CALC_FREQ??? O_O --bb
# define DBG_CALC_FREQ 0
# if DBG_CALC_FREQ
const UINT MAX_CNT = 256 ;
double g_fDbg [ MAX_CNT ] ;
UINT g_nIdx = 0 ;
double g_fMeanPeriod , g_fMeanFreq ;
ULONG g_nPerfFreq = 0 ;
# endif
//---------------------------------------------------------------------------
void ContinueExecution ( )
{
static BOOL pageflipping = 0 ; //?
const double fUsecPerSec = 1.e6 ;
const UINT nExecutionPeriodUsec = 1000 ; // 1.0ms
const double fExecutionPeriodClks = g_fCurrentCLK6502 * ( ( double ) nExecutionPeriodUsec / fUsecPerSec ) ;
bool bScrollLock_FullSpeed = g_bScrollLock_FullSpeed ; //g_uScrollLockToggle;
g_bFullSpeed = ( ( g_dwSpeed = = SPEED_MAX ) | |
bScrollLock_FullSpeed | |
( DiskIsSpinning ( ) & & enhancedisk & & ! Spkr_IsActive ( ) & & ! MB_IsActive ( ) ) ) ;
if ( g_bFullSpeed )
{
// Don't call Spkr_Mute() - will get speaker clicks
MB_Mute ( ) ;
SysClk_StopTimer ( ) ;
g_nCpuCyclesFeedback = 0 ; // For the case when this is a big -ve number
// SetPriorityNormal();
}
else
{
// Don't call Spkr_Demute()
MB_Demute ( ) ;
SysClk_StartTimerUsec ( nExecutionPeriodUsec ) ;
// Switch to higher priority, eg. for audio (BUG #015394)
// SetPriorityAboveNormal();
}
//
int nCyclesToExecute = ( int ) fExecutionPeriodClks + g_nCpuCyclesFeedback ;
if ( nCyclesToExecute < 0 )
nCyclesToExecute = 0 ;
DWORD dwExecutedCycles = CpuExecute ( nCyclesToExecute ) ;
g_dwCyclesThisFrame + = dwExecutedCycles ;
//
cyclenum = dwExecutedCycles ;
DiskUpdatePosition ( dwExecutedCycles ) ;
JoyUpdatePosition ( ) ;
// the next call does not present in current Applewin as on March 2012??
VideoUpdateVbl ( g_dwCyclesThisFrame ) ;
SpkrUpdate ( cyclenum ) ;
sg_SSC . CommUpdate ( cyclenum ) ;
PrintUpdate ( cyclenum ) ;
//
const DWORD CLKS_PER_MS = ( DWORD ) g_fCurrentCLK6502 / 1000 ;
emulmsec_frac + = dwExecutedCycles ;
if ( emulmsec_frac > CLKS_PER_MS )
{
emulmsec + = emulmsec_frac / CLKS_PER_MS ;
emulmsec_frac % = CLKS_PER_MS ;
}
//
// DETERMINE WHETHER THE SCREEN WAS UPDATED, THE DISK WAS SPINNING,
// OR THE KEYBOARD I/O PORTS WERE BEING EXCESSIVELY QUERIED THIS CLOCKTICK
VideoCheckPage ( 0 ) ;
BOOL screenupdated = VideoHasRefreshed ( ) ;
BOOL systemidle = 0 ; //(KeybGetNumQueries() > (clockgran << 2)); // && (!ranfinegrain); // TO DO
if ( screenupdated )
pageflipping = 3 ;
//
if ( g_dwCyclesThisFrame > = dwClksPerFrame )
{
g_dwCyclesThisFrame - = dwClksPerFrame ;
if ( g_nAppMode ! = MODE_LOGO )
{
VideoUpdateFlash ( ) ;
static BOOL anyupdates = 0 ;
static DWORD lastcycles = 0 ;
static BOOL lastupdates [ 2 ] = { 0 , 0 } ;
anyupdates | = screenupdated ;
//
lastcycles = cumulativecycles ;
if ( ( ! anyupdates ) & & ( ! lastupdates [ 0 ] ) & & ( ! lastupdates [ 1 ] ) & & VideoApparentlyDirty ( ) )
{
VideoCheckPage ( 1 ) ;
static DWORD lasttime = 0 ;
DWORD currtime = GetTickCount ( ) ;
if ( ( ! g_bFullSpeed ) | |
( currtime - lasttime > = ( DWORD ) ( ( graphicsmode | | ! systemidle ) ? 100 : 25 ) ) )
{
VideoRefreshScreen ( ) ;
lasttime = currtime ;
}
screenupdated = 1 ;
}
lastupdates [ 1 ] = lastupdates [ 0 ] ;
lastupdates [ 0 ] = anyupdates ;
anyupdates = 0 ;
if ( pageflipping )
pageflipping - - ;
}
MB_EndOfVideoFrame ( ) ;
}
//
if ( ! g_bFullSpeed )
{
SysClk_WaitTimer ( ) ;
# if DBG_CALC_FREQ
if ( g_nPerfFreq )
{
//QueryPerformanceCounter((LARGE_INTEGER*)&nTime1); QueryPerformanceFrequency
LONG nTime1 = GetTickCount ( ) ; //no QueryPerformanceCounter and alike
LONG nTimeDiff = nTime1 - nTime0 ;
double fTime = ( double ) nTimeDiff / ( double ) ( LONG ) g_nPerfFreq ;
g_fDbg [ g_nIdx ] = fTime ;
g_nIdx = ( g_nIdx + 1 ) & ( MAX_CNT - 1 ) ;
g_fMeanPeriod = 0.0 ;
for ( UINT n = 0 ; n < MAX_CNT ; n + + )
g_fMeanPeriod + = g_fDbg [ n ] ;
g_fMeanPeriod / = ( double ) MAX_CNT ;
g_fMeanFreq = 1.0 / g_fMeanPeriod ;
}
# endif
}
}
//===========================================================================
void SetCurrentCLK6502 ( )
{
static DWORD dwPrevSpeed = ( DWORD ) - 1 ;
if ( dwPrevSpeed = = g_dwSpeed )
return ;
dwPrevSpeed = g_dwSpeed ;
// SPEED_MIN = 0 = 0.50 MHz
// SPEED_NORMAL = 10 = 1.00 MHz
// 20 = 2.00 MHz
// SPEED_MAX-1 = 39 = 3.90 MHz
// SPEED_MAX = 40 = ???? MHz (run full-speed, /g_fCurrentCLK6502/ is ignored)
if ( g_dwSpeed < SPEED_NORMAL )
g_fMHz = 0.5 + ( double ) g_dwSpeed * 0.05 ;
else
g_fMHz = ( double ) g_dwSpeed / 10.0 ;
g_fCurrentCLK6502 = CLK_6502 * g_fMHz ;
//
// Now re-init modules that are dependent on /g_fCurrentCLK6502/
//
SpkrReinitialize ( ) ;
MB_Reinitialize ( ) ;
}
//===========================================================================
void EnterMessageLoop ( )
{
// MSG message;
SDL_Event event ;
// PeekMessage(&message, NULL, 0, 0, PM_NOREMOVE);
while ( true )
// while (message.message!=WM_QUIT)
{
if ( SDL_PollEvent ( & event ) )
{
if ( event . type = = SDL_QUIT & & event . key . keysym . sym ! = SDLK_F4 ) return ;
FrameDispatchMessage ( & event ) ;
// if (PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
// {
// TranslateMessage(&message);
// DispatchMessage(&message);
while ( ( g_nAppMode = = MODE_RUNNING ) | | ( g_nAppMode = = MODE_STEPPING ) )
{
if ( SDL_PollEvent ( & event ) ) {
if ( event . type = = SDL_QUIT & & event . key . keysym . sym ! = SDLK_F4 ) return ;
FrameDispatchMessage ( & event ) ;
}
else if ( g_nAppMode = = MODE_STEPPING )
{
DebugContinueStepping ( ) ;
}
else
{
ContinueExecution ( ) ;
if ( g_nAppMode ! = MODE_DEBUG )
{
2016-03-13 21:30:46 +00:00
if ( joyexitenable )
{
CheckJoyExit ( ) ;
if ( joyquitevent ) return ;
}
2015-10-24 12:56:00 +00:00
if ( g_bFullSpeed )
ContinueExecution ( ) ;
}
}
}
}
else
{
if ( g_nAppMode = = MODE_DEBUG )
DebuggerUpdate ( ) ;
else if ( g_nAppMode = = MODE_LOGO | | g_nAppMode = = MODE_PAUSED )
SDL_Delay ( 100 ) ; // Stop process hogging CPU
}
}
}
//===========================================================================
// void GetProgramDirectory () {
// GetModuleFileName((HINSTANCE)0,g_sProgramDir,MAX_PATH);
// g_sProgramDir[MAX_PATH-1] = 0;
// int loop = _tcslen(g_sProgramDir);
// while (loop--)
// if ((g_sProgramDir[loop] == TEXT('\\')) ||
// (g_sProgramDir[loop] == TEXT(':'))) {
// g_sProgramDir[loop+1] = 0;
// break;
// }
// }
//---------------------------------------------------------------------------
int DoDiskInsert ( int nDrive , LPSTR szFileName )
{
// DWORD dwAttributes = GetFileAttributes(szFileName);
//
//
// if(dwAttributes == INVALID_FILE_ATTRIBUTES)
// {
// return -1;
// }
//
// BOOL bWriteProtected = (dwAttributes & FILE_ATTRIBUTE_READONLY) ? TRUE : FALSE;
return DiskInsert ( nDrive , szFileName , 0 , 0 ) ;
}
//===========================================================================
// Let us load main configuration from config file. Y_Y --bb
void LoadConfiguration ( )
{
DWORD dwComputerType ;
/* if (LOAD(TEXT(REGVALUE_APPLE2_TYPE),&dwComputerType))
{
if ( dwComputerType > = A2TYPE_MAX )
dwComputerType = A2TYPE_APPLE2EEHANCED ;
g_Apple2Type = ( eApple2Type ) dwComputerType ;
}
else
{ */
LOAD ( TEXT ( " Computer Emulation " ) , & dwComputerType ) ;
switch ( dwComputerType )
{
// NB. No A2TYPE_APPLE2E
case 0 : g_Apple2Type = A2TYPE_APPLE2 ; break ;
case 1 : g_Apple2Type = A2TYPE_APPLE2PLUS ; break ;
case 2 : g_Apple2Type = A2TYPE_APPLE2EEHANCED ; break ;
default : g_Apple2Type = A2TYPE_APPLE2EEHANCED ; break ;
}
// }
// determine Apple type and set appropriate caption -- should be in (F9)switching modes?
switch ( g_Apple2Type )
{
case A2TYPE_APPLE2 : g_pAppTitle = TITLE_APPLE_2 ; break ;
2015-10-30 20:31:40 +00:00
case A2TYPE_APPLE2PLUS : g_pAppTitle = TITLE_APPLE_2_PLUS ; break ;
2015-10-24 12:56:00 +00:00
case A2TYPE_APPLE2E : g_pAppTitle = TITLE_APPLE_2E ; break ;
case A2TYPE_APPLE2EEHANCED : g_pAppTitle = TITLE_APPLE_2E_ENHANCED ; break ;
}
2015-10-30 20:31:40 +00:00
// Load Joystick values
joytype [ 0 ] = 2 ;
joytype [ 1 ] = 0 ;
2015-10-24 12:56:00 +00:00
LOAD ( TEXT ( " Joystick 0 " ) , & joytype [ 0 ] ) ;
LOAD ( TEXT ( " Joystick 1 " ) , & joytype [ 1 ] ) ;
2015-10-30 20:31:40 +00:00
LOAD ( TEXT ( " Joy0Index " ) , & joy1index ) ;
LOAD ( TEXT ( " Joy1Index " ) , & joy2index ) ;
LOAD ( TEXT ( " Joy0Button1 " ) , & joy1button1 ) ;
LOAD ( TEXT ( " Joy0Button2 " ) , & joy1button2 ) ;
LOAD ( TEXT ( " Joy1Button1 " ) , & joy2button1 ) ;
LOAD ( TEXT ( " Joy0Axis0 " ) , & joy1axis0 ) ;
LOAD ( TEXT ( " Joy0Axis1 " ) , & joy1axis1 ) ;
LOAD ( TEXT ( " Joy1Axis0 " ) , & joy2axis0 ) ;
LOAD ( TEXT ( " Joy1Axis1 " ) , & joy2axis1 ) ;
2015-11-02 19:43:21 +00:00
LOAD ( TEXT ( " JoyExitEnable " ) , & joyexitenable ) ;
LOAD ( TEXT ( " JoyExitButton0 " ) , & joyexitbutton0 ) ;
LOAD ( TEXT ( " JoyExitButton1 " ) , & joyexitbutton1 ) ;
2015-10-30 20:31:40 +00:00
if ( joytype [ 0 ] = = 1 ) printf ( " Joystick 1 Index # = %i, Name = %s \n Button 1 = %i, Button 2 = %i \n Axis 0 = %i,Axis 1 = %i \n " , joy1index , SDL_JoystickName ( joy1index ) , joy1button1 , joy1button2 , joy1axis0 , joy1axis1 ) ;
if ( joytype [ 1 ] = = 1 ) printf ( " Joystick 2 Index # = %i, Name = %s \n Button 1 = %i \n Axis 0 = %i,Axis 1 = %i \n " , joy2index , SDL_JoystickName ( joy2index ) , joy2button1 , joy2axis0 , joy2axis1 ) ;
2015-10-24 12:56:00 +00:00
LOAD ( TEXT ( " Sound Emulation " ) , & soundtype ) ;
DWORD dwSerialPort ;
LOAD ( TEXT ( " Serial Port " ) , & dwSerialPort ) ;
sg_SSC . SetSerialPort ( dwSerialPort ) ; // ----------- why it is here????
LOAD ( TEXT ( " Emulation Speed " ) , & g_dwSpeed ) ;
LOAD ( TEXT ( " Enhance Disk Speed " ) , ( DWORD * ) & enhancedisk ) ; //
LOAD ( TEXT ( " Video Emulation " ) , & videotype ) ;
// printf("Video Emulation = %d\n", videotype);
DWORD dwTmp = 0 ; // temp var
LOAD ( TEXT ( " Fullscreen " ) , & dwTmp ) ; // load fullscreen flag
fullscreen = ( BOOL ) dwTmp ;
2015-10-30 20:31:40 +00:00
if ( fullscreenboot ) fullscreen = true ;
2015-11-02 22:03:02 +00:00
LOAD ( TEXT ( " DisableCursor " ) , & dwTmp ) ; // load Disable Cursor Flag
disablecursor = ( BOOL ) dwTmp ;
dwTmp = 1 ;
2015-10-24 12:56:00 +00:00
LOAD ( TEXT ( REGVALUE_SHOW_LEDS ) , & dwTmp ) ; // load Show Leds flag
g_ShowLeds = ( BOOL ) dwTmp ;
//printf("Fullscreen = %d\n", fullscreen);
// LOAD(TEXT("Uthernet Active") ,(DWORD *)&tfe_enabled);
SetCurrentCLK6502 ( ) ; // set up real speed
//
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))
// SpkrSetVolume(dwTmp, 100); // volume by default?
//
// if(LOAD(TEXT(REGVALUE_MB_VOLUME), &dwTmp))
// MB_SetVolume(dwTmp, 100); // volume by default?? --bb
if ( LOAD ( TEXT ( REGVALUE_SOUNDCARD_TYPE ) , & dwTmp ) )
MB_SetSoundcardType ( ( eSOUNDCARDTYPE ) dwTmp ) ;
if ( LOAD ( TEXT ( REGVALUE_SAVE_STATE_ON_EXIT ) , & dwTmp ) )
g_bSaveStateOnExit = dwTmp ? true : false ;
if ( LOAD ( TEXT ( REGVALUE_HDD_ENABLED ) , & dwTmp ) ) hddenabled = ( bool ) dwTmp ; // after MemInitialize
// HD_SetEnabled(dwTmp ? true : false);
// printf("g_bHD_Enabled = %d\n", g_bHD_Enabled);
char * szHDFilename = NULL ;
if ( RegLoadString ( TEXT ( " Configuration " ) , TEXT ( " Monochrome Color " ) , 1 , & szHDFilename , 10 ) )
{
if ( ! sscanf ( szHDFilename , " #%X " , & monochrome ) ) monochrome = 0xC0C0C0 ;
free ( szHDFilename ) ;
szHDFilename = NULL ;
}
dwTmp = 0 ;
LOAD ( TEXT ( " Boot at Startup " ) , & dwTmp ) ; //
2015-10-30 20:31:40 +00:00
if ( ( dwTmp ) | | ( autoboot ) )
{
2015-10-24 12:56:00 +00:00
// autostart
SDL_Event user_ev ;
user_ev . type = SDL_USEREVENT ;
user_ev . user . code = 1 ; //restart?
SDL_PushEvent ( & user_ev ) ;
}
2015-10-30 20:31:40 +00:00
2015-10-24 12:56:00 +00:00
dwTmp = 0 ;
LOAD ( TEXT ( " Slot 6 Autoload " ) , & dwTmp ) ; // load autoinsert for Slot 6 flag
2015-10-27 23:10:50 +00:00
if ( dwTmp & & ! autoboot ) {
2015-10-24 12:56:00 +00:00
// Load floppy disk images and insert it automatically in slot 6 drive 1 and 2
if ( RegLoadString ( TEXT ( " Configuration " ) , TEXT ( REGVALUE_DISK_IMAGE1 ) , 1 , & szHDFilename , MAX_PATH ) )
{
DoDiskInsert ( 0 , szHDFilename ) ;
free ( szHDFilename ) ;
szHDFilename = NULL ;
}
if ( RegLoadString ( TEXT ( " Configuration " ) , TEXT ( REGVALUE_DISK_IMAGE2 ) , 1 , & szHDFilename , MAX_PATH ) )
{
DoDiskInsert ( 1 , szHDFilename ) ;
free ( szHDFilename ) ;
szHDFilename = NULL ;
}
}
2015-10-27 23:10:50 +00:00
else {
if ( argdisks ) {
DoDiskInsert ( 0 , Disk1 ) ;
}
else
{
const char * home = getenv ( " HOME " ) ;
std : : string MASTER_DISKstr ( home ) ;
MASTER_DISKstr + = " /.linapple/Master.dsk " ;
const char * MasterDiskLocation = MASTER_DISKstr . c_str ( ) ;
ifstream ifile2 ( MasterDiskLocation ) ;
if ( ifile2 ) {
char * MasterDisk = new char [ MASTER_DISKstr . length ( ) + 1 ] ;
strcpy ( MasterDisk , MASTER_DISKstr . c_str ( ) ) ;
DoDiskInsert ( 0 , MasterDisk ) ;
}
else {
char * MasterDisk = " Master.dsk " ;
DoDiskInsert ( 0 , MasterDisk ) ;
}
}
if ( argdisks2 ) DoDiskInsert ( 1 , Disk2 ) ;
}
2015-10-24 12:56:00 +00:00
// Load hard disk images and insert it automatically in slot 7
if ( RegLoadString ( TEXT ( " Configuration " ) , TEXT ( REGVALUE_HDD_IMAGE1 ) , 1 , & szHDFilename , MAX_PATH ) )
{
// printf("LoadConfiguration: returned string is: %s\n", szHDFilename);
HD_InsertDisk2 ( 0 , szHDFilename ) ;
free ( szHDFilename ) ;
szHDFilename = NULL ;
}
if ( RegLoadString ( TEXT ( " Configuration " ) , TEXT ( REGVALUE_HDD_IMAGE2 ) , 1 , & szHDFilename , MAX_PATH ) )
{
// printf("LoadConfiguration: returned string is: %s\n", szHDFilename);
HD_InsertDisk2 ( 1 , szHDFilename ) ;
free ( szHDFilename ) ;
szHDFilename = NULL ;
}
// file name for Parallel Printer
if ( RegLoadString ( TEXT ( " Configuration " ) , TEXT ( REGVALUE_PPRINTER_FILENAME ) , 1 , & szHDFilename , MAX_PATH ) )
{
if ( strlen ( szHDFilename ) > 1 ) strncpy ( g_sParallelPrinterFile , szHDFilename , MAX_PATH ) ;
free ( szHDFilename ) ;
szHDFilename = NULL ;
}
// for joysticks use default Y-,X-trims
// if(LOAD(TEXT(REGVALUE_PDL_XTRIM), &dwTmp))
// JoySetTrim((short)dwTmp, true);
// if(LOAD(TEXT(REGVALUE_PDL_YTRIM), &dwTmp))
// JoySetTrim((short)dwTmp, false);
// we do not use this, scroll lock ever toggling full-speed???
// if(LOAD(TEXT(REGVALUE_SCROLLLOCK_TOGGLE), &dwTmp))
// g_uScrollLockToggle = dwTmp;
//
char * szFilename = NULL ;
double scrFactor = 0.0 ;
// Define screen sizes
if ( RegLoadString ( TEXT ( " Configuration " ) , TEXT ( " Screen factor " ) , 1 , & szFilename , 16 ) ) {
scrFactor = atof ( szFilename ) ;
if ( scrFactor > 0.1 ) {
g_ScreenWidth = UINT ( g_ScreenWidth * scrFactor ) ;
g_ScreenHeight = UINT ( g_ScreenHeight * scrFactor ) ;
}
free ( szFilename ) ;
szFilename = NULL ;
}
else { // Try to set Screen Width & Height directly
dwTmp = 0 ;
LOAD ( TEXT ( " Screen Width " ) , & dwTmp ) ;
if ( dwTmp > 0 ) g_ScreenWidth = dwTmp ;
dwTmp = 0 ;
LOAD ( TEXT ( " Screen Height " ) , & dwTmp ) ;
if ( dwTmp > 0 ) g_ScreenHeight = dwTmp ;
}
if ( RegLoadString ( TEXT ( " Configuration " ) , TEXT ( REGVALUE_SAVESTATE_FILENAME ) , 1 , & szFilename , MAX_PATH ) ) {
Snapshot_SetFilename ( szFilename ) ; // If not in Registry than default will be used
free ( szFilename ) ;
szFilename = NULL ;
}
// Current/Starting Dir is the "root" of where the user keeps his disk images
RegLoadString ( TEXT ( " Preferences " ) , REGVALUE_PREF_START_DIR , 1 , & szFilename , MAX_PATH ) ;
if ( szFilename ) {
strcpy ( g_sCurrentDir , szFilename ) ;
free ( szFilename ) ;
szFilename = NULL ;
}
// SetCurrentDirectory(g_sCurrentDir);
if ( strlen ( g_sCurrentDir ) = = 0 | | g_sCurrentDir [ 0 ] ! = ' / ' ) //something is wrong in dir name?
{ //
char * tmp = getenv ( " HOME " ) ; /* we don't have HOME? ^_^ 0_0 $_$ */
if ( tmp = = NULL ) strcpy ( g_sCurrentDir , " / " ) ; //begin from the root, then
else strcpy ( g_sCurrentDir , tmp ) ;
}
// Load starting directory for HDV (Apple][ HDD) images
RegLoadString ( TEXT ( " Preferences " ) , REGVALUE_PREF_HDD_START_DIR , 1 , & szFilename , MAX_PATH ) ;
if ( szFilename ) {
strcpy ( g_sHDDDir , szFilename ) ;
free ( szFilename ) ;
szFilename = NULL ;
}
// SetCurrentDirectory(g_sCurrentDir);
if ( strlen ( g_sHDDDir ) = = 0 | | g_sHDDDir [ 0 ] ! = ' / ' ) //something is wrong in dir name?
{
char * tmp = getenv ( " HOME " ) ; /* we don't have HOME? ^_^ 0_0 $_$ */
if ( tmp = = NULL ) strcpy ( g_sHDDDir , " / " ) ; //begin from the root, then
else strcpy ( g_sHDDDir , tmp ) ;
}
// Load starting directory for saving current states
RegLoadString ( TEXT ( " Preferences " ) , REGVALUE_PREF_SAVESTATE_DIR , 1 , & szFilename , MAX_PATH ) ;
if ( szFilename ) {
strcpy ( g_sSaveStateDir , szFilename ) ;
free ( szFilename ) ;
szFilename = NULL ;
}
if ( strlen ( g_sSaveStateDir ) = = 0 | | g_sSaveStateDir [ 0 ] ! = ' / ' ) //something is wrong in dir name?
{
char * tmp = getenv ( " HOME " ) ; /* we don't have HOME? ^_^ 0_0 $_$ */
if ( tmp = = NULL ) strcpy ( g_sSaveStateDir , " / " ) ; //begin from the root, then
else strcpy ( g_sSaveStateDir , tmp ) ;
}
// Read and fill FTP variables - server, local dir, user name and password
RegLoadString ( TEXT ( " Preferences " ) , REGVALUE_FTP_DIR , 1 , & szFilename , MAX_PATH ) ;
if ( szFilename ) {
strcpy ( g_sFTPServer , szFilename ) ;
free ( szFilename ) ;
szFilename = NULL ;
}
RegLoadString ( TEXT ( " Preferences " ) , REGVALUE_FTP_HDD_DIR , 1 , & szFilename , MAX_PATH ) ;
if ( szFilename ) {
strcpy ( g_sFTPServerHDD , szFilename ) ;
free ( szFilename ) ;
szFilename = NULL ;
}
RegLoadString ( TEXT ( " Preferences " ) , REGVALUE_FTP_LOCAL_DIR , 1 , & szFilename , MAX_PATH ) ;
if ( szFilename ) {
strcpy ( g_sFTPLocalDir , szFilename ) ;
free ( szFilename ) ;
szFilename = NULL ;
}
RegLoadString ( TEXT ( " Preferences " ) , REGVALUE_FTP_USERPASS , 1 , & szFilename , 512 ) ;
if ( szFilename ) {
strcpy ( g_sFTPUserPass , szFilename ) ;
free ( szFilename ) ;
szFilename = NULL ;
}
// Print some debug strings
printf ( " Ready login = %s \n " , g_sFTPUserPass ) ;
//
// ****By now we deal without Uthernet interface! --bb****
// char szUthernetInt[MAX_PATH] = {0};
// RegLoadString(TEXT("Configuration"),TEXT("Uthernet Interface"),1,szUthernetInt,MAX_PATH);
// update_tfe_interface(szUthernetInt,NULL);
}
//===========================================================================
void RegisterExtensions ( )
{ // TO DO: register extensions for KDE or GNOME desktops?? Do not know, if it is sane idea. He-he. --bb
// TCHAR szCommandTmp[MAX_PATH];
// GetModuleFileName((HMODULE)0,szCommandTmp,MAX_PATH);
//
// TCHAR command[MAX_PATH];
// wsprintf(command, "\"%s\"", szCommandTmp); // Wrap path & filename in quotes & null terminate
//
// TCHAR icon[MAX_PATH];
// wsprintf(icon,TEXT("%s,1"),(LPCTSTR)command);
//
// _tcscat(command,TEXT(" \"%1\"")); // Append "%1"
//
// RegSetValue(HKEY_CLASSES_ROOT,".bin",REG_SZ,"DiskImage",10);
// RegSetValue(HKEY_CLASSES_ROOT,".do" ,REG_SZ,"DiskImage",10);
// RegSetValue(HKEY_CLASSES_ROOT,".dsk",REG_SZ,"DiskImage",10);
// RegSetValue(HKEY_CLASSES_ROOT,".nib",REG_SZ,"DiskImage",10);
// RegSetValue(HKEY_CLASSES_ROOT,".po" ,REG_SZ,"DiskImage",10);
// // RegSetValue(HKEY_CLASSES_ROOT,".aws",REG_SZ,"DiskImage",10); // TO DO
// // RegSetValue(HKEY_CLASSES_ROOT,".hdv",REG_SZ,"DiskImage",10); // TO DO
//
// RegSetValue(HKEY_CLASSES_ROOT,
// "DiskImage",
// REG_SZ,"Disk Image",21);
//
// RegSetValue(HKEY_CLASSES_ROOT,
// "DiskImage\\DefaultIcon",
// REG_SZ,icon,_tcslen(icon)+1);
//
// RegSetValue(HKEY_CLASSES_ROOT,
// "DiskImage\\shell\\open\\command",
// REG_SZ,command,_tcslen(command)+1);
//
// RegSetValue(HKEY_CLASSES_ROOT,
// "DiskImage\\shell\\open\\ddeexec",
// REG_SZ,"%1",3);
//
// RegSetValue(HKEY_CLASSES_ROOT,
// "DiskImage\\shell\\open\\ddeexec\\application",
// REG_SZ,"applewin",9);
//
// RegSetValue(HKEY_CLASSES_ROOT,
// "DiskImage\\shell\\open\\ddeexec\\topic",
// REG_SZ,"system",7);
}
//===========================================================================
//LPSTR GetNextArg(LPSTR lpCmdLine)
//{
// Sane idea: use getoptlong as command-line parameter preprocessor. Use it at your health. Ha. --bb
/*
int bInQuotes = 0 ;
while ( * lpCmdLine )
{
if ( * lpCmdLine = = ' \" ' )
{
bInQuotes ^ = 1 ;
if ( ! bInQuotes )
{
* lpCmdLine + + = 0x00 ; // Assume end-quote is end of this arg
continue ;
}
}
if ( ( * lpCmdLine = = ' ' ) & & ! bInQuotes )
{
* lpCmdLine + + = 0x00 ;
break ;
}
lpCmdLine + + ;
}
return lpCmdLine ;
*/
//}
//FILE *spMono, *spStereo;
//---------------------------------------------------------------------------
int main ( int argc , char * lpCmdLine [ ] )
{
// reading FullScreen and Boot from conf file?
// bool bSetFullScreen = false;
// bool bBoot = false;
2015-10-27 23:10:50 +00:00
//
// Find Home Directory and assign linapple.conf to ~/.linapple/linapple.conf
// if not found set default name in current directory
const char * home = getenv ( " HOME " ) ;
std : : string linappleconfstr ( home ) ;
linappleconfstr + = " /.linapple/linapple.conf " ;
const char * linappleconf = linappleconfstr . c_str ( ) ;
ifstream ifile ( linappleconf ) ;
if ( ifile ) {
registry = fopen ( linappleconf , " a+t " ) ; // open conf file (linapple.conf by default)
}
else {
registry = fopen ( " linapple.conf " , " a+t " ) ; // open conf file (linapple.conf by default)
}
2015-10-24 12:56:00 +00:00
// spMono = fopen("speakersmono.pcm","wb");
// spStereo = fopen("speakersstereo.pcm","wb");
// LPSTR szImageName_drive1 = NULL; // file names for images of drive1 and drive2
// LPSTR szImageName_drive2 = NULL;
2015-10-27 23:10:50 +00:00
bool bBenchMark = false ;
// bool bBenchMark = (argc > 1 &&
// !strcmp(lpCmdLine[1],"-b")); // if we should start benchmark (-b in command line string)
2015-10-24 12:56:00 +00:00
2015-10-30 20:31:40 +00:00
while ( ( opt = getopt ( argc , lpCmdLine , " 1:2:rbhf " ) ) ! = - 1 )
2015-10-27 23:10:50 +00:00
{
switch ( opt )
2015-10-24 12:56:00 +00:00
{
2015-10-27 23:10:50 +00:00
case ' 1 ' :
Disk1 = optarg ;
argdisks = true ;
break ;
case ' 2 ' :
Disk2 = optarg ;
argdisks2 = true ;
break ;
case ' r ' :
autoboot = true ;
break ;
2015-10-30 20:31:40 +00:00
case ' b ' :
2015-10-27 23:10:50 +00:00
bBenchMark = true ;
printf ( " benchmark " ) ;
break ;
2015-10-30 20:31:40 +00:00
case ' h ' :
printf ( " Linapple command options.. \n \n -h Show this help message \n -1 Mount disk image in first drive \n -2 Mount disk image in second drive \n -r Auto start emulation \n -b Benchmark and quit \n \n " ) ;
return 0 ;
break ;
case ' f ' :
fullscreenboot = true ;
break ;
2015-10-27 23:10:50 +00:00
}
}
2015-10-24 12:56:00 +00:00
// I will remake this using getopt and getoptlong!
/*
while ( * lpCmdLine )
{
LPSTR lpNextArg = GetNextArg ( lpCmdLine ) ;
if ( strcmp ( lpCmdLine , " -d1 " ) = = 0 )
{
lpCmdLine = lpNextArg ;
lpNextArg = GetNextArg ( lpCmdLine ) ;
szImageName_drive1 = lpCmdLine ;
if ( * szImageName_drive1 = = ' \" ' )
szImageName_drive1 + + ;
}
else if ( strcmp ( lpCmdLine , " -d2 " ) = = 0 )
{
lpCmdLine = lpNextArg ;
lpNextArg = GetNextArg ( lpCmdLine ) ;
szImageName_drive2 = lpCmdLine ;
if ( * szImageName_drive2 = = ' \" ' )
szImageName_drive2 + + ;
}
else if ( strcmp ( lpCmdLine , " -f " ) = = 0 )
{
bSetFullScreen = true ;
}
else if ( ( strcmp ( lpCmdLine , " -l " ) = = 0 ) & & ( g_fh = = NULL ) )
{
g_fh = fopen ( " AppleWin.log " , " a+t " ) ; // Open log file (append & text g_nAppMode)
// Start of Unix(tm) specific code
struct timeval tv ;
struct tm * ptm ;
char time_str [ 40 ] ;
gettimeofday ( & tv , NULL ) ;
ptm = localtime ( & tv . tvsec ) ;
strftime ( time_str , sizeof ( time_str ) , " %Y-%m-%d %H:%M:%S " , ptm ) ;
// end of Unix(tm) specific code
fprintf ( g_fh , " *** Logging started: %s \n " , time_str ) ;
}
else if ( strcmp ( lpCmdLine , " -m " ) = = 0 )
{
g_bDisableDirectSound = true ; // without direct sound? U-u-u-u-uuuuuuuhhhhhhhhh --bb
}
# ifdef RAMWORKS
else if ( strcmp ( lpCmdLine , " -r " ) = = 0 ) // RamWorks size [1..127]
{
lpCmdLine = lpNextArg ;
lpNextArg = GetNextArg ( lpCmdLine ) ;
g_uMaxExPages = atoi ( lpCmdLine ) ;
if ( g_uMaxExPages > 127 )
g_uMaxExPages = 128 ;
else if ( g_uMaxExPages < 1 )
g_uMaxExPages = 1 ;
}
# endif
lpCmdLine = lpNextArg ;
}
*/
// What is it???? RIFF support for sound saving during emulation in RIFF format.
// Currently not used?
#if 0
# ifdef RIFF_SPKR
RiffInitWriteFile ( " Spkr.wav " , SPKR_SAMPLE_RATE , 1 ) ;
# endif
# ifdef RIFF_MB
RiffInitWriteFile ( " Mockingboard.wav " , 44100 , 2 ) ;
# endif
# endif
//-----
// char szPath[_MAX_PATH];
//
// if(0 == GetModuleFileName(NULL, szPath, sizeof(szPath)))
// {
// strcpy(szPath, __argv[0]);
// }
// Extract application version and store in a global variable
// DWORD dwHandle, dwVerInfoSize;
//
// dwVerInfoSize = GetFileVersionInfoSize(szPath, &dwHandle);
//
// if(dwVerInfoSize > 0)
// {
// char* pVerInfoBlock = new char[dwVerInfoSize];
//
// if(GetFileVersionInfo(szPath, NULL, dwVerInfoSize, pVerInfoBlock))
// {
// VS_FIXEDFILEINFO* pFixedFileInfo;
// UINT pFixedFileInfoLen;
//
// VerQueryValue(pVerInfoBlock, TEXT("\\"), (LPVOID*) &pFixedFileInfo, (PUINT) &pFixedFileInfoLen);
//
// // Construct version string from fixed file info block
//
// unsigned long major = pFixedFileInfo->dwFileVersionMS >> 16;
// unsigned long minor = pFixedFileInfo->dwFileVersionMS & 0xffff;
// unsigned long fix = pFixedFileInfo->dwFileVersionLS >> 16;
// unsigned long fix_minor = pFixedFileInfo->dwFileVersionLS & 0xffff;
//
// sprintf(VERSIONSTRING, "%d.%d.%d.%d", major, minor, fix, fix_minor);
// }
// }
# if DBG_CALC_FREQ
//QueryPerformanceFrequency((LARGE_INTEGER*)&g_nPerfFreq);
g_nPerfFreq = 1000 ; //milliseconds?
if ( g_fh ) fprintf ( g_fh , " Performance frequency = %d \n " , g_nPerfFreq ) ;
# endif
//-----
// Initialize COM
// . NB. DSInit() is done when g_hFrameWindow is created (WM_CREATE)
if ( InitSDL ( ) ) return 1 ; // init SDL subsystems, set icon
// CoInitialize( NULL ); ------- what is it initializing?----------------------------------------
// CURL routines
curl_global_init ( CURL_GLOBAL_DEFAULT ) ;
g_curl = curl_easy_init ( ) ;
if ( ! g_curl ) {
printf ( " Could not initialize CURL easy interface " ) ;
return 1 ;
}
/* Set user name and password to access FTP server */
curl_easy_setopt ( g_curl , CURLOPT_USERPWD , g_sFTPUserPass ) ;
//
// just do not see why we need this timer???
/*bool bSysClkOK =*/ SysClk_InitTimer ( ) ;
// DO ONE-TIME INITIALIZATION
// g_hInstance = passinstance;
MemPreInitialize ( ) ; // Call before any of the slot devices are initialized
// GdiSetBatchLimit(512);
// GetProgramDirectory();
// RegisterExtensions();
// FrameRegisterClass();
ImageInitialize ( ) ;
DiskInitialize ( ) ;
CreateColorMixMap ( ) ; // For tv emulation g_nAppMode
// int nError = 0;
// if(szImageName_drive1)
// {
// nError = DoDiskInsert(0, szImageName_drive1);
// bBoot = true;
// }
// if(szImageName_drive2)
// {
// nError |= DoDiskInsert(1, szImageName_drive2);
// }
//
do
{
// DO INITIALIZATION THAT MUST BE REPEATED FOR A RESTART
restart = 0 ;
g_nAppMode = MODE_LOGO ;
fullscreen = false ;
LoadConfiguration ( ) ;
FrameCreateWindow ( ) ;
if ( ! DSInit ( ) ) soundtype = SOUND_NONE ; // Direct Sound and Stuff
MB_Initialize ( ) ; // Mocking board
SpkrInitialize ( ) ; // Speakers - of Apple][ ...grrrrrrrrrrr, I love them!--bb
DebugInitialize ( ) ;
JoyInitialize ( ) ;
MemInitialize ( ) ;
HD_SetEnabled ( hddenabled ? true : false ) ;
//printf("g_bHD_Enabled = %d\n", g_bHD_Enabled);
VideoInitialize ( ) ;
// if (!bSysClkOK)
// {
// MessageBox(g_hFrameWindow, "DirectX failed to create SystemClock instance", TEXT("AppleWin Error"), MB_OK);
// PostMessage(g_hFrameWindow, WM_DESTROY, 0, 0); // Close everything down
// }
// tfe_init();
Snapshot_Startup ( ) ; // Do this after everything has been init'ed
/* ------Will be fullscreened and booted later. I promise. --bb */
// if(bSetFullScreen)
// {
// PostMessage(g_hFrameWindow, WM_KEYDOWN, VK_F1+BTN_FULLSCR, 0);
// PostMessage(g_hFrameWindow, WM_KEYUP, VK_F1+BTN_FULLSCR, 0);
// bSetFullScreen = false;
// }
//
// if(bBoot)
// {
// PostMessage(g_hFrameWindow, WM_KEYDOWN, VK_F1+BTN_RUN, 0);
// PostMessage(g_hFrameWindow, WM_KEYUP, VK_F1+BTN_RUN, 0);
// bBoot = false;
// }
JoyReset ( ) ;
SetUsingCursor ( 0 ) ;
2015-11-02 22:03:02 +00:00
if ( disablecursor ) SDL_ShowCursor ( SDL_DISABLE ) ;
2015-10-24 12:56:00 +00:00
// trying fullscreen
if ( ! fullscreen ) SetNormalMode ( ) ;
else SetFullScreenMode ( ) ;
DrawFrameWindow ( ) ; // we do not have WM_PAINT?
// ENTER THE MAIN MESSAGE LOOP
if ( bBenchMark ) VideoBenchmark ( ) ; // start VideoBenchmark and exit
else EnterMessageLoop ( ) ; // else we just start game
// on WM_DESTROY event:
Snapshot_Shutdown ( ) ;
DebugDestroy ( ) ;
// printf("Quitting. Snapshot_Shutdown-ed!\n");
if ( ! restart ) {
DiskDestroy ( ) ;
ImageDestroy ( ) ;
HD_Cleanup ( ) ;
}
// printf("Quitting. DiskDestroy, ImageDestroy and HD_Cleanup!\n");
PrintDestroy ( ) ;
sg_SSC . CommDestroy ( ) ;
CpuDestroy ( ) ;
MemDestroy ( ) ;
// printf("Quitting. PrintDestroy, sg_SSC.CommDestroy, CPU-MEMDestroy!\n");
SpkrDestroy ( ) ;
// printf("Quitting. SpkrDestroy!!\n");
VideoDestroy ( ) ;
// printf("Quitting. VideoDestroy!!\n");
MB_Destroy ( ) ;
// printf("Quitting. MB_Destroy!\n");
// end of WM_DESTROY event
MB_Reset ( ) ;
// printf("Quitting. MB_Reset!\n");
sg_Mouse . Uninitialize ( ) ; // Maybe restarting due to switching slot-4 card from mouse to MB
// printf("Quitting. Mouse.Uninitialize!!!\n");
JoyShutDown ( ) ; // close opened (if any) joysticks
}
while ( restart ) ;
// Release COM
DSUninit ( ) ;
SysClk_UninitTimer ( ) ;
// CoUninitialize();------------------------------- what is it uninitializing?--------------------------
// tfe_shutdown();
if ( g_fh )
{
fprintf ( g_fh , " *** Logging ended \n \n " ) ;
fclose ( g_fh ) ;
}
RiffFinishWriteFile ( ) ;
2015-10-27 23:10:50 +00:00
fclose ( registry ) ; //close conf file (linapple.conf by default)
2015-10-24 12:56:00 +00:00
// fclose(spMono);
// fclose(spStereo);
SDL_Quit ( ) ;
// CURL routines
curl_easy_cleanup ( g_curl ) ;
curl_global_cleanup ( ) ;
//
printf ( " Linapple: successfully exited! \n " ) ;
return 0 ;
}