applen: add --log, --ntsc, and log time till first $C000 access.

This commit is contained in:
Andrea Odetti 2019-11-23 20:34:24 +00:00
parent 7529f5c659
commit 35a81f8009
7 changed files with 97 additions and 24 deletions

View file

@ -47,6 +47,7 @@ add_library(appleii SHARED
linux/duplicates/Joystick.cpp
linux/duplicates/Frame.cpp
linux/duplicates/SerialComms.cpp
linux/duplicates/Applewin.cpp
Z80VICE/z80.cpp
Z80VICE/z80mem.cpp

View file

@ -2,7 +2,6 @@
#include <chrono>
#include <iostream>
#include <unistd.h>
#include <ncurses.h>
#include <boost/program_options.hpp>
@ -37,8 +36,10 @@ namespace
bool createMissingDisks;
std::string snapshot;
int memclear;
bool log;
bool benchmark;
bool headless;
bool ntsc;
bool saveConfigurationOnExit;
bool run; // false if options include "-h"
@ -70,7 +71,9 @@ namespace
po::options_description emulatorDesc("Emulator");
emulatorDesc.add_options()
("log", "Log to AppleWin.log")
("headless,hl", "Headless: disable video")
("ntsc,nt", "NTSC: execute NTSC code")
("benchmark,b", "Benchmark emulator");
desc.add(emulatorDesc);
@ -113,6 +116,8 @@ namespace
options.benchmark = vm.count("benchmark") > 0;
options.headless = vm.count("headless") > 0;
options.log = vm.count("log") > 0;
options.ntsc = vm.count("ntsc") > 0;
return true;
}
@ -128,7 +133,7 @@ namespace
}
}
bool ContinueExecution(const bool updateVideo)
bool ContinueExecution(const EmulatorOptions & options)
{
const auto start = std::chrono::steady_clock::now();
@ -144,7 +149,9 @@ namespace
const DWORD uCyclesToExecute = fExecutionPeriodClks;
const bool bVideoUpdate = false;
const bool bVideoUpdate = options.ntsc;
g_bFullSpeed = !bVideoUpdate;
const DWORD uActualCyclesExecuted = CpuExecute(uCyclesToExecute, bVideoUpdate);
g_dwCyclesThisFrame += uActualCyclesExecuted;
@ -156,6 +163,12 @@ namespace
{
case KEY_F(2):
{
g_bRestart = false;
return false;
}
case KEY_F(3):
{
g_bRestart = true;
return false;
}
case KEY_F(12):
@ -173,35 +186,39 @@ namespace
const UINT dwClksPerFrame = NTSC_GetCyclesPerFrame();
if (g_dwCyclesThisFrame >= dwClksPerFrame)
{
g_dwCyclesThisFrame -= dwClksPerFrame;
if (updateVideo)
g_dwCyclesThisFrame = g_dwCyclesThisFrame % dwClksPerFrame;
if (!options.headless)
{
VideoRedrawScreen();
}
}
const auto end = std::chrono::steady_clock::now();
const auto diff = end - start;
const long us = std::chrono::duration_cast<std::chrono::microseconds>(diff).count();
const double coeff = exp(-0.000001 * nExecutionPeriodUsec); // 0.36 after 1 second
g_relativeSpeed = g_relativeSpeed * coeff + double(us) / double(nExecutionPeriodUsec) * (1.0 - coeff);
if (!sg_Disk2Card.IsConditionForFullSpeed())
if (!options.headless)
{
if (us < nExecutionPeriodUsec)
const auto end = std::chrono::steady_clock::now();
const auto diff = end - start;
const long us = std::chrono::duration_cast<std::chrono::microseconds>(diff).count();
const double coeff = exp(-0.000001 * nExecutionPeriodUsec); // 0.36 after 1 second
g_relativeSpeed = g_relativeSpeed * coeff + double(us) / double(nExecutionPeriodUsec) * (1.0 - coeff);
if (!sg_Disk2Card.IsConditionForFullSpeed())
{
usleep(nExecutionPeriodUsec - us);
if (us < nExecutionPeriodUsec)
{
usleep(nExecutionPeriodUsec - us);
}
}
}
return true;
}
void EnterMessageLoop(const bool updateVideo)
void EnterMessageLoop(const EmulatorOptions & options)
{
while (ContinueExecution(updateVideo))
LogFileTimeUntilFirstKeyReadReset();
while (ContinueExecution(options))
{
}
}
@ -238,9 +255,6 @@ namespace
int foo(int argc, const char * argv [])
{
g_fh = fopen("/tmp/applewin.txt", "w");
setbuf(g_fh, NULL);
EmulatorOptions options;
options.memclear = g_nMemoryClearType;
const bool run = getEmulatorOptions(argc, argv, options);
@ -248,6 +262,11 @@ namespace
if (!run)
return 1;
if (options.log)
{
LogInit();
}
InitializeRegistry("applen.conf");
g_nMemoryClearType = options.memclear;
@ -296,11 +315,10 @@ namespace
if (options.benchmark)
{
VideoBenchmark(&VideoRedrawScreen);
g_bRestart = false;
}
else
{
EnterMessageLoop(!options.headless);
EnterMessageLoop(options);
}
sg_Mouse.Uninitialize();
sg_Mouse.Reset();

View file

@ -369,7 +369,7 @@ void FrameRefreshStatus(int x, bool)
void NVideoInitialize()
{
VideoReinitialize();
VideoInitialize();
setlocale(LC_ALL, "");
initscr();
@ -540,6 +540,7 @@ BYTE KeybGetKeycode ()
BYTE KeybReadData()
{
LogFileTimeUntilFirstKeyRead();
return nextKey;
}

View file

@ -7,3 +7,6 @@ void SetWindowTitle();
void getScreenData(uint8_t * & data, int & width, int & height, int & sx, int & sy, int & sw, int & sh);
extern int g_nAltCharSetOffset; // alternate character set
void LogFileTimeUntilFirstKeyReadReset(void);
void LogFileTimeUntilFirstKeyRead(void);

View file

@ -0,0 +1,40 @@
#include "StdAfx.h"
#include "Memory.h"
#include "Log.h"
#include "Common.h"
#include "CPU.h"
static bool bLogKeyReadDone = false;
static DWORD dwLogKeyReadTickStart;
void LogFileTimeUntilFirstKeyReadReset(void)
{
if (!g_fh)
return;
dwLogKeyReadTickStart = GetTickCount();
bLogKeyReadDone = false;
}
// Log the time from emulation restart/reboot until the first key read: BIT $C000
// . AZTEC.DSK (DOS 3.3) does prior LDY $C000 reads, but the BIT $C000 is at the "Press any key" message
// . Phasor1.dsk / ProDOS 1.1.1: PC=E797: B1 50: LDA ($50),Y / "Select an Option:" message
// . Rescue Raiders v1.3,v1.5: PC=895: LDA $C000 / boot to intro
void LogFileTimeUntilFirstKeyRead(void)
{
if (!g_fh || bLogKeyReadDone)
return;
if ( (mem[regs.pc-3] != 0x2C) // AZTEC: bit $c000
&& !((regs.pc-2) == 0xE797 && mem[regs.pc-2] == 0xB1 && mem[regs.pc-1] == 0x50) // Phasor1: lda ($50),y
&& !((regs.pc-3) == 0x0895 && mem[regs.pc-3] == 0xAD) // Rescue Raiders v1.3,v1.5: lda $c000
)
return;
DWORD dwTime = GetTickCount() - dwLogKeyReadTickStart;
LogFileOutput("Time from emulation reboot until first $C000 access: %d msec\n", dwTime);
bLogKeyReadDone = true;
}

View file

@ -19,6 +19,15 @@ DWORD timeGetTime()
return now.tv_usec / 1000;
}
/// Returns the number of ticks since an undefined time (usually system startup).
DWORD GetTickCount()
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
const uint64_t ticks = (uint64_t)(ts.tv_nsec / 1000000) + ((uint64_t)ts.tv_sec * 1000ull);
return ticks;
}
void GetLocalTime(SYSTEMTIME *t)
{
timespec ts;

View file

@ -26,4 +26,5 @@ int GetDateFormat(LCID Locale, DWORD dwFlags, CONST SYSTEMTIME *lpDate, LPCSTR l
int GetTimeFormat(LCID Locale, DWORD dwFlags, CONST SYSTEMTIME *lpTime, LPCSTR lpFormat, LPSTR lpTimeStr, int cchTime);
DWORD timeGetTime();
DWORD GetTickCount();
void GetLocalTime(SYSTEMTIME *t);