From 5ad20af6f34079d08fd9161e49dc9692780fcf02 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Fri, 5 Jul 2024 21:22:26 +0100
Subject: [PATCH 001/101] Disable joystick when switching model to Master ET
---
Src/BeebWin.cpp | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index 5b1170fc..afd3a81e 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -802,6 +802,11 @@ void BeebWin::ResetBeebSystem(Model NewModelType, bool LoadRoms)
AtoDInit();
SetRomMenu();
+ if (NewModelType == Model::MasterET)
+ {
+ SetJoystickOption(JoystickOption::Disabled);
+ }
+
char szDiscName[2][MAX_PATH];
strcpy(szDiscName[0], DiscInfo[0].FileName);
strcpy(szDiscName[1], DiscInfo[1].FileName);
@@ -5944,6 +5949,7 @@ MessageResult BeebWin::ReportV(MessageType type, const char *format, va_list arg
case MessageType::Confirm:
Type = MB_ICONWARNING | MB_OKCANCEL;
+ break;
}
hCBTHook = SetWindowsHookEx(WH_CBT, CBTMessageBox, nullptr, GetCurrentThreadId());
From 82ea0d3a720297162f2b6029e1406bc86893fdec Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 6 Jul 2024 12:29:43 +0100
Subject: [PATCH 002/101] Removed unused function
---
Src/BeebWinIo.cpp | 5 -----
1 file changed, 5 deletions(-)
diff --git a/Src/BeebWinIo.cpp b/Src/BeebWinIo.cpp
index 5cd64805..31336155 100644
--- a/Src/BeebWinIo.cpp
+++ b/Src/BeebWinIo.cpp
@@ -1357,11 +1357,6 @@ void BeebWin::LoadFDC(char *DLLName, bool save)
DisplayCycles = 0;
}
-void BeebWin::KillDLLs()
-{
- Ext1770Reset();
-}
-
void BeebWin::SetDriveControl(unsigned char Value)
{
// This takes a value from the mem/io decoder, as written by the CPU,
From 1f9b6714ca9d0bc7815551dd6149ae4fb6bf71fc Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sun, 7 Jul 2024 22:55:37 +0100
Subject: [PATCH 003/101] Refactored serial port code
- Added error checks
- Added WriteChar() method
---
Src/Serial.cpp | 165 ++++++++++++++++++++++++++++++++-----------------
1 file changed, 109 insertions(+), 56 deletions(-)
diff --git a/Src/Serial.cpp b/Src/Serial.cpp
index d9814ff6..f88bb9f9 100644
--- a/Src/Serial.cpp
+++ b/Src/Serial.cpp
@@ -136,9 +136,11 @@ class Win32SerialPort
bool Init(const char* PortName);
void Close();
- void SetBaudRate(int BaudRate);
- void Configure(unsigned char DataBits, unsigned char StopBits, unsigned char Parity);
- void SetRTS(bool RTS);
+ bool SetBaudRate(int BaudRate);
+ bool Configure(unsigned char DataBits, unsigned char StopBits, unsigned char Parity);
+ bool SetRTS(bool RTS);
+
+ bool WriteChar(unsigned char Data);
public:
HANDLE hSerialPort; // Serial port handle
@@ -185,18 +187,21 @@ Win32SerialPort::Win32SerialPort() :
bWaitingForStat(false),
bCharReady(false)
{
- memset(&olSerialPort, 0, sizeof(olSerialPort));
- memset(&olSerialWrite, 0, sizeof(olSerialWrite));
- memset(&olStatus, 0, sizeof(olStatus));
+ ZeroMemory(&olSerialPort, sizeof(olSerialPort));
+ ZeroMemory(&olSerialWrite, sizeof(olSerialWrite));
+ ZeroMemory(&olStatus, sizeof(olStatus));
}
/*--------------------------------------------------------------------------*/
bool Win32SerialPort::Init(const char* PortName)
{
- char FileName[_MAX_PATH];
+ char FileName[MAX_PATH];
sprintf(FileName, "\\\\.\\%s", PortName);
+ COMMTIMEOUTS CommTimeOuts{};
+ DCB dcb{}; // Serial port device control block
+
hSerialPort = CreateFile(FileName,
GENERIC_READ | GENERIC_WRITE,
0, // dwShareMode
@@ -209,43 +214,59 @@ bool Win32SerialPort::Init(const char* PortName)
{
return false;
}
- else
+
+ if (!SetupComm(hSerialPort, 1024, 1024))
{
- BOOL bPortStat = SetupComm(hSerialPort, 1280, 1280);
+ goto Fail;
+ }
- DCB dcbSerialPort{}; // Serial port device control block
- dcbSerialPort.DCBlength = sizeof(dcbSerialPort);
+ dcb.DCBlength = sizeof(dcb);
- bPortStat = GetCommState(hSerialPort, &dcbSerialPort);
+ if (!GetCommState(hSerialPort, &dcb))
+ {
+ goto Fail;
+ }
- dcbSerialPort.fBinary = TRUE;
- dcbSerialPort.BaudRate = 9600;
- dcbSerialPort.Parity = NOPARITY;
- dcbSerialPort.StopBits = ONESTOPBIT;
- dcbSerialPort.ByteSize = 8;
- dcbSerialPort.fDtrControl = DTR_CONTROL_DISABLE;
- dcbSerialPort.fOutxCtsFlow = FALSE;
- dcbSerialPort.fOutxDsrFlow = FALSE;
- dcbSerialPort.fOutX = FALSE;
- dcbSerialPort.fDsrSensitivity = FALSE;
- dcbSerialPort.fInX = FALSE;
- dcbSerialPort.fRtsControl = RTS_CONTROL_DISABLE; // Leave it low (do not send) for now
+ dcb.fBinary = TRUE;
+ dcb.BaudRate = 9600;
+ dcb.Parity = NOPARITY;
+ dcb.StopBits = ONESTOPBIT;
+ dcb.ByteSize = 8;
+ dcb.fDtrControl = DTR_CONTROL_DISABLE;
+ dcb.fOutxCtsFlow = FALSE;
+ dcb.fOutxDsrFlow = FALSE;
+ dcb.fOutX = FALSE;
+ dcb.fDsrSensitivity = FALSE;
+ dcb.fInX = FALSE;
+ dcb.fRtsControl = RTS_CONTROL_DISABLE; // Leave it low (do not send) for now
+
+ if (!SetCommState(hSerialPort, &dcb))
+ {
+ goto Fail;
+ }
- bPortStat = SetCommState(hSerialPort, &dcbSerialPort);
+ CommTimeOuts.ReadIntervalTimeout = MAXDWORD;
+ CommTimeOuts.ReadTotalTimeoutConstant = 0;
+ CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
+ CommTimeOuts.WriteTotalTimeoutConstant = 0;
+ CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
+
+ if (!SetCommTimeouts(hSerialPort, &CommTimeOuts))
+ {
+ goto Fail;
+ }
- COMMTIMEOUTS CommTimeOuts{};
- CommTimeOuts.ReadIntervalTimeout = MAXDWORD;
- CommTimeOuts.ReadTotalTimeoutConstant = 0;
- CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
- CommTimeOuts.WriteTotalTimeoutConstant = 0;
- CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
+ if (!SetCommMask(hSerialPort, EV_CTS | EV_RXCHAR | EV_ERR))
+ {
+ goto Fail;
+ }
- SetCommTimeouts(hSerialPort, &CommTimeOuts);
+ return true;
- SetCommMask(hSerialPort, EV_CTS | EV_RXCHAR | EV_ERR);
+Fail:
+ Close();
- return true;
- }
+ return false;
}
/*--------------------------------------------------------------------------*/
@@ -261,39 +282,73 @@ void Win32SerialPort::Close()
/*--------------------------------------------------------------------------*/
-void Win32SerialPort::SetBaudRate(int BaudRate)
+bool Win32SerialPort::SetBaudRate(int BaudRate)
{
- DCB dcbSerialPort{}; // Serial port device control block
- dcbSerialPort.DCBlength = sizeof(dcbSerialPort);
+ DCB dcb{}; // Serial port device control block
+ dcb.DCBlength = sizeof(dcb);
+
+ if (!GetCommState(hSerialPort, &dcb))
+ {
+ return false;
+ }
+
+ dcb.BaudRate = BaudRate;
+ dcb.DCBlength = sizeof(dcb);
+
+ if (!SetCommState(hSerialPort, &dcb))
+ {
+ return false;
+ }
- GetCommState(hSerialPort, &dcbSerialPort);
- dcbSerialPort.BaudRate = BaudRate;
- dcbSerialPort.DCBlength = sizeof(dcbSerialPort);
- SetCommState(hSerialPort, &dcbSerialPort);
+ return true;
}
/*--------------------------------------------------------------------------*/
-void Win32SerialPort::Configure(unsigned char DataBits, unsigned char StopBits, unsigned char Parity)
+bool Win32SerialPort::Configure(unsigned char DataBits, unsigned char StopBits, unsigned char Parity)
{
- DCB dcbSerialPort{}; // Serial port device control block
- dcbSerialPort.DCBlength = sizeof(dcbSerialPort);
+ DCB dcb{}; // Serial port device control block
+ dcb.DCBlength = sizeof(dcb);
+
+ if (!GetCommState(hSerialPort, &dcb))
+ {
+ return false;
+ }
+
+ dcb.ByteSize = DataBits;
+ dcb.StopBits = (StopBits == 1) ? ONESTOPBIT : TWOSTOPBITS;
+ dcb.Parity = Parity;
+ dcb.DCBlength = sizeof(dcb);
+
+ if (!SetCommState(hSerialPort, &dcb))
+ {
+ return false;
+ }
- GetCommState(hSerialPort, &dcbSerialPort);
+ return true;
+}
- dcbSerialPort.ByteSize = DataBits;
- dcbSerialPort.StopBits = (StopBits == 1) ? ONESTOPBIT : TWOSTOPBITS;
- dcbSerialPort.Parity = Parity;
- dcbSerialPort.DCBlength = sizeof(dcbSerialPort);
+/*--------------------------------------------------------------------------*/
- SetCommState(hSerialPort, &dcbSerialPort);
+bool Win32SerialPort::SetRTS(bool RTS)
+{
+ if (!EscapeCommFunction(hSerialPort, RTS ? CLRRTS : SETRTS))
+ {
+ return false;
+ }
+
+ return true;
}
/*--------------------------------------------------------------------------*/
-void Win32SerialPort::SetRTS(bool RTS)
+bool Win32SerialPort::WriteChar(unsigned char Data)
{
- EscapeCommFunction(hSerialPort, RTS ? CLRRTS : SETRTS);
+ SerialWriteBuffer = Data;
+
+ WriteFile(hSerialPort, &SerialWriteBuffer, 1, &BytesOut, &olSerialWrite);
+
+ return true;
}
/*--------------------------------------------------------------------------*/
@@ -429,9 +484,7 @@ static void HandleTXData(unsigned char Data)
}
else
{
- SerialPort.SerialWriteBuffer = SerialACIA.TDSR;
-
- WriteFile(SerialPort.hSerialPort, &SerialPort.SerialWriteBuffer, 1, &SerialPort.BytesOut, &SerialPort.olSerialWrite);
+ SerialPort.WriteChar(SerialACIA.TDSR);
}
//WriteLog("Serial: TX TDR=%02X, TDSR=%02x TxD=%d Status=%02x Tx_Rate=%d\n", TDR, TDSR, TxD, SerialACIA.Status, Tx_Rate);
From 0a4edd6da2279295f96e583ffb44b842f254ab90 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Mon, 8 Jul 2024 19:42:58 +0100
Subject: [PATCH 004/101] Rewrote the Windows serial port implementation
* Received characters are now buffered to prevent being lost
* Use only one worker thread, for reading the serial port
* Avoid accessing Beeb Serial ACIA/ULA from multiple threads
---
CHANGES.md | 2 +
Src/BeebEm.vcxproj | 2 +
Src/BeebEm.vcxproj.filters | 6 +
Src/BeebWin.cpp | 55 ++--
Src/BeebWin.h | 10 +-
Src/BeebWinPrefs.cpp | 19 +-
Src/IP232.cpp | 23 +-
Src/Main.cpp | 15 +-
Src/RingBuffer.cpp | 23 +-
Src/RingBuffer.h | 7 +-
Src/Serial.cpp | 471 +++----------------------------
Src/Serial.h | 7 +-
Src/SerialPort.cpp | 554 +++++++++++++++++++++++++++++++++++++
Src/SerialPort.h | 72 +++++
Src/TouchScreen.cpp | 4 +-
15 files changed, 767 insertions(+), 503 deletions(-)
create mode 100644 Src/SerialPort.cpp
create mode 100644 Src/SerialPort.h
diff --git a/CHANGES.md b/CHANGES.md
index 49e4eca0..199a4e1c 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -44,6 +44,8 @@ Steve Inglis, Alistair Cree, Ken Lowe, Mark Usher, Martin Mather, Tom Seddon
- Fixed loading CSW files from the command line.
* Improved serial port emulation, and fixed data loss when using
serial over a TCP connection.
+* Rewrote the Windows serial port implementation. Received characters
+ are now buffered to prevent being lost.
* Added Set Keyboard Links command, which allows you to change the default
screen mode and other options (Model B/B+ only).
* Fixed installer to not delete Econet and key map config files.
diff --git a/Src/BeebEm.vcxproj b/Src/BeebEm.vcxproj
index 96894e5c..bafd1b45 100644
--- a/Src/BeebEm.vcxproj
+++ b/Src/BeebEm.vcxproj
@@ -223,6 +223,7 @@
+
@@ -392,6 +393,7 @@
+
diff --git a/Src/BeebEm.vcxproj.filters b/Src/BeebEm.vcxproj.filters
index 2245ca72..74a08c4e 100644
--- a/Src/BeebEm.vcxproj.filters
+++ b/Src/BeebEm.vcxproj.filters
@@ -198,6 +198,9 @@
Source Files
+
+ Source Files
+
Source Files
@@ -497,6 +500,9 @@
Header Files
+
+ Header Files
+
Header Files
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index afd3a81e..7cf21faf 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -661,6 +661,8 @@ void BeebWin::Shutdown()
CloseTextView();
IP232Close();
+ SerialClose();
+ CloseTape();
WSACleanup();
@@ -3519,18 +3521,27 @@ void BeebWin::ToggleSerial()
SerialPortEnabled = !SerialPortEnabled;
- if (SerialPortEnabled && SerialDestination == SerialType::IP232)
+ if (SerialPortEnabled)
{
- if (!IP232Open())
+ if (SerialDestination == SerialType::IP232)
{
- SerialPortEnabled = false;
- UpdateSerialMenu();
+ if (!IP232Open())
+ {
+ SerialPortEnabled = false;
+ UpdateSerialMenu();
+ }
}
- }
+ else if (SerialDestination == SerialType::SerialPort)
+ {
+ if (!SerialInit(m_SerialPort.c_str()))
+ {
+ Report(MessageType::Error,
+ "Could not open serial port %s", m_SerialPort.c_str());
- if (SerialDestination == SerialType::SerialPort)
- {
- bSerialStateChanged = true;
+ SerialPortEnabled = false;
+ UpdateSerialMenu();
+ }
+ }
}
UpdateSerialMenu();
@@ -3541,7 +3552,7 @@ void BeebWin::ConfigureSerial()
SerialPortDialog Dialog(hInst,
m_hWnd,
SerialDestination,
- SerialPortName,
+ m_SerialPort.c_str(),
IP232Address,
IP232Port,
IP232Raw,
@@ -3557,7 +3568,7 @@ void BeebWin::ConfigureSerial()
if (SerialDestination == SerialType::SerialPort)
{
- SelectSerialPort(Dialog.GetSerialPortName().c_str());
+ m_SerialPort = Dialog.GetSerialPortName();
}
else if (SerialDestination == SerialType::IP232)
{
@@ -3571,7 +3582,13 @@ void BeebWin::ConfigureSerial()
{
if (SerialDestination == SerialType::SerialPort)
{
- SerialPortEnabled = true;
+ SerialPortEnabled = SerialInit(m_SerialPort.c_str());
+
+ if (!SerialPortEnabled)
+ {
+ Report(MessageType::Error,
+ "Could not open serial port %s", m_SerialPort.c_str());
+ }
}
else if (SerialDestination == SerialType::TouchScreen)
{
@@ -3598,11 +3615,11 @@ void BeebWin::ConfigureSerial()
void BeebWin::DisableSerial()
{
- /* if (SerialDestination == SerialType::SerialPort)
+ if (SerialDestination == SerialType::SerialPort)
{
SerialClose();
- } */
- if (SerialDestination == SerialType::TouchScreen)
+ }
+ else if (SerialDestination == SerialType::TouchScreen)
{
TouchScreenClose();
}
@@ -3612,16 +3629,6 @@ void BeebWin::DisableSerial()
}
}
-void BeebWin::SelectSerialPort(const char* PortName)
-{
- // DisableSerial();
- strcpy(SerialPortName, PortName);
- SerialDestination = SerialType::SerialPort;
- bSerialStateChanged = true;
-
- UpdateSerialMenu();
-}
-
void BeebWin::UpdateSerialMenu()
{
CheckMenuItem(IDM_SERIAL, SerialPortEnabled);
diff --git a/Src/BeebWin.h b/Src/BeebWin.h
index 35a6f888..7b8ab585 100644
--- a/Src/BeebWin.h
+++ b/Src/BeebWin.h
@@ -252,9 +252,9 @@ class BeebWin
void Shutdown();
static LRESULT CALLBACK WndProc(HWND hWnd,
- UINT nMessage,
- WPARAM wParam,
- LPARAM lParam);
+ UINT nMessage,
+ WPARAM wParam,
+ LPARAM lParam);
LRESULT WndProc(UINT nMessage, WPARAM wParam, LPARAM lParam);
@@ -413,7 +413,6 @@ class BeebWin
void ToggleSerial();
void DisableSerial();
void ConfigureSerial();
- void SelectSerialPort(const char *PortName);
void UpdateSerialMenu();
void OnIP232Error(int Error);
@@ -769,6 +768,9 @@ class BeebWin
std::string m_PrinterFileName;
std::string m_PrinterDevice;
+ // Serial
+ std::string m_SerialPort;
+
// Command line
char m_CommandLineFileName1[_MAX_PATH];
char m_CommandLineFileName2[_MAX_PATH];
diff --git a/Src/BeebWinPrefs.cpp b/Src/BeebWinPrefs.cpp
index 4e7def0a..36c915f4 100644
--- a/Src/BeebWinPrefs.cpp
+++ b/Src/BeebWinPrefs.cpp
@@ -1085,23 +1085,26 @@ void BeebWin::LoadTapePreferences(int Version)
void BeebWin::LoadSerialPortPreferences(int Version)
{
- if (m_Preferences.GetStringValue(CFG_SERIAL_PORT, SerialPortName))
+ if (m_Preferences.GetStringValue(CFG_SERIAL_PORT, m_SerialPort))
{
// For backwards compatibility with Preferences.cfg files from
// BeebEm 4.18 and earlier, which stored the port number as a
// binary value
- if (strlen(SerialPortName) == 2 &&
- isxdigit(SerialPortName[0]) &&
- isxdigit(SerialPortName[1]))
+ if (m_SerialPort.size() == 2 &&
+ isxdigit(m_SerialPort[0]) &&
+ isxdigit(m_SerialPort[1]))
{
int Port;
- sscanf(SerialPortName, "%x", &Port);
- sprintf(SerialPortName, "COM%d", Port);
+ sscanf(m_SerialPort.c_str(), "%x", &Port);
+
+ char PortName[20];
+ sprintf(PortName, "COM%d", Port);
+ m_SerialPort = PortName;
}
}
else
{
- strcpy(SerialPortName, "COM2");
+ m_SerialPort = "COM2";
}
m_Preferences.GetBoolValue(CFG_SERIAL_PORT_ENABLED, SerialPortEnabled, false);
@@ -1719,7 +1722,7 @@ void BeebWin::SavePreferences(bool saveAll)
m_Preferences.SetBoolValue(CFG_UNLOCK_TAPE, TapeState.Unlock);
// Serial port
- m_Preferences.SetStringValue(CFG_SERIAL_PORT, SerialPortName);
+ m_Preferences.SetStringValue(CFG_SERIAL_PORT, m_SerialPort);
m_Preferences.SetBoolValue(CFG_SERIAL_PORT_ENABLED, SerialPortEnabled);
m_Preferences.SetBoolValue(CFG_TOUCH_SCREEN_ENABLED, SerialDestination == SerialType::TouchScreen);
m_Preferences.SetBoolValue(CFG_IP232_ENABLED, SerialDestination == SerialType::IP232);
diff --git a/Src/IP232.cpp b/Src/IP232.cpp
index 76c4ada7..ecd825fc 100644
--- a/Src/IP232.cpp
+++ b/Src/IP232.cpp
@@ -70,15 +70,13 @@ int IP232Port;
static bool IP232FlagReceived = false;
-static bool IP232RTS = false;
-
// IP232 routines use InputBuffer as data coming in from the modem,
// and OutputBuffer for data to be sent out to the modem.
// StatusBuffer is used for changes to the serial ACIA status
// registers
-static RingBuffer InputBuffer;
-static RingBuffer OutputBuffer;
-static RingBuffer StatusBuffer;
+static RingBuffer InputBuffer(1024);
+static RingBuffer OutputBuffer(1024);
+static RingBuffer StatusBuffer(128);
CycleCountT IP232RxTrigger = CycleCountTMax;
@@ -284,17 +282,12 @@ unsigned char IP232ReadStatus()
void IP232SetRTS(bool RTS)
{
- if (RTS != IP232RTS)
- {
- DebugTrace("IP232SetRTS: RTS=%d\n", (int)RTS);
-
- if (IP232Handshake)
- {
- IP232Write(255);
- IP232Write(static_cast(RTS));
- }
+ DebugTrace("IP232SetRTS: RTS=%d\n", (int)RTS);
- IP232RTS = RTS;
+ if (IP232Handshake)
+ {
+ IP232Write(255);
+ IP232Write(static_cast(RTS));
}
}
diff --git a/Src/Main.cpp b/Src/Main.cpp
index 2c0428df..b493a92f 100644
--- a/Src/Main.cpp
+++ b/Src/Main.cpp
@@ -34,7 +34,8 @@ Boston, MA 02110-1301, USA.
#include "BeebWin.h"
#include "Log.h"
#include "SelectKeyDialog.h"
-#include "Serial.h"
+
+/****************************************************************************/
Model MachineType;
BeebWin *mainWin = nullptr;
@@ -42,6 +43,8 @@ HINSTANCE hInst;
HWND hCurrentDialog = nullptr;
HACCEL hCurrentAccelTable = nullptr;
+/****************************************************************************/
+
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
LPSTR /* lpszCmdLine */, int /* nCmdShow */)
{
@@ -62,9 +65,6 @@ int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
OpenLog();
- // Create serial threads
- SerialInit();
-
for (;;)
{
MSG msg;
@@ -107,16 +107,17 @@ int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
}
}
- if (!mainWin->IsFrozen() && !mainWin->IsPaused()) {
+ if (!mainWin->IsFrozen() && !mainWin->IsPaused())
+ {
Exec6502Instruction();
}
}
CloseLog();
- SerialClose();
-
delete mainWin;
return 0;
}
+
+/****************************************************************************/
diff --git a/Src/RingBuffer.cpp b/Src/RingBuffer.cpp
index 701252d0..5713ea57 100644
--- a/Src/RingBuffer.cpp
+++ b/Src/RingBuffer.cpp
@@ -24,13 +24,22 @@ Boston, MA 02110-1301, USA.
/*****************************************************************************/
-RingBuffer::RingBuffer()
+RingBuffer::RingBuffer(int Size) :
+ m_pBuffer(new unsigned char[Size]),
+ m_Size(Size)
{
Reset();
}
/*****************************************************************************/
+RingBuffer::~RingBuffer()
+{
+ delete [] m_pBuffer;
+}
+
+/*****************************************************************************/
+
void RingBuffer::Reset()
{
m_Head = 0;
@@ -51,8 +60,8 @@ unsigned char RingBuffer::GetData()
{
assert(m_Length > 0);
- unsigned char Data = m_Buffer[m_Head];
- m_Head = (m_Head + 1) % BUFFER_SIZE;
+ unsigned char Data = m_pBuffer[m_Head];
+ m_Head = (m_Head + 1) % m_Size;
m_Length--;
return Data;
@@ -62,10 +71,10 @@ unsigned char RingBuffer::GetData()
bool RingBuffer::PutData(unsigned char Data)
{
- if (m_Length != BUFFER_SIZE)
+ if (m_Length != m_Size)
{
- m_Buffer[m_Tail] = Data;
- m_Tail = (m_Tail + 1) % BUFFER_SIZE;
+ m_pBuffer[m_Tail] = Data;
+ m_Tail = (m_Tail + 1) % m_Size;
m_Length++;
return true;
}
@@ -77,7 +86,7 @@ bool RingBuffer::PutData(unsigned char Data)
int RingBuffer::GetSpace() const
{
- return BUFFER_SIZE - m_Length;
+ return m_Size - m_Length;
}
/*****************************************************************************/
diff --git a/Src/RingBuffer.h b/Src/RingBuffer.h
index c1e956b9..a146db8b 100644
--- a/Src/RingBuffer.h
+++ b/Src/RingBuffer.h
@@ -24,9 +24,10 @@ Boston, MA 02110-1301, USA.
class RingBuffer
{
public:
- RingBuffer();
+ explicit RingBuffer(int Size);
RingBuffer(const RingBuffer&) = delete;
RingBuffer& operator=(const RingBuffer&) = delete;
+ ~RingBuffer();
public:
void Reset();
@@ -37,8 +38,8 @@ class RingBuffer
int GetLength() const;
private:
- static const int BUFFER_SIZE = 10240;
- unsigned char m_Buffer[BUFFER_SIZE];
+ unsigned char* m_pBuffer;
+ int m_Size;
int m_Head;
int m_Tail;
int m_Length;
diff --git a/Src/Serial.cpp b/Src/Serial.cpp
index f88bb9f9..ed9f83ff 100644
--- a/Src/Serial.cpp
+++ b/Src/Serial.cpp
@@ -46,6 +46,7 @@ Boston, MA 02110-1301, USA.
#include "Log.h"
#include "Main.h"
#include "Resource.h"
+#include "SerialPort.h"
#include "Sound.h"
#include "TapeControlDialog.h"
#include "TapeMap.h"
@@ -61,7 +62,7 @@ static bool FirstReset = true;
static UEFFileReader UEFReader;
static UEFFileWriter UEFWriter;
-char TapeFileName[256]; // Filename of current tape file
+char TapeFileName[MAX_PATH]; // Filename of current tape file
static bool UEFFileOpen = false;
static bool CSWFileOpen = false;
@@ -111,55 +112,8 @@ constexpr int TAPECYCLES = CPU_CYCLES_PER_SECOND / 5600; // 5600 is normal tape
// This bit is the Serial Port stuff
bool SerialPortEnabled;
-char SerialPortName[_MAX_PATH];
-class SerialPortReadThread : public Thread
-{
- public:
- virtual unsigned int ThreadFunc();
-};
-
-class SerialPortStatusThread : public Thread
-{
- public:
- virtual unsigned int ThreadFunc();
-};
-
-SerialPortReadThread SerialReadThread;
-SerialPortStatusThread SerialStatusThread;
-volatile bool bSerialStateChanged = false;
-
-class Win32SerialPort
-{
- public:
- Win32SerialPort();
-
- bool Init(const char* PortName);
- void Close();
- bool SetBaudRate(int BaudRate);
- bool Configure(unsigned char DataBits, unsigned char StopBits, unsigned char Parity);
- bool SetRTS(bool RTS);
-
- bool WriteChar(unsigned char Data);
-
- public:
- HANDLE hSerialPort; // Serial port handle
- unsigned int SerialBuffer;
- unsigned int SerialWriteBuffer;
- DWORD BytesIn;
- DWORD BytesOut;
- DWORD dwCommEvent;
- OVERLAPPED olSerialPort;
- OVERLAPPED olSerialWrite;
- OVERLAPPED olStatus;
- volatile bool bWaitingForData;
- volatile bool bWaitingForStat;
- volatile bool bCharReady;
-};
-
-static Win32SerialPort SerialPort;
-
-static void InitSerialPort();
+static SerialPort SerialPort;
SerialACIAType SerialACIA;
@@ -176,183 +130,6 @@ static SerialULAType SerialULA;
/*--------------------------------------------------------------------------*/
-Win32SerialPort::Win32SerialPort() :
- hSerialPort(INVALID_HANDLE_VALUE),
- SerialBuffer(0),
- SerialWriteBuffer(0),
- BytesIn(0),
- BytesOut(0),
- dwCommEvent(0),
- bWaitingForData(false),
- bWaitingForStat(false),
- bCharReady(false)
-{
- ZeroMemory(&olSerialPort, sizeof(olSerialPort));
- ZeroMemory(&olSerialWrite, sizeof(olSerialWrite));
- ZeroMemory(&olStatus, sizeof(olStatus));
-}
-
-/*--------------------------------------------------------------------------*/
-
-bool Win32SerialPort::Init(const char* PortName)
-{
- char FileName[MAX_PATH];
- sprintf(FileName, "\\\\.\\%s", PortName);
-
- COMMTIMEOUTS CommTimeOuts{};
- DCB dcb{}; // Serial port device control block
-
- hSerialPort = CreateFile(FileName,
- GENERIC_READ | GENERIC_WRITE,
- 0, // dwShareMode
- nullptr, // lpSecurityAttributes
- OPEN_EXISTING,
- FILE_FLAG_OVERLAPPED,
- nullptr); // hTemplateFile
-
- if (hSerialPort == INVALID_HANDLE_VALUE)
- {
- return false;
- }
-
- if (!SetupComm(hSerialPort, 1024, 1024))
- {
- goto Fail;
- }
-
- dcb.DCBlength = sizeof(dcb);
-
- if (!GetCommState(hSerialPort, &dcb))
- {
- goto Fail;
- }
-
- dcb.fBinary = TRUE;
- dcb.BaudRate = 9600;
- dcb.Parity = NOPARITY;
- dcb.StopBits = ONESTOPBIT;
- dcb.ByteSize = 8;
- dcb.fDtrControl = DTR_CONTROL_DISABLE;
- dcb.fOutxCtsFlow = FALSE;
- dcb.fOutxDsrFlow = FALSE;
- dcb.fOutX = FALSE;
- dcb.fDsrSensitivity = FALSE;
- dcb.fInX = FALSE;
- dcb.fRtsControl = RTS_CONTROL_DISABLE; // Leave it low (do not send) for now
-
- if (!SetCommState(hSerialPort, &dcb))
- {
- goto Fail;
- }
-
- CommTimeOuts.ReadIntervalTimeout = MAXDWORD;
- CommTimeOuts.ReadTotalTimeoutConstant = 0;
- CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
- CommTimeOuts.WriteTotalTimeoutConstant = 0;
- CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
-
- if (!SetCommTimeouts(hSerialPort, &CommTimeOuts))
- {
- goto Fail;
- }
-
- if (!SetCommMask(hSerialPort, EV_CTS | EV_RXCHAR | EV_ERR))
- {
- goto Fail;
- }
-
- return true;
-
-Fail:
- Close();
-
- return false;
-}
-
-/*--------------------------------------------------------------------------*/
-
-void Win32SerialPort::Close()
-{
- if (hSerialPort != INVALID_HANDLE_VALUE)
- {
- CloseHandle(hSerialPort);
- hSerialPort = INVALID_HANDLE_VALUE;
- }
-}
-
-/*--------------------------------------------------------------------------*/
-
-bool Win32SerialPort::SetBaudRate(int BaudRate)
-{
- DCB dcb{}; // Serial port device control block
- dcb.DCBlength = sizeof(dcb);
-
- if (!GetCommState(hSerialPort, &dcb))
- {
- return false;
- }
-
- dcb.BaudRate = BaudRate;
- dcb.DCBlength = sizeof(dcb);
-
- if (!SetCommState(hSerialPort, &dcb))
- {
- return false;
- }
-
- return true;
-}
-
-/*--------------------------------------------------------------------------*/
-
-bool Win32SerialPort::Configure(unsigned char DataBits, unsigned char StopBits, unsigned char Parity)
-{
- DCB dcb{}; // Serial port device control block
- dcb.DCBlength = sizeof(dcb);
-
- if (!GetCommState(hSerialPort, &dcb))
- {
- return false;
- }
-
- dcb.ByteSize = DataBits;
- dcb.StopBits = (StopBits == 1) ? ONESTOPBIT : TWOSTOPBITS;
- dcb.Parity = Parity;
- dcb.DCBlength = sizeof(dcb);
-
- if (!SetCommState(hSerialPort, &dcb))
- {
- return false;
- }
-
- return true;
-}
-
-/*--------------------------------------------------------------------------*/
-
-bool Win32SerialPort::SetRTS(bool RTS)
-{
- if (!EscapeCommFunction(hSerialPort, RTS ? CLRRTS : SETRTS))
- {
- return false;
- }
-
- return true;
-}
-
-/*--------------------------------------------------------------------------*/
-
-bool Win32SerialPort::WriteChar(unsigned char Data)
-{
- SerialWriteBuffer = Data;
-
- WriteFile(hSerialPort, &SerialWriteBuffer, 1, &BytesOut, &olSerialWrite);
-
- return true;
-}
-
-/*--------------------------------------------------------------------------*/
-
// mm
static void SerialUpdateACIAInterruptStatus()
{
@@ -383,8 +160,6 @@ void SerialACIAWriteControl(unsigned char Value)
"Serial: Write ACIA control %02X", (int)Value);
}
- SerialACIA.Control = Value; // This is done for safe keeping
-
// Master reset - clear all bits in the status register, except for
// external conditions on CTS and DCD.
if ((Value & MC6850_CONTROL_COUNTER_DIVIDE) == MC6850_CONTROL_MASTER_RESET)
@@ -415,6 +190,13 @@ void SerialACIAWriteControl(unsigned char Value)
SetTrigger(TAPECYCLES, TapeTrigger);
}
+ unsigned char OldWordSelect = SerialACIA.Control & MC6850_CONTROL_WORD_SELECT;
+ unsigned char NewWordSelect = Value & MC6850_CONTROL_WORD_SELECT;
+
+ bool OldRTS = SerialACIA.RTS;
+
+ SerialACIA.Control = Value; // This is done for safe keeping
+
// Clock Divide
if ((Value & MC6850_CONTROL_COUNTER_DIVIDE) == 0x00) SerialACIA.ClkDivide = 1;
if ((Value & MC6850_CONTROL_COUNTER_DIVIDE) == 0x01) SerialACIA.ClkDivide = 16;
@@ -442,14 +224,25 @@ void SerialACIAWriteControl(unsigned char Value)
{
if (SerialDestination == SerialType::SerialPort)
{
- SerialPort.Configure(SerialACIA.DataBits, SerialACIA.StopBits, SerialACIA.Parity);
+ if (NewWordSelect != OldWordSelect)
+ {
+ SerialPort.Configure(SerialACIA.DataBits,
+ SerialACIA.StopBits,
+ SerialACIA.Parity);
+ }
// Check RTS
- SerialPort.SetRTS(SerialACIA.RTS);
+ if (SerialACIA.RTS != OldRTS)
+ {
+ SerialPort.SetRTS(SerialACIA.RTS);
+ }
}
else if (SerialDestination == SerialType::IP232)
{
- IP232SetRTS(SerialACIA.RTS);
+ if (SerialACIA.RTS != OldRTS)
+ {
+ IP232SetRTS(SerialACIA.RTS);
+ }
}
}
@@ -1050,209 +843,31 @@ void SerialPoll(int Cycles)
}
else // SerialType::SerialPort
{
- if (!SerialPort.bWaitingForStat && !bSerialStateChanged)
+ if (SerialPort.HasRxData() && SerialACIA.RxD < 2)
{
- WaitCommEvent(SerialPort.hSerialPort, &SerialPort.dwCommEvent, &SerialPort.olStatus);
- SerialPort.bWaitingForStat = true;
- }
+ unsigned char Data = SerialPort.GetRxData();
- if (!bSerialStateChanged && SerialPort.bCharReady && !SerialPort.bWaitingForData && SerialACIA.RxD < 2)
- {
- if (!ReadFile(SerialPort.hSerialPort, &SerialPort.SerialBuffer, 1, &SerialPort.BytesIn, &SerialPort.olSerialPort))
- {
- if (GetLastError() == ERROR_IO_PENDING)
- {
- SerialPort.bWaitingForData = true;
- }
- else
- {
- mainWin->Report(MessageType::Error, "Serial Port Error");
- }
- }
- else
- {
- if (SerialPort.BytesIn > 0)
- {
- HandleData((unsigned char)SerialPort.SerialBuffer);
- }
- else
- {
- DWORD CommError;
- ClearCommError(SerialPort.hSerialPort, &CommError, nullptr);
- SerialPort.bCharReady = false;
- }
- }
+ HandleData(Data);
}
- }
- }
-}
-
-/*--------------------------------------------------------------------------*/
-
-static void InitThreads()
-{
- SerialPort.Close();
- SerialPort.bWaitingForData = false;
- SerialPort.bWaitingForStat = false;
-
- if (SerialPortEnabled &&
- SerialDestination == SerialType::SerialPort &&
- SerialPortName[0] != '\0')
- {
- InitSerialPort(); // Set up the serial port if its enabled.
-
- if (SerialPort.olSerialPort.hEvent)
- {
- CloseHandle(SerialPort.olSerialPort.hEvent);
- SerialPort.olSerialPort.hEvent = nullptr;
- }
-
- SerialPort.olSerialPort.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); // Create the serial port event signal
-
- if (SerialPort.olSerialWrite.hEvent)
- {
- CloseHandle(SerialPort.olSerialWrite.hEvent);
- SerialPort.olSerialWrite.hEvent = nullptr;
- }
-
- SerialPort.olSerialWrite.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); // Write event, not actually used.
-
- if (SerialPort.olStatus.hEvent)
- {
- CloseHandle(SerialPort.olStatus.hEvent);
- SerialPort.olStatus.hEvent = nullptr;
- }
-
- SerialPort.olStatus.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); // Status event, for WaitCommEvent
- }
-
- bSerialStateChanged = false;
-}
-
-/*--------------------------------------------------------------------------*/
-
-unsigned int SerialPortStatusThread::ThreadFunc()
-{
- DWORD dwOvRes = 0;
-
- while (1)
- {
- if (SerialDestination == SerialType::SerialPort &&
- SerialPortEnabled &&
- (WaitForSingleObject(SerialPort.olStatus.hEvent, 10) == WAIT_OBJECT_0))
- {
- if (GetOverlappedResult(SerialPort.hSerialPort, &SerialPort.olStatus, &dwOvRes, FALSE))
+ if (SerialPort.HasStatus())
{
- // Event waiting in dwCommEvent
- if ((SerialPort.dwCommEvent & EV_RXCHAR) && !SerialPort.bWaitingForData)
- {
- SerialPort.bCharReady = true;
- }
+ // CTS line change
+ unsigned char ModemStatus = SerialPort.GetStatus();
- if (SerialPort.dwCommEvent & EV_CTS)
+ // Invert for CTS bit, Keep for TDRE bit
+ if (ModemStatus & MS_CTS_ON)
{
- // CTS line change
- DWORD LineStat;
- GetCommModemStatus(SerialPort.hSerialPort, &LineStat);
-
- // Invert for CTS bit, Keep for TDRE bit
- if (LineStat & MS_CTS_ON)
- {
- SerialACIA.Status &= ~MC6850_STATUS_CTS;
- SerialACIA.Status |= MC6850_STATUS_TDRE;
- }
- else
- {
- SerialACIA.Status |= MC6850_STATUS_CTS;
- SerialACIA.Status &= ~MC6850_STATUS_TDRE;
- }
+ SerialACIA.Status &= ~MC6850_STATUS_CTS;
+ SerialACIA.Status |= MC6850_STATUS_TDRE;
}
- }
-
- SerialPort.bWaitingForStat = false;
- }
- else
- {
- Sleep(100); // Don't hog CPU if nothing happening
- }
-
- if (bSerialStateChanged && !SerialPort.bWaitingForData)
- {
- // Shut off serial port, and re-initialise
- InitThreads();
- bSerialStateChanged = false;
- }
-
- Sleep(0);
- }
-
- return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-unsigned int SerialPortReadThread::ThreadFunc()
-{
- // New Serial port thread - 7:35pm 16/10/2001 GMT
- // This sorta runs as a seperate process in effect, checking
- // enable status, and doing the monitoring.
-
- while (1)
- {
- if (!bSerialStateChanged && SerialPortEnabled && SerialDestination == SerialType::SerialPort && SerialPort.bWaitingForData)
- {
- DWORD Result = WaitForSingleObject(SerialPort.olSerialPort.hEvent, INFINITE); // 10ms to respond
-
- if (Result == WAIT_OBJECT_0)
- {
- if (GetOverlappedResult(SerialPort.hSerialPort, &SerialPort.olSerialPort, &SerialPort.BytesIn, FALSE))
+ else
{
- // sucessful read, screw any errors.
- if (SerialULA.RS423 && SerialPort.BytesIn > 0)
- {
- HandleData((unsigned char)SerialPort.SerialBuffer);
- }
-
- if (SerialPort.BytesIn == 0)
- {
- SerialPort.bCharReady = false;
-
- DWORD CommError;
- ClearCommError(SerialPort.hSerialPort, &CommError, nullptr);
- }
-
- SerialPort.bWaitingForData = false;
+ SerialACIA.Status |= MC6850_STATUS_CTS;
+ SerialACIA.Status &= ~MC6850_STATUS_TDRE;
}
}
}
- else
- {
- Sleep(100); // Don't hog CPU if nothing happening
- }
-
- Sleep(0);
- }
-
- return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-static void InitSerialPort()
-{
- // Initialise COM port
- if (SerialPortEnabled &&
- SerialDestination == SerialType::SerialPort &&
- SerialPortName[0] != '\0')
- {
- if (!SerialPort.Init(SerialPortName))
- {
- mainWin->Report(MessageType::Error, "Could not open serial port %s", SerialPortName);
- bSerialStateChanged = true;
- SerialPortEnabled = false;
- mainWin->UpdateSerialMenu();
- }
}
}
@@ -1281,12 +896,11 @@ static void CloseCSWFile()
/*--------------------------------------------------------------------------*/
-void SerialInit()
-{
- InitThreads();
+// Set up the serial port.
- SerialReadThread.Start();
- SerialStatusThread.Start();
+bool SerialInit(const char* PortName)
+{
+ return SerialPort.Init(PortName);
}
/*--------------------------------------------------------------------------*/
@@ -1312,7 +926,6 @@ void SerialReset()
void SerialClose()
{
- CloseTape();
SerialPort.Close();
}
@@ -1743,3 +1356,5 @@ void DebugSerialState()
SerialACIA.RxRate,
SerialACIA.TxRate);
}
+
+/*--------------------------------------------------------------------------*/
diff --git a/Src/Serial.h b/Src/Serial.h
index d22b5057..ee7878b7 100644
--- a/Src/Serial.h
+++ b/Src/Serial.h
@@ -98,9 +98,8 @@ void SerialULAWrite(unsigned char Value);
unsigned char SerialULARead();
extern bool SerialPortEnabled;
-extern char SerialPortName[_MAX_PATH];
-void SerialInit();
+bool SerialInit(const char* PortName);
void SerialReset();
void SerialPoll(int Cycles);
void SerialClose();
@@ -109,8 +108,6 @@ CSWResult LoadCSWTape(const char *FileName);
void CloseTape();
void RewindTape();
-extern volatile bool bSerialStateChanged;
-
struct TapeStateType
{
bool Playing;
@@ -136,7 +133,7 @@ void SerialStopTapeRecording(bool ReloadTape);
void SerialEjectTape();
int SerialGetTapeClock();
-extern char TapeFileName[256];
+extern char TapeFileName[MAX_PATH];
enum class SerialTapeState
{
diff --git a/Src/SerialPort.cpp b/Src/SerialPort.cpp
new file mode 100644
index 00000000..dfb01682
--- /dev/null
+++ b/Src/SerialPort.cpp
@@ -0,0 +1,554 @@
+/****************************************************************
+BeebEm - BBC Micro and Master 128 Emulator
+Copyright (C) 2024 Chris Needham
+
+This program 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.
+
+This program 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 this program; if not, write to the Free
+Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
+****************************************************************/
+
+#include
+
+#include
+#include
+
+#include "SerialPort.h"
+#include "DebugTrace.h"
+
+/*--------------------------------------------------------------------------*/
+
+SerialPort::SerialPort() :
+ m_hSerialPort(INVALID_HANDLE_VALUE),
+ m_hReadThread(nullptr),
+ m_hReadStartUpEvent(nullptr),
+ m_hReadShutDownEvent(nullptr),
+ m_dwCommEvent(0),
+ m_RxBuffer(1024),
+ m_StatusBuffer(128)
+{
+ ZeroMemory(&m_OverlappedRead, sizeof(m_OverlappedRead));
+ ZeroMemory(&m_OverlappedWrite, sizeof(m_OverlappedWrite));
+ ZeroMemory(&m_BufferLock, sizeof(m_BufferLock));
+}
+
+/*--------------------------------------------------------------------------*/
+
+SerialPort::~SerialPort()
+{
+ Close();
+}
+
+/*--------------------------------------------------------------------------*/
+
+bool SerialPort::Init(const char* PortName)
+{
+ char FileName[MAX_PATH];
+ sprintf(FileName, "\\\\.\\%s", PortName);
+
+ COMMTIMEOUTS CommTimeOuts{};
+ DCB dcb{}; // Serial port device control block
+
+ m_hSerialPort = CreateFile(FileName,
+ GENERIC_READ | GENERIC_WRITE,
+ 0, // dwShareMode
+ nullptr, // lpSecurityAttributes
+ OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED,
+ nullptr); // hTemplateFile
+
+ if (m_hSerialPort == INVALID_HANDLE_VALUE)
+ {
+ goto Fail;
+ }
+
+ if (!SetupComm(m_hSerialPort, 1024, 1024))
+ {
+ goto Fail;
+ }
+
+ dcb.DCBlength = sizeof(dcb);
+
+ if (!GetCommState(m_hSerialPort, &dcb))
+ {
+ goto Fail;
+ }
+
+ dcb.fBinary = TRUE;
+ dcb.BaudRate = 9600;
+ dcb.Parity = NOPARITY;
+ dcb.StopBits = ONESTOPBIT;
+ dcb.ByteSize = 8;
+ dcb.fDtrControl = DTR_CONTROL_DISABLE;
+ dcb.fOutxCtsFlow = FALSE;
+ dcb.fOutxDsrFlow = FALSE;
+ dcb.fOutX = FALSE;
+ dcb.fDsrSensitivity = FALSE;
+ dcb.fInX = FALSE;
+ dcb.fRtsControl = RTS_CONTROL_DISABLE; // Leave it low (do not send) for now
+
+ if (!SetCommState(m_hSerialPort, &dcb))
+ {
+ goto Fail;
+ }
+
+ CommTimeOuts.ReadIntervalTimeout = MAXDWORD;
+ CommTimeOuts.ReadTotalTimeoutConstant = 0;
+ CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
+ CommTimeOuts.WriteTotalTimeoutConstant = 0;
+ CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
+
+ if (!SetCommTimeouts(m_hSerialPort, &CommTimeOuts))
+ {
+ goto Fail;
+ }
+
+ // Configure the conditions for WaitCommEvent() to signal an event.
+ if (!SetCommMask(m_hSerialPort, EV_CTS | EV_RXCHAR | EV_ERR))
+ {
+ goto Fail;
+ }
+
+ return InitThread();
+
+Fail:
+ Close();
+
+ return false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+// Create the thread to wait on the I/O event object. Wait for the thread
+// to start up before returning.
+
+bool SerialPort::InitThread()
+{
+ InitializeCriticalSection(&m_BufferLock);
+
+ ZeroMemory(&m_OverlappedRead, sizeof(m_OverlappedRead));
+ ZeroMemory(&m_OverlappedWrite, sizeof(m_OverlappedWrite));
+
+ m_hReadStartUpEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
+
+ if (m_hReadStartUpEvent == nullptr)
+ {
+ return false;
+ }
+
+ m_hReadShutDownEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
+
+ if (m_hReadShutDownEvent == nullptr)
+ {
+ return false;
+ }
+
+ m_OverlappedRead.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
+
+ if (m_OverlappedRead.hEvent == nullptr)
+ {
+ return false;
+ }
+
+ // Create the thread.
+
+ unsigned int ThreadID = 0;
+
+ m_hReadThread = (HANDLE)_beginthreadex(
+ nullptr, // security
+ 0, // stack_size
+ ReadThreadFunc, // start_address
+ this, // arglist
+ 0, // initflag
+ &ThreadID // thrdaddr
+ );
+
+ if (m_hReadThread == nullptr)
+ {
+ return false;
+ }
+
+ DWORD dwResult = WaitForSingleObject(m_hReadStartUpEvent, INFINITE);
+
+ if (dwResult != WAIT_OBJECT_0)
+ {
+ return false;
+ }
+
+ // Wait for a comm event.
+
+ m_dwCommEvent = 0;
+
+ if (!WaitCommEvent(m_hSerialPort, &m_dwCommEvent, &m_OverlappedRead))
+ {
+ if (GetLastError() != ERROR_IO_PENDING)
+ {
+ DebugTrace("Failed to initiate port event wait\n");
+ return false;
+ }
+ }
+
+ m_RxBuffer.Reset();
+ m_StatusBuffer.Reset();
+
+ return true;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void SerialPort::Close()
+{
+ if (m_hReadThread != nullptr)
+ {
+ SetEvent(m_hReadShutDownEvent);
+
+ WaitForSingleObject(m_hReadThread, INFINITE);
+
+ CloseHandle(m_hReadThread);
+ m_hReadThread = nullptr;
+ }
+
+ if (m_hSerialPort != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(m_hSerialPort);
+ m_hSerialPort = INVALID_HANDLE_VALUE;
+ }
+
+ if (m_hReadStartUpEvent != nullptr)
+ {
+ CloseHandle(m_hReadStartUpEvent);
+ m_hReadStartUpEvent = nullptr;
+ }
+
+ if (m_hReadShutDownEvent != nullptr)
+ {
+ CloseHandle(m_hReadShutDownEvent);
+ m_hReadShutDownEvent = nullptr;
+ }
+
+ if (m_OverlappedRead.hEvent != nullptr)
+ {
+ CloseHandle(m_OverlappedRead.hEvent);
+ m_OverlappedRead.hEvent = nullptr;
+ }
+
+ DeleteCriticalSection(&m_BufferLock);
+
+ m_RxBuffer.Reset();
+ m_StatusBuffer.Reset();
+}
+
+/*--------------------------------------------------------------------------*/
+
+bool SerialPort::SetBaudRate(int BaudRate)
+{
+ DebugTrace("SerialPort::SetBaudRate\n");
+
+ if (m_hSerialPort == INVALID_HANDLE_VALUE)
+ {
+ return false;
+ }
+
+ DCB dcb{}; // Serial port device control block
+ dcb.DCBlength = sizeof(dcb);
+
+ if (!GetCommState(m_hSerialPort, &dcb))
+ {
+ return false;
+ }
+
+ dcb.BaudRate = BaudRate;
+ dcb.DCBlength = sizeof(dcb);
+
+ if (!SetCommState(m_hSerialPort, &dcb))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+/*--------------------------------------------------------------------------*/
+
+bool SerialPort::Configure(unsigned char DataBits,
+ unsigned char StopBits,
+ unsigned char Parity)
+{
+ DebugTrace("SerialPort::Configure DataBits=%d StopBits=%d Parity=%d\n", DataBits, StopBits, Parity);
+
+ if (m_hSerialPort == INVALID_HANDLE_VALUE)
+ {
+ return false;
+ }
+
+ DCB dcb{}; // Serial port device control block
+ dcb.DCBlength = sizeof(dcb);
+
+ if (!GetCommState(m_hSerialPort, &dcb))
+ {
+ return false;
+ }
+
+ dcb.ByteSize = DataBits;
+ dcb.StopBits = (StopBits == 1) ? ONESTOPBIT : TWOSTOPBITS;
+ dcb.Parity = Parity;
+ dcb.DCBlength = sizeof(dcb);
+
+ if (!SetCommState(m_hSerialPort, &dcb))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+/*--------------------------------------------------------------------------*/
+
+bool SerialPort::SetRTS(bool RTS)
+{
+ DebugTrace("SerialPort::SetRTS\n");
+
+ if (m_hSerialPort == INVALID_HANDLE_VALUE)
+ {
+ return false;
+ }
+
+ if (!EscapeCommFunction(m_hSerialPort, RTS ? CLRRTS : SETRTS))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+/*--------------------------------------------------------------------------*/
+
+bool SerialPort::WriteChar(unsigned char Data)
+{
+ DWORD BytesSent = 0;
+
+ bool Success = !!WriteFile(m_hSerialPort,
+ &Data,
+ 1,
+ &BytesSent,
+ &m_OverlappedWrite);
+
+ if (!Success)
+ {
+ DWORD Error = GetLastError();
+
+ if (Error == ERROR_IO_PENDING)
+ {
+ DWORD WaitResult = WaitForSingleObject(m_OverlappedWrite.hEvent, INFINITE);
+
+ Success = WaitResult == WAIT_OBJECT_0;
+ }
+ else
+ {
+ DebugTrace("WriteFile failed, code %lu", (ULONG)Error);
+ }
+ }
+
+ return Success;
+}
+
+/*--------------------------------------------------------------------------*/
+
+bool SerialPort::HasRxData() const
+{
+ return m_RxBuffer.HasData();
+}
+
+/*--------------------------------------------------------------------------*/
+
+unsigned char SerialPort::GetRxData()
+{
+ EnterCriticalSection(&m_BufferLock);
+
+ unsigned char Data = m_RxBuffer.GetData();
+
+ LeaveCriticalSection(&m_BufferLock);
+
+ return Data;
+}
+
+/*--------------------------------------------------------------------------*/
+
+bool SerialPort::HasStatus() const
+{
+ return m_StatusBuffer.HasData();
+}
+
+/*--------------------------------------------------------------------------*/
+
+unsigned char SerialPort::GetStatus()
+{
+ EnterCriticalSection(&m_BufferLock);
+
+ unsigned char Data = m_StatusBuffer.GetData();
+
+ LeaveCriticalSection(&m_BufferLock);
+
+ return Data;
+}
+
+/*--------------------------------------------------------------------------*/
+
+unsigned int __stdcall SerialPort::ReadThreadFunc(void* pParameter)
+{
+ SerialPort* pSerialPort = static_cast(pParameter);
+
+ if (pSerialPort != nullptr)
+ {
+ pSerialPort->ReadThreadFunc();
+ }
+
+ return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void SerialPort::ReadThreadFunc()
+{
+ // Notify the parent thread that this thread has started running.
+ SetEvent(m_hReadStartUpEvent);
+
+ DebugTrace("ReadThreadFunc started\n");
+
+ bool bQuit = false;
+
+ while (!bQuit)
+ {
+ HANDLE hEvents[] = { m_OverlappedRead.hEvent, m_hReadShutDownEvent };
+
+ // Wait for one of the event objects to become signalled.
+ DWORD Result = WaitForMultipleObjects(_countof(hEvents), hEvents, FALSE, INFINITE);
+
+ switch (Result)
+ {
+ case WAIT_OBJECT_0 + 0:
+ // Clear comms port line errors, if any.
+ if (m_dwCommEvent & EV_ERR)
+ {
+ DWORD Error = 0;
+
+ if (ClearCommError(m_hSerialPort, &Error, nullptr))
+ {
+ DebugTrace("Comms error %lu (framing, overrun, parity)\n", Error);
+ }
+ }
+
+ // Process received characters, if any.
+ if (m_dwCommEvent & EV_RXCHAR)
+ {
+ const int BUFFER_LENGTH = 256;
+ unsigned char Buffer[BUFFER_LENGTH];
+
+ int Pos = 0;
+
+ for (;;)
+ {
+ unsigned char Data;
+ DWORD BytesRead = 0;
+
+ OVERLAPPED Overlapped{};
+
+ BOOL Success = ReadFile(m_hSerialPort, // hFile
+ &Data, // lpBuffer
+ 1, // nNumberOfBytesToRead
+ &BytesRead, // lpNumberOfBytesRead
+ &Overlapped); // lpOverlapped
+
+ if (Success && BytesRead == 1)
+ {
+ Buffer[Pos] = Data;
+
+ if (++Pos == BUFFER_LENGTH)
+ {
+ PutRxData(Buffer, BUFFER_LENGTH);
+ Pos = 0;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (Pos > 0)
+ {
+ PutRxData(Buffer, Pos);
+ }
+ }
+
+ if (m_dwCommEvent & EV_CTS)
+ {
+ DWORD ModemStatus = 0;
+
+ if (GetCommModemStatus(m_hSerialPort, &ModemStatus))
+ {
+ PutCommStatus((unsigned char)ModemStatus);
+ }
+ }
+
+ // Prepare for the next comms event.
+ ResetEvent(m_OverlappedRead.hEvent);
+ WaitCommEvent(m_hSerialPort, &m_dwCommEvent, &m_OverlappedRead);
+ break;
+
+ case WAIT_OBJECT_0 + 1:
+ // The thread has been signalled to terminate.
+ DebugTrace("Overlapped I/O read thread shutdown event signalled\n");
+
+ bQuit = true;
+ break;
+
+ default:
+ // Unexpected return code - terminate the thread.
+ Result = GetLastError();
+ DebugTrace("Overlapped I/O thread WaitForMultipleObjects failed, code %lu\n", (ULONG)Result);
+
+ bQuit = true;
+ break;
+ }
+ }
+
+ DebugTrace("ReadThreadFunc stopped\n");
+}
+
+/*--------------------------------------------------------------------------*/
+
+void SerialPort::PutRxData(const unsigned char* pData, int Length)
+{
+ EnterCriticalSection(&m_BufferLock);
+
+ for (int i = 0; i < Length; i++)
+ {
+ m_RxBuffer.PutData(pData[i]);
+ }
+
+ LeaveCriticalSection(&m_BufferLock);
+}
+
+/*--------------------------------------------------------------------------*/
+
+void SerialPort::PutCommStatus(unsigned char Status)
+{
+ EnterCriticalSection(&m_BufferLock);
+
+ m_StatusBuffer.PutData(Status);
+
+ LeaveCriticalSection(&m_BufferLock);
+}
+
+/*--------------------------------------------------------------------------*/
diff --git a/Src/SerialPort.h b/Src/SerialPort.h
new file mode 100644
index 00000000..a703a388
--- /dev/null
+++ b/Src/SerialPort.h
@@ -0,0 +1,72 @@
+/****************************************************************
+BeebEm - BBC Micro and Master 128 Emulator
+Copyright (C) 2024 Chris Needham
+
+This program 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.
+
+This program 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 this program; if not, write to the Free
+Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
+****************************************************************/
+
+#ifndef SERIAL_PORT_HEADER
+#define SERIAL_PORT_HEADER
+
+#include "RingBuffer.h"
+
+class SerialPort
+{
+ public:
+ SerialPort();
+ SerialPort(const SerialPort&) = delete;
+ SerialPort& operator=(const SerialPort&) = delete;
+ ~SerialPort();
+
+ public:
+ bool Init(const char* PortName);
+ void Close();
+
+ bool SetBaudRate(int BaudRate);
+ bool Configure(unsigned char DataBits, unsigned char StopBits, unsigned char Parity);
+ bool SetRTS(bool RTS);
+
+ bool WriteChar(unsigned char Data);
+
+ bool HasRxData() const;
+ unsigned char GetRxData();
+
+ bool HasStatus() const;
+ unsigned char GetStatus();
+
+ private:
+ bool InitThread();
+
+ static unsigned int __stdcall ReadThreadFunc(void* pParameter);
+ void ReadThreadFunc();
+
+ void PutRxData(const unsigned char* pData, int Length);
+ void PutCommStatus(unsigned char Status);
+
+ private:
+ HANDLE m_hSerialPort;
+ HANDLE m_hReadThread;
+ HANDLE m_hReadStartUpEvent;
+ HANDLE m_hReadShutDownEvent;
+ DWORD m_dwCommEvent;
+ OVERLAPPED m_OverlappedRead;
+ OVERLAPPED m_OverlappedWrite;
+ RingBuffer m_RxBuffer;
+ RingBuffer m_StatusBuffer;
+ CRITICAL_SECTION m_BufferLock;
+};
+
+#endif
diff --git a/Src/TouchScreen.cpp b/Src/TouchScreen.cpp
index 3bfcd61d..c1d410fb 100644
--- a/Src/TouchScreen.cpp
+++ b/Src/TouchScreen.cpp
@@ -36,8 +36,8 @@ static int TouchScreenDelay;
// Note: Touchscreen routines use InputBuffer for data into the
// touchscreen and OutputBuffer as data from the touchscreen.
-static RingBuffer InputBuffer;
-static RingBuffer OutputBuffer;
+static RingBuffer InputBuffer(1024);
+static RingBuffer OutputBuffer(1024);
/*--------------------------------------------------------------------------*/
From a6573cd506e103909db2b9335469eececfe30397 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Mon, 8 Jul 2024 21:46:40 +0100
Subject: [PATCH 005/101] Fixed some compiler warnings
---
Src/Disc1770.cpp | 14 ++++++++++----
Src/Disc8271.cpp | 4 ++--
Src/DiscEdit.cpp | 12 ++++++------
Src/Ide.cpp | 25 +++++++++++++++----------
4 files changed, 33 insertions(+), 22 deletions(-)
diff --git a/Src/Disc1770.cpp b/Src/Disc1770.cpp
index 1df645c4..28e857fc 100644
--- a/Src/Disc1770.cpp
+++ b/Src/Disc1770.cpp
@@ -568,10 +568,16 @@ void Poll1770(int NCycles) {
// If reading multiple sectors, and ByteCount== :-
// 256..2: read + DRQ (255x)
// 1: read + DRQ + rotate disc + go back to 256
- if (ByteCount > 0 && !feof(CurrentDisc)) {
- Data = fgetc(CurrentDisc);
- Status |= WD1770_STATUS_DATA_REQUEST;
- NMIStatus |= 1 << nmi_floppy;
+ if (ByteCount > 0 && !feof(CurrentDisc))
+ {
+ int Value = fgetc(CurrentDisc);
+
+ if (Value != EOF)
+ {
+ Data = (unsigned char)Value;
+ Status |= WD1770_STATUS_DATA_REQUEST;
+ NMIStatus |= 1 << nmi_floppy;
+ }
}
if (ByteCount == 0 || (ByteCount == 1 && MultiSect)) {
diff --git a/Src/Disc8271.cpp b/Src/Disc8271.cpp
index f43ab4c0..d5d95d99 100644
--- a/Src/Disc8271.cpp
+++ b/Src/Disc8271.cpp
@@ -2281,11 +2281,11 @@ static bool DriveHeadMotorUpdate()
if (FDCState.DriveHeadPosition[Drive] < FDCState.FSDPhysicalTrack[Drive])
{
- FDCState.DriveHeadPosition[Drive] += Tracks;
+ FDCState.DriveHeadPosition[Drive] = (unsigned char)(FDCState.DriveHeadPosition[Drive] + Tracks);
}
else
{
- FDCState.DriveHeadPosition[Drive] -= Tracks;
+ FDCState.DriveHeadPosition[Drive] = (unsigned char)(FDCState.DriveHeadPosition[Drive] - Tracks);
}
return true;
diff --git a/Src/DiscEdit.cpp b/Src/DiscEdit.cpp
index c84a7394..bcd44b60 100644
--- a/Src/DiscEdit.cpp
+++ b/Src/DiscEdit.cpp
@@ -12,8 +12,8 @@ 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 this program; if not, write to the Free
+You should have received a copy of the GNU General Public
+License along with this program; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
****************************************************************/
@@ -153,7 +153,7 @@ bool dfs_get_catalogue(const char *szDiscFile,
dfsCat->numFiles = buffer[DFS_SECTOR_SIZE + 5] / 8;
dfsCat->numSectors = ((buffer[DFS_SECTOR_SIZE + 6] & 3) << 8) + buffer[DFS_SECTOR_SIZE + 7];
dfsCat->bootOpts = (buffer[DFS_SECTOR_SIZE + 6] >> 4) & 3;
-
+
// Read first 31 files
dfs_get_files_from_cat(buffer, buffer + DFS_SECTOR_SIZE, dfsCat->numFiles, dfsCat->fileAttrs);
@@ -371,7 +371,7 @@ bool dfs_import_file(const char *szDiscFile,
}
// Build file names
- char filename[_MAX_PATH];
+ char filename[MAX_PATH];
strcpy(filename, szImportFolder);
strcat(filename, "/");
@@ -622,13 +622,13 @@ bool dfs_import_file(const char *szDiscFile,
// Update catalogue sectors
n = (dfsCat->numFiles > 31) ? 31 : dfsCat->numFiles;
- buffer[DFS_SECTOR_SIZE + 5] = n * 8;
+ buffer[DFS_SECTOR_SIZE + 5] = (unsigned char)(n * 8);
dfs_write_files_to_cat(buffer, buffer + DFS_SECTOR_SIZE, n, attrs);
if (dfsCat->watford62)
{
n = (dfsCat->numFiles > 31) ? dfsCat->numFiles - 31 : 0;
- buffer[DFS_SECTOR_SIZE * 3 + 5] = n * 8;
+ buffer[DFS_SECTOR_SIZE * 3 + 5] = (unsigned char)(n * 8);
dfs_write_files_to_cat(buffer + DFS_SECTOR_SIZE * 2, buffer + DFS_SECTOR_SIZE * 3,
n, &attrs[31]);
}
diff --git a/Src/Ide.cpp b/Src/Ide.cpp
index 8a649ea2..fe8d1d3f 100644
--- a/Src/Ide.cpp
+++ b/Src/Ide.cpp
@@ -131,7 +131,7 @@ void IDEWrite(int Address, unsigned char Value)
unsigned char IDERead(int Address)
{
- unsigned char data = 0xff;
+ unsigned char Data = 0xff;
switch (Address)
{
@@ -152,31 +152,36 @@ unsigned char IDERead(int Address)
// If in data read cycle, read data byte from file
if (IDEData > 0)
{
- data = fgetc(IDEDisc[IDEDrive]);
- IDEData--;
+ int Value = fgetc(IDEDisc[IDEDrive]);
- // If read all data, reset Data Ready
- if (IDEData == 0)
+ if (Value != EOF)
{
- IDEStatus &= ~0x08;
+ Data = (unsigned char)Value;
+ IDEData--;
+
+ // If read all data, reset Data Ready
+ if (IDEData == 0)
+ {
+ IDEStatus &= ~0x08;
+ }
}
}
break;
case 0x01: // Error
- data = IDEError;
+ Data = IDEError;
break;
case 0x07: // Status
- data = IDEStatus;
+ Data = IDEStatus;
break;
default: // Other registers
- data = IDERegs[Address];
+ Data = IDERegs[Address];
break;
}
- return data;
+ return Data;
}
void IDEClose()
From e87b30d549a276c7b0f2ea689fe0079e829431fb Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Tue, 9 Jul 2024 08:52:56 +0100
Subject: [PATCH 006/101] Disable compiler warnings from zlib files
---
Src/BeebEm.vcxproj | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/Src/BeebEm.vcxproj b/Src/BeebEm.vcxproj
index bafd1b45..2a0a8e51 100644
--- a/Src/BeebEm.vcxproj
+++ b/Src/BeebEm.vcxproj
@@ -263,10 +263,10 @@
4131
- 4131
- 4131
- 4131
- 4131
+ 4131;4244;4127
+ 4131;4244;4127
+ 4131;4244;4127
+ 4131;4244;4127
4131
@@ -311,10 +311,10 @@
4131
- 4131
- 4131
- 4131
- 4131
+ 4131;4244
+ 4131;4244
+ 4131;4244
+ 4131;4244
4131
From d805e6d3194334ee54a04a89db2fece1dece72e2 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Tue, 9 Jul 2024 20:13:11 +0100
Subject: [PATCH 007/101] Updated help documentation for serial port emulation
---
Help/serial.html | 59 ++++++++++++++++++++++++++++--------------------
1 file changed, 34 insertions(+), 25 deletions(-)
diff --git a/Help/serial.html b/Help/serial.html
index 8de1a651..ec395e4e 100644
--- a/Help/serial.html
+++ b/Help/serial.html
@@ -60,14 +60,41 @@ Serial Port
+ Serial Port
+
+
+ When the Serial Port option is selected, BeebEm
+ will use one of the host PC's serial ports. Enter the port name, e.g.,
+ COM1 into the Port field.
+
+
+ Microvitec Touchtech 501
+
+
+ When the Microvitec Touch Screen option is
+ selected, together with the Options → Analogue
+ Mousestick option, mouse input in the BeebEm window is translated
+ into touch screen input. Software for the Microvitec Touchtech 501
+ can be downloaded from
+ Paul
+ Vernon's website .
+
+
Serial over IP
- You can use the "tcpser" package, which emulates a modem. Select
- 127.0.0.1 and 25232 as the IP Address and Port . Download a prebuilt Windows binary of
- tcpser.zip . The tcpser
- source code is available
+ When the IP option is selected, BeebEm will
+ make a TCP connection to the specified IP Address .
+ and Port . This could be the address of a host
+ to connect to over the internet, or the "tcpser" package, which emulates
+ a modem and handles the connection to a remote system.
+
+
+
+ To use tcpser, select 127.0.0.1 and 25232 as the IP
+ Address and Port . Download a prebuilt
+ Windows binary of tcpser.zip .
+ The tcpser source code is available
here .
@@ -92,8 +119,8 @@ Serial over IP
Add the Commstar.rom to your ROM configuration (see
ROM Software ) and start up BeebEm. In the RS423 dialog box, select IP ,
- IP Address "127.0.0.1", and Port "25232". Click OK to
+ IP Address 127.0.0.1, and Port 25232. Click OK to
close the dialog box then select RS432 On/Off
from the Comms menu. Type
*COMMSTAR to start CommStar. In Commstar:
@@ -114,12 +141,6 @@ Serial over IP
server using ATDishar.com:9999 .
-
- To make a direct connection to a server, select IP
- and put the server's IP address and port into the RS423 dialog box.
-
-
The IP232 Raw Comms option controls special
processing of character 255. When enabled, no special handling is
@@ -147,18 +168,6 @@
Serial over IP
realistic experience when talking at 1200 baud to a Viewdata host!
Transmitted data is just sent out as fast as it will go.
-
- Microvitec Touchtech 501
-
-
- When the Microvitec Touch Screen option is
- selected, together with the Options → Analogue
- Mousestick option, mouse input in the BeebEm window is translated
- into touch screen input. Software for the Microvitec Touchtech 501
- can be downloaded from
- Paul
- Vernon's website .
-
From 98ce22d93ae882f9cf41f509a0a37ed560b86ffe Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Wed, 10 Jul 2024 23:53:55 +0100
Subject: [PATCH 008/101] Fixed TubeType preferences setting
---
Src/BeebWinPrefs.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Src/BeebWinPrefs.cpp b/Src/BeebWinPrefs.cpp
index 36c915f4..f345128d 100644
--- a/Src/BeebWinPrefs.cpp
+++ b/Src/BeebWinPrefs.cpp
@@ -1630,7 +1630,7 @@ void BeebWin::SavePreferences(bool saveAll)
m_Preferences.SetBinaryValue(CFG_KEYBOARD_LINKS, &KeyboardLinks, sizeof(KeyboardLinks));
// Second processors
- m_Preferences.SetDecimalValue(CFG_TUBE_TYPE, (int)TubeType);
+ m_Preferences.SetStringValue(CFG_TUBE_TYPE, TubeDeviceStr[(int)TubeType]);
m_Preferences.EraseValue(CFG_TUBE_ENABLED_OLD);
m_Preferences.EraseValue(CFG_TUBE_ACORN_Z80_OLD);
m_Preferences.EraseValue(CFG_TUBE_TORCH_Z80_OLD);
From f6b403e8b3269f9bc6024751374fdef85e4c522c Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Thu, 11 Jul 2024 01:51:40 +0100
Subject: [PATCH 009/101] Fixed printer output to clipboard
---
Src/BeebWin.cpp | 1 +
Src/BeebWinIo.cpp | 32 ++++++++++++++++++++++++++------
Src/UserVia.cpp | 2 +-
3 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index 7cf21faf..39a6e0c9 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -2552,6 +2552,7 @@ LRESULT BeebWin::WndProc(UINT nMessage, WPARAM wParam, LPARAM lParam)
}
else if (wParam == TIMER_PRINTER)
{
+ KillTimer(m_hWnd, TIMER_PRINTER);
CopyPrinterBufferToClipboard();
}
break;
diff --git a/Src/BeebWinIo.cpp b/Src/BeebWinIo.cpp
index 31336155..ba70324d 100644
--- a/Src/BeebWinIo.cpp
+++ b/Src/BeebWinIo.cpp
@@ -735,7 +735,9 @@ void BeebWin::SetPrinterPort(PrinterPortType PrinterPort)
// If printer is enabled then need to
// disable it before changing file
if (PrinterEnabled)
+ {
TogglePrinter();
+ }
// Add file name to menu
std::string MenuString = "File: ";
@@ -753,7 +755,9 @@ void BeebWin::SetPrinterPort(PrinterPortType PrinterPort)
else if (PrinterPort == PrinterPortType::Clipboard)
{
if (PrinterEnabled)
+ {
TogglePrinter();
+ }
m_PrinterPort = PrinterPort;
@@ -766,7 +770,9 @@ void BeebWin::SetPrinterPort(PrinterPortType PrinterPort)
// If printer is enabled then need to
// disable it before changing file
if (PrinterEnabled)
+ {
TogglePrinter();
+ }
m_PrinterPort = PrinterPort;
@@ -856,14 +862,15 @@ bool BeebWin::TogglePrinter()
{
bool Success = true;
- m_PrinterBuffer.clear();
-
if (PrinterEnabled)
{
PrinterDisable();
}
else
{
+ m_PrinterBuffer.clear();
+ KillTimer(m_hWnd, TIMER_PRINTER);
+
if (m_PrinterPort == PrinterPortType::File)
{
if (m_PrinterFileName.empty())
@@ -1535,7 +1542,9 @@ void BeebWin::SaveUserKeyMap()
void BeebWin::OnCopy()
{
if (PrinterEnabled)
+ {
TogglePrinter();
+ }
m_PrinterPort = PrinterPortType::Clipboard;
@@ -1614,8 +1623,15 @@ void BeebWin::PrintChar(unsigned char Value)
void BeebWin::CopyPrinterBufferToClipboard()
{
+ if (m_PrinterBuffer.size() == 0)
+ {
+ return;
+ }
+
if (!OpenClipboard(m_hWnd))
+ {
return;
+ }
EmptyClipboard();
@@ -1628,11 +1644,15 @@ void BeebWin::CopyPrinterBufferToClipboard()
}
unsigned char* pData = (unsigned char*)GlobalLock(hClipboardData);
- memcpy(pData, &m_PrinterBuffer[0], m_PrinterBuffer.size());
- pData[m_PrinterBuffer.size()] = '\0';
- GlobalUnlock(hClipboardData);
- SetClipboardData(CF_TEXT, hClipboardData);
+ if (pData != nullptr)
+ {
+ memcpy(pData, &m_PrinterBuffer[0], m_PrinterBuffer.size());
+ pData[m_PrinterBuffer.size()] = '\0';
+ GlobalUnlock(hClipboardData);
+
+ SetClipboardData(CF_TEXT, hClipboardData);
+ }
CloseClipboard();
}
diff --git a/Src/UserVia.cpp b/Src/UserVia.cpp
index 22ce2e2a..5f4acea6 100644
--- a/Src/UserVia.cpp
+++ b/Src/UserVia.cpp
@@ -611,7 +611,7 @@ bool PrinterEnable(const char *FileName)
{
ClosePrinterOutputFile();
- if (FileName != nullptr)
+ if (FileName == nullptr)
{
PrinterEnabled = true;
SetTrigger(PRINTER_TRIGGER, PrinterTrigger);
From d15f6183f080d4eba6dcb16780dae5354ec50472 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Fri, 12 Jul 2024 20:12:21 +0100
Subject: [PATCH 010/101] Add some error handling
---
Src/BeebWin.cpp | 31 ++++++++++++++++++++++++++-----
Src/BeebWin.h | 2 +-
2 files changed, 27 insertions(+), 6 deletions(-)
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index 39a6e0c9..53cf826d 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -431,10 +431,16 @@ bool BeebWin::Initialise()
INITCOMMONCONTROLSEX cc;
cc.dwSize = sizeof(cc);
cc.dwICC = ICC_LISTVIEW_CLASSES;
- InitCommonControlsEx(&cc);
+ if (!InitCommonControlsEx(&cc))
+ {
+ return false;
+ }
GdiplusStartupInput gdiplusStartupInput;
- GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
+ if (GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL) != Status::Ok)
+ {
+ return false;
+ }
WSADATA WsaData;
@@ -444,8 +450,16 @@ bool BeebWin::Initialise()
return false;
}
- InitClass();
- CreateBeebWindow();
+ if (!InitClass())
+ {
+ return false;
+ }
+
+ if (!CreateBeebWindow())
+ {
+ return false;
+ }
+
CreateBitmap();
m_hMenu = GetMenu(m_hWnd);
@@ -1171,7 +1185,7 @@ bool BeebWin::InitClass()
/****************************************************************************/
-void BeebWin::CreateBeebWindow()
+bool BeebWin::CreateBeebWindow()
{
int x = m_XWinPos;
int y = m_YWinPos;
@@ -1216,12 +1230,19 @@ void BeebWin::CreateBeebWindow()
this
);
+ if (m_hWnd == nullptr)
+ {
+ return false;
+ }
+
DisableRoundedCorners(m_hWnd);
ShowWindow(m_hWnd, nCmdShow); // Show the window
UpdateWindow(m_hWnd); // Sends WM_PAINT message
SetWindowAttributes(false);
+
+ return true;
}
/****************************************************************************/
diff --git a/Src/BeebWin.h b/Src/BeebWin.h
index 7b8ab585..c47c5240 100644
--- a/Src/BeebWin.h
+++ b/Src/BeebWin.h
@@ -402,7 +402,7 @@ class BeebWin
bool InitClass();
void UpdateOptionsMenu();
- void CreateBeebWindow(void);
+ bool CreateBeebWindow();
void DisableRoundedCorners(HWND hWnd);
void FlashWindow();
void CreateBitmap(void);
From 131905bc1c6c3a1b3baccca2463223d223db1b83 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 13 Jul 2024 19:11:01 +0100
Subject: [PATCH 011/101] Removed unnecessary variable to fix compiler warning
---
Src/IP232.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/Src/IP232.cpp b/Src/IP232.cpp
index ecd825fc..d70a1dc1 100644
--- a/Src/IP232.cpp
+++ b/Src/IP232.cpp
@@ -208,8 +208,7 @@ void IP232Close()
if (Result == SOCKET_ERROR)
{
- int Error = WSAGetLastError();
- DebugTrace("closesocket() returned error %d\n", Error);
+ DebugTrace("closesocket() returned error %d\n", WSAGetLastError());
}
EthernetSocket = INVALID_SOCKET;
From ef92f754ef1ecfa4aa608949844f3f0782796718 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 13 Jul 2024 19:12:14 +0100
Subject: [PATCH 012/101] Fixed emulator slow down when debugger window is open
---
Src/Debug.cpp | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/Src/Debug.cpp b/Src/Debug.cpp
index ed6289c5..20fccc44 100644
--- a/Src/Debug.cpp
+++ b/Src/Debug.cpp
@@ -1615,8 +1615,10 @@ bool DebugDisassembler(int addr,
// Check breakpoints
if (BPSOn && DebugSource != DebugType::Breakpoint)
{
- for (const Breakpoint& bp : Breakpoints)
+ for (size_t i = 0; i < Breakpoints.size(); i++)
{
+ const Breakpoint& bp = Breakpoints[i];
+
if (bp.end == -1)
{
if (addr == bp.start)
@@ -1753,8 +1755,8 @@ bool DebugDisassembler(int addr,
DebugDisplayInfo(str);
- // If host debug is enable then only count host instructions
- // and display all parasite inst (otherwise we lose them).
+ // If host debug is enabled then only count host instructions
+ // and display all parasite instructions (otherwise we lose them).
if ((DebugHost && host) || !DebugHost)
{
if (InstCount > 0)
From c18ed4018b23ca9fa47867d5dbf4b4dcbffe3139 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 13 Jul 2024 19:18:01 +0100
Subject: [PATCH 013/101] Renamed variables
---
Src/BeebEm.rc | 2 +-
Src/BeebWin.cpp | 24 +++++++++++++-----------
Src/BeebWin.h | 4 ++--
Src/BeebWinDx.cpp | 18 ++++++++++++------
Src/Resource.h | 2 +-
5 files changed, 29 insertions(+), 21 deletions(-)
diff --git a/Src/BeebEm.rc b/Src/BeebEm.rc
index 4dfd6bf9..ca8af2e3 100644
--- a/Src/BeebEm.rc
+++ b/Src/BeebEm.rc
@@ -257,7 +257,7 @@ BEGIN
MENUITEM "5 FPS", IDM_5FPS
MENUITEM "1 FPS", IDM_1FPS
MENUITEM SEPARATOR
- MENUITEM "&Pause Emulation", IDM_EMUPAUSED
+ MENUITEM "&Pause Emulation", IDM_PAUSE
END
POPUP "&Sound"
BEGIN
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index 53cf826d..48f00d2f 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -165,7 +165,7 @@ BeebWin::BeebWin()
// Pause / freeze emulation
m_StartPaused = false;
- m_EmuPaused = false;
+ m_Paused = false;
m_WasPaused = false;
m_FreezeWhenInactive = false;
m_Frozen = false;
@@ -1405,8 +1405,8 @@ void BeebWin::InitMenu(void)
// Speed
UpdateSpeedMenu();
- // Check menu based on m_EmuPaused to take into account -StartPaused arg
- CheckMenuItem(IDM_EMUPAUSED, m_EmuPaused);
+ // Check menu based on m_Paused to take into account -StartPaused arg
+ CheckMenuItem(IDM_PAUSE, m_Paused);
// Sound
UpdateSoundStreamerMenu();
@@ -2246,7 +2246,7 @@ LRESULT BeebWin::WndProc(UINT nMessage, WPARAM wParam, LPARAM lParam)
}
else if (wParam == VK_F5 && AltPressed) // Alt+F5
{
- HandleCommand(IDM_EMUPAUSED);
+ HandleCommand(IDM_PAUSE);
break;
}
@@ -4225,7 +4225,7 @@ void BeebWin::HandleCommand(UINT MenuID)
TranslateTiming();
break;
- case IDM_EMUPAUSED:
+ case IDM_PAUSE:
TogglePause();
break;
@@ -4928,15 +4928,17 @@ bool BeebWin::IsFrozen() const
void BeebWin::TogglePause()
{
- m_EmuPaused = !m_EmuPaused;
- CheckMenuItem(IDM_EMUPAUSED, m_EmuPaused);
- if (m_ShowSpeedAndFPS && m_EmuPaused)
+ m_Paused = !m_Paused;
+
+ CheckMenuItem(IDM_PAUSE, m_Paused);
+
+ if (m_ShowSpeedAndFPS && m_Paused)
{
sprintf(m_szTitle, "%s Paused", WindowTitle);
SetWindowText(m_hWnd, m_szTitle);
}
- if (m_EmuPaused)
+ if (m_Paused)
{
KillTimer(m_hWnd, TIMER_KEYBOARD);
KillTimer(m_hWnd, TIMER_AUTOBOOT_DELAY);
@@ -4957,7 +4959,7 @@ void BeebWin::TogglePause()
bool BeebWin::IsPaused() const
{
- return m_EmuPaused;
+ return m_Paused;
}
void BeebWin::SetFreezeWhenInactive(bool State)
@@ -5107,7 +5109,7 @@ void BeebWin::ParseCommandLine()
else if (_stricmp(__argv[i], "-StartPaused") == 0)
{
m_StartPaused = true;
- m_EmuPaused = true;
+ m_Paused = true;
}
else if (_stricmp(__argv[i], "-FullScreen") == 0)
{
diff --git a/Src/BeebWin.h b/Src/BeebWin.h
index c47c5240..ca5b18fb 100644
--- a/Src/BeebWin.h
+++ b/Src/BeebWin.h
@@ -333,7 +333,7 @@ class BeebWin
void DisplayTiming();
void UpdateWindowTitle();
bool IsWindowMinimized() const;
- void DisplayClientAreaText(HDC hdc);
+ void DisplayClientAreaText(HDC hDC);
void DisplayFDCBoardInfo(HDC hDC, int x, int y);
void ScaleJoystick(unsigned int x, unsigned int y);
void SetMousestickButton(int index, bool button);
@@ -648,7 +648,7 @@ class BeebWin
// Pause / freeze emulation
bool m_StartPaused;
- bool m_EmuPaused;
+ bool m_Paused;
bool m_WasPaused;
bool m_FreezeWhenInactive;
bool m_Frozen;
diff --git a/Src/BeebWinDx.cpp b/Src/BeebWinDx.cpp
index 3d2b72ab..1cd90b21 100644
--- a/Src/BeebWinDx.cpp
+++ b/Src/BeebWinDx.cpp
@@ -1002,24 +1002,30 @@ bool BeebWin::IsWindowMinimized() const
/****************************************************************************/
-void BeebWin::DisplayClientAreaText(HDC hdc)
+void BeebWin::DisplayClientAreaText(HDC hDC)
{
int TextStart=240;
if (TeletextEnabled)
TextStart=(480/TeletextStyle)-((TeletextStyle==2)?12:0);
- DisplayFDCBoardInfo(hdc, 0, TextStart);
+ DisplayFDCBoardInfo(hDC, 0, TextStart);
if (m_ShowSpeedAndFPS && m_FullScreen)
{
char fps[50];
- if (!m_EmuPaused)
+
+ if (!m_Paused)
+ {
sprintf(fps, "%2.2f %2d", m_RelativeSpeed, (int)m_FramesPerSecond);
+ }
else
+ {
sprintf(fps, "Paused");
- SetBkMode(hdc,TRANSPARENT);
- SetTextColor(hdc,0x808080);
- TextOut(hdc, TeletextEnabled ? 490 : 580, TextStart, fps, (int)strlen(fps));
+ }
+
+ SetBkMode(hDC, TRANSPARENT);
+ SetTextColor(hDC, 0x808080);
+ TextOut(hDC, TeletextEnabled ? 490 : 580, TextStart, fps, (int)strlen(fps));
}
}
diff --git a/Src/Resource.h b/Src/Resource.h
index 08a2c4cc..9abc854c 100644
--- a/Src/Resource.h
+++ b/Src/Resource.h
@@ -445,7 +445,7 @@
#define IDM_XAUDIO2 40285
#define IDM_DIRECTSOUND 40286
#define IDM_IDE_HARD_DRIVE 40287
-#define IDM_EMUPAUSED 40296
+#define IDM_PAUSE 40296
#define IDM_VIEW_DD_SCREENRES 40297
#define IDM_VIEW_DD_640X480 40298
#define IDM_VIEW_DD_720X576 40299
From 3440eeede75a1bb951c139f3f724df0ac05586da Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 13 Jul 2024 19:29:39 +0100
Subject: [PATCH 014/101] Simplified code
---
Src/Debug.cpp | 48 +++++++++++++++++++++++++-----------------------
1 file changed, 25 insertions(+), 23 deletions(-)
diff --git a/Src/Debug.cpp b/Src/Debug.cpp
index 20fccc44..955448a8 100644
--- a/Src/Debug.cpp
+++ b/Src/Debug.cpp
@@ -1493,75 +1493,77 @@ void DebugDisplayTraceV(DebugType type, bool host, const char *format, va_list a
static void DebugUpdateWatches(bool all)
{
int value = 0;
- char str[200];
for (size_t i = 0; i < Watches.size(); ++i)
{
- switch (Watches[i].type)
+ Watch& watch = Watches[i];
+
+ switch (watch.type)
{
case 'b':
- value = DebugReadMem(Watches[i].start, Watches[i].host);
+ value = DebugReadMem(watch.start, watch.host);
break;
case 'w':
if (WatchBigEndian)
{
- value = (DebugReadMem(Watches[i].start, Watches[i].host) << 8) +
- DebugReadMem(Watches[i].start + 1, Watches[i].host);
+ value = (DebugReadMem(watch.start, watch.host) << 8) +
+ DebugReadMem(watch.start + 1, watch.host);
}
else
{
- value = (DebugReadMem(Watches[i].start + 1, Watches[i].host) << 8) +
- DebugReadMem(Watches[i].start, Watches[i].host);
+ value = (DebugReadMem(watch.start + 1, watch.host) << 8) +
+ DebugReadMem(watch.start, watch.host);
}
break;
case 'd':
if (WatchBigEndian)
{
- value = (DebugReadMem(Watches[i].start, Watches[i].host) << 24) +
- (DebugReadMem(Watches[i].start + 1, Watches[i].host) << 16) +
- (DebugReadMem(Watches[i].start + 2, Watches[i].host) << 8) +
- DebugReadMem(Watches[i].start + 3, Watches[i].host);
+ value = (DebugReadMem(watch.start, watch.host) << 24) +
+ (DebugReadMem(watch.start + 1, watch.host) << 16) +
+ (DebugReadMem(watch.start + 2, watch.host) << 8) +
+ DebugReadMem(watch.start + 3, watch.host);
}
else
{
- value = (DebugReadMem(Watches[i].start + 3, Watches[i].host) << 24) +
- (DebugReadMem(Watches[i].start + 2, Watches[i].host) << 16) +
- (DebugReadMem(Watches[i].start + 1, Watches[i].host) << 8) +
- DebugReadMem(Watches[i].start, Watches[i].host);
+ value = (DebugReadMem(watch.start + 3, watch.host) << 24) +
+ (DebugReadMem(watch.start + 2, watch.host) << 16) +
+ (DebugReadMem(watch.start + 1, watch.host) << 8) +
+ DebugReadMem(watch.start, watch.host);
}
break;
}
- if (all || value != Watches[i].value)
+ if (all || value != watch.value)
{
- Watches[i].value = value;
+ watch.value = value;
- SendMessage(hwndW, LB_DELETESTRING, i, 0);
+ char str[200];
if (WatchDecimal)
{
- sprintf(str, "%s%04X %s=%d (%c)", (Watches[i].host ? "" : "p"), Watches[i].start, Watches[i].name.c_str(), Watches[i].value, Watches[i].type);
+ sprintf(str, "%s%04X %s=%d (%c)", (watch.host ? "" : "p"), watch.start, watch.name.c_str(), watch.value, watch.type);
}
else
{
- switch (Watches[i].type)
+ switch (watch.type)
{
case 'b':
- sprintf(str, "%s%04X %s=$%02X", Watches[i].host ? "" : "p", Watches[i].start, Watches[i].name.c_str(), Watches[i].value);
+ sprintf(str, "%s%04X %s=$%02X", watch.host ? "" : "p", watch.start, watch.name.c_str(), watch.value);
break;
case 'w':
- sprintf(str, "%s%04X %s=$%04X", Watches[i].host ? "" : "p", Watches[i].start, Watches[i].name.c_str(), Watches[i].value);
+ sprintf(str, "%s%04X %s=$%04X", watch.host ? "" : "p", watch.start, watch.name.c_str(), watch.value);
break;
case 'd':
- sprintf(str, "%s%04X %s=$%08X", Watches[i].host ? "" : "p", Watches[i].start, Watches[i].name.c_str(), Watches[i].value);
+ sprintf(str, "%s%04X %s=$%08X", watch.host ? "" : "p", watch.start, watch.name.c_str(), watch.value);
break;
}
}
+ SendMessage(hwndW, LB_DELETESTRING, i, 0);
SendMessage(hwndW, LB_INSERTSTRING, i, (LPARAM)str);
}
}
From e82b5db78e3e4127a2c164c2dbd2bdf742728ea2 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 13 Jul 2024 19:43:32 +0100
Subject: [PATCH 015/101] Renamed functions
---
Src/6502core.cpp | 7 ++++---
Src/6502core.h | 10 +++++-----
Src/BeebWin.cpp | 8 ++++----
Src/Tube.cpp | 6 ++++--
Src/Tube.h | 11 ++++++-----
5 files changed, 23 insertions(+), 19 deletions(-)
diff --git a/Src/6502core.cpp b/Src/6502core.cpp
index f6ac52a2..efd495bb 100644
--- a/Src/6502core.cpp
+++ b/Src/6502core.cpp
@@ -1307,9 +1307,10 @@ INLINE static int ZeroPgYAddrModeHandler_Address()
// Initialise 6502core
-void Init6502core()
+void Init6502Core()
{
- switch (MachineType) {
+ switch (MachineType)
+ {
case Model::Master128:
case Model::MasterET:
CPUType = CPU::CPU65C12;
@@ -1544,7 +1545,7 @@ void Exec6502Instruction()
InstructionCount[CurrentInstruction]++;
// Advance VIAs to point where mem read happens
- ViaCycles=0;
+ ViaCycles = 0;
AdvanceCyclesForMemRead();
switch (CurrentInstruction)
diff --git a/Src/6502core.h b/Src/6502core.h
index 070677b5..935ff6ba 100644
--- a/Src/6502core.h
+++ b/Src/6502core.h
@@ -76,12 +76,12 @@ extern int CyclesToInt;
#define AdjustTrigger(var) if (var!=CycleCountTMax) var-=CycleCountWrap;
/*-------------------------------------------------------------------------*/
-/* Initialise 6502core */
-void Init6502core(void);
-/*-------------------------------------------------------------------------*/
-/* Execute one 6502 instruction, move program counter on */
-void Exec6502Instruction(void);
+// Initialise 6502core
+void Init6502Core();
+
+// Execute one 6502 instruction, move program counter on.
+void Exec6502Instruction();
void DoNMI(void);
void DoInterrupt(void);
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index 48f00d2f..dc09395b 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -774,13 +774,13 @@ void BeebWin::ResetBeebSystem(Model NewModelType, bool LoadRoms)
}
BeebMemInit(LoadRoms, m_ShiftBooted);
- Init6502core();
+ Init6502Core();
RTCInit();
if (TubeType == TubeDevice::Acorn65C02)
{
- Init65C02core();
+ Init65C02Core();
}
else if (TubeType == TubeDevice::Master512CoPro)
{
@@ -922,11 +922,11 @@ void BeebWin::ResetBeebSystem(Model NewModelType, bool LoadRoms)
void BeebWin::Break()
{
// Must do a reset!
- Init6502core();
+ Init6502Core();
if (TubeType == TubeDevice::Acorn65C02)
{
- Init65C02core();
+ Init65C02Core();
}
else if (TubeType == TubeDevice::Master512CoPro)
{
diff --git a/Src/Tube.cpp b/Src/Tube.cpp
index e899c81d..4acb528e 100644
--- a/Src/Tube.cpp
+++ b/Src/Tube.cpp
@@ -1586,8 +1586,10 @@ void ResetTube(void)
TubeNMIStatus=0;
}
-/* Initialise 6502core */
-void Init65C02core(void) {
+// Initialise 65C02Core
+
+void Init65C02Core()
+{
Reset65C02();
R1Status=0;
ResetTube();
diff --git a/Src/Tube.h b/Src/Tube.h
index 2726e0ee..99720458 100644
--- a/Src/Tube.h
+++ b/Src/Tube.h
@@ -57,12 +57,13 @@ enum TubeNMI {
};
/*-------------------------------------------------------------------------*/
-/* Initialise 6502core */
-void Init65C02core(void);
-/*-------------------------------------------------------------------------*/
-/* Execute one 6502 instruction, move program counter on */
-void Exec65C02Instruction(void);
+// Initialise 6502core
+
+void Init65C02Core();
+
+// Execute one 6502 instruction, move program counter on.
+void Exec65C02Instruction();
void WrapTubeCycles(void);
void SyncTubeProcessor(void);
From c1a66b31f666208a9f7baed0cb1cb8f180d3b35f Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Tue, 16 Jul 2024 01:11:32 +0100
Subject: [PATCH 016/101] Fixed minor consistency issues in OS 1.2 memory map
---
UserData/BeebFile/BBC/OS12.map | 66 +++++++++++++++++-----------------
1 file changed, 33 insertions(+), 33 deletions(-)
diff --git a/UserData/BeebFile/BBC/OS12.map b/UserData/BeebFile/BBC/OS12.map
index fa91679a..70a9c293 100644
--- a/UserData/BeebFile/BBC/OS12.map
+++ b/UserData/BeebFile/BBC/OS12.map
@@ -116,21 +116,21 @@ C407 C408 Mask table for 2 colour modes
C409 C40C Mask table for 4 colour modes
C40D C414 Mask table for 4 colour modes font flag mask table
C414 C41B Number of colours per mode look up table
-C41C C425 Gcol plot options processing look up table
+C41C C425 GCOL plot options processing look up table
C424 C425 2 colour modes parameter look up table
C426 C429 4 colour modes parameter look up table
C42A C439 16 colour modes parameter look up table
C43A C441 Display mode pixels/byte-1 look up table
C440 C447 Screen display memory index look up table
C441 C444 Sound pitch offset by channel look up table
-C44B C44E Crtc set up parameters table 1
-C44F C453 Crtc set up parameters table 2
+C44B C44E CRTC set up parameters table 1
+C44F C453 CRTC set up parameters table 2
C447 C458 VDU section control numbers
-C459 C45D Msb of memory occupied by screen buffer
-C45E C462 Msb of first location occupied by screen buffer
+C459 C45D MSB of memory occupied by screen buffer
+C45E C462 MSB of first location occupied by screen buffer
C463 C465 Number of bytes per row
C466 C468 Row multipliaction table pointer to look up table
-C469 C46D Crtc cursor end register setting look up table
+C469 C46D CRTC cursor end register setting look up table
C46E C479 6845 registers 0-11 for modes 0-2
C47A C485 6845 registers 0-11 for mode 3
C486 C491 6845 registers 0-11 for modes 4-5
@@ -140,7 +140,7 @@ C4AA C4AD VDU rotine vector addresses
C4AE C4B1 VDU routine branch vector address lo
C4B2 C4B5 VDU routine branch vector address hi
C4B6 C4B9 Teletext character conversion table
-C4BA C4BF Soft character ram allocation
+C4BA C4BF Soft character RAM allocation
C4C0 C533 OSWRCH main routine, entry from E0C5, parameter parse
C534 C542 VDU 1 send next character to printer only
C545 C55C OSWRCH further parameter parse - deal with no params
@@ -185,7 +185,7 @@ C8F1 C937 VDU 23 - Define characters 9 parameters
C938 C93C VDU extension (jumps to VDUV)
C93F C98B VDU 23 - set CRTC parameter
C98C C991 VDU 25 plot entry point - jumps to VDU extension or PLOT routines
-C994 C9BB Adjust screen ram addresses (called by cursor routines)
+C994 C9BB Adjust screen RAM addresses (called by cursor routines)
C9BD C9FF VDU 26 set default windows 0 parameters
CA02 CA38 Set cursor position
CA39 CA7E VDU 24 define graphics window 8 parameters
@@ -242,8 +242,8 @@ D940 D974 Default vector table (loaded at 0x0200)
D976 D9CC MOS variables default settings
D9CD D9E6 Boot: System reset
D9E7 DA00 Boot: Clear RAM
-DA03 DA05 Boot: Set up system via
-DA08 DA25 Boot: Set addressable latch IC 32 for peripherals via PORT B
+DA03 DA05 Boot: Set up system VIA
+DA08 DA25 Boot: Set addressable latch IC 32 for peripherals VIA port B
DA26 DA68 Boot: Set up page 2
DA6B DABA Boot: Clear interrupt and enable registers of both VIAs
DABD DB0F Boot: Check sideways ROMs and make catalogue
@@ -259,7 +259,7 @@ DBE7 DC05 OSBYTE 142 enter language rom at 0x8000
DC08 DC08 Tube found - Enter Tube environment
DC0B DC1B OSRDRM
DC1C DC24 Main IRQ handler - calls IRQ1V or Main BRK handler if BRK flag set
-DC27 DC51 Main BRK handler - issues service call 6 to roms, calls BRKV
+DC27 DC51 Main BRK handler - issues service call 6 to ROMs, calls BRKV
DC54 DC92 Default BRK handler - BRKV points here by default
DC93 DD03 Default IRQ handler - IRQ1V points here by default
DD06 DD44 VIA interupt dispatch
@@ -274,7 +274,7 @@ DE8C DEBA OSBYTE 17 start conversion
DEBB DEC3 Set up timer for OSBYTE 129
DEC5 DEFE OSRDCH
E114 E17A Printer driver
-E17C E190 OSBYTE 156 update acia setting and ram copy
+E17C E190 OSBYTE 156 update ACIA setting and RAM copy
E191 E194 Handle user printer
E197 E1AA OSBYTE 123 warn printer driver going dormant
E1AD E1D0 Buffer handling
@@ -319,8 +319,8 @@ E6F9 E704 OSBYTE 13/14 disable/enable events
E706 E712 OSBYTE 16 select a/d channel
E713 E731 OSBYTE 129 read key within time limit
E732 E73E Check occupancy of input or free space of output buffer
-E741 E74E Check rs423 input buffer
-E74F E771 OSBYTE 128 read adc channel
+E741 E74E Check RS423 input buffer
+E74F E771 OSBYTE 128 read ADC channel
E772 E7EA Default BYTEV handler (OSBYTE)
E7EB E801 Default WORDV handler (OSWORD)
E803 E80A OSWORD 05 entry point
@@ -339,31 +339,31 @@ E8E8 E901 OSWORD 02 entry point
E902 E975 OSWORD 00 entry point
E976 E986 OSBYTE 05 entry point
E988 E98A OSBYTE 01/06 entry point
-E98C E993 OSBYTE 0c entry point
-E995 E996 OSBYTE 0b entry point
+E98C E993 OSBYTE 0C entry point
+E995 E996 OSBYTE 0B entry point
E997 E99B OSBYTE 03/04
-E99C E9AC OSBYTE a6-ff entry point
+E99C E9AC OSBYTE A6-FF entry point
E9AD E9B5 Serial baud rate look up table
E9B6 E9BE OSBYTE &13 entry point
E9C0 E9C7 OSBYTE 160 entry point
E9C8 E9D8 OSBYTE 18 entry point
E9D9 E9E9 OSBYTE &76 (118) set leds to keyboard status
E9EA E9F7 Turn on keyboard lights and test escape flag
-E9F8 E9FE Write a to system via register b
-E9FF EA0F OSBYTE 154 (&9a) set video ula
-EA10 EA1C OSBYTE &9b (155) write to pallette register
+E9F8 E9FE Write A to system VIA register B
+E9FF EA0F OSBYTE &9A (154) set video ULA
+EA10 EA1C OSBYTE &9B (155) write to pallette register
EA1D EA2E GSINIT string initialisation
EA2F EAD1 GSREAD string read routine
EAD2 EAD8 "/!BOOT\n"
-EAD9 EAE0 OSBYTE &f7 (247) intercept break
-EAE3 EAF3 OSBYTE &90 (144) *tv
+EAD9 EAE0 OSBYTE &F7 (247) intercept break
+EAE3 EAF3 OSBYTE &90 (144) *TV
EAF4 EAF8 OSBYTE &93 (147) write to FRED
EAF9 EAFD OSBYTE &95 (149) write to JIM
EAFE EB02 OSBYTE &97 (151) write to SHEILA
EB03 EDFA Sound routines
EDFB EE06 Pitch look up table 1
EE07 EE12 Pitch look up table 2
-EE13 EE17 Set current filing system rom/phrom
+EE13 EE17 Set current filing system ROM/PHROM
EE18 EE4F Get byte from data ROM
EE51 EE61 ROM service
EE62 EE6B PHROM service
@@ -388,9 +388,9 @@ F09B F0A4 Key translation table 7
F0A5 F0A7 Jump to EVENTV
F0A8 F0B2 OSBYTE 15 flush selected buffer class
F0B4 F0B8 OSBYTE 21 flush specific buffer
-F0B9 F0CB Issue *help to roms
+F0B9 F0CB Issue *help to ROMs
F0CC F0CD OSBYTE 122 keyboard scan from &10 (16)
-F0CF F134 OSBYTE 121 keyboard scan from value in x
+F0CF F134 OSBYTE 121 keyboard scan from value in X
F135 F13D OSBYTE 140/141 *TAPE/*ROM
F140 F157 Set cassette options
F159 F166 Reset FILEV,ARGSV,BGETV,BPUTV,GBPBV,FINDV,FSCV
@@ -422,13 +422,13 @@ F68B F6AB *EXEC
F6AC F72C CFS: Read a block
F72D F785 CFS: Pick up a header
F787 F796 CFS: Terminator found
-F797 F7AD CFS: Get character from file and do crc
-F7B0 F7EB CFS: Perform crc
+F797 F7AD CFS: Get character from file and do CRC
+F7B0 F7EB CFS: Perform CRC
F7EC F81F CFS: Save a block
F821 F874 CFS: Deal with rest of header
-F875 F878 CFS: Transfer byte to cfs and do crc
+F875 F878 CFS: Transfer byte to CFS and do CFC
F87B F880 CFS: Save checksum to tape reset buffer flag
-F882 F891 CFS: Save byte to buffer, transfer to cfs & reset flag
+F882 F891 CFS: Save byte to buffer, transfer to CFS & reset flag
F892 F8A8 CFS: Generate delays
F8A9 F933 CFS: Generate screen reports
F934 F967 CFS: Prompt 'RECORD then RETURN', wait for RETURN
@@ -439,10 +439,10 @@ F991 F993 CFS: Print a space
F995 F9B3 CFS: Confirm CFS not operating, nor escape flag set
F9B4 FA6F CFS: Load
FA72 FAE5 CFS: Compare filenames
-FAE8 FB19 CFS: Sound bell, reset acia, motor off
+FAE8 FB19 CFS: Sound bell, reset ACIA, motor off
FB1A FB25 Claim serial system for sequential access
FB27 FB48 Claim serial system for cassette etc.
-FB4A FB4E CFS: Set acia control register
+FB4A FB4E CFS: Set ACIA control register
FB50 FB7A CFS: Control cassette system
FB7C FB80 CFS: Clear checksum bytes
FB81 FB8E CFS: Copy sought filename routine
@@ -471,8 +471,8 @@ FE00 FEFF SHEILA - system hardware memory-mapped I/O
FF00 FF88 Extended vector entry points
-FF89 FFA6 Return address from rom indirection
-FFA7 FFA8 OSBYTE &9d fast BPUT
+FF89 FFA6 Return address from ROM indirection
+FFA7 FFA8 OSBYTE &9D fast BPUT
FFAA FFAD OSBYTE &92 read a byte from FRED
FFAE FFB1 OSBYTE &94 read a byte from JIM
FFB2 FFB5 OSBYTE &96 read a byte from SHEILA
From ecd71a1a6997c7453c754e6ec3514c82709fa154 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Tue, 30 Jul 2024 20:53:00 +0100
Subject: [PATCH 017/101] Replaced _MAX_PATH with MAX_PATH
---
Src/BeebMem.cpp | 6 ++---
Src/BeebMem.h | 6 ++---
Src/BeebWin.cpp | 35 +++++++++++++-------------
Src/BeebWin.h | 12 ++++-----
Src/BeebWinIo.cpp | 52 +++++++++++++++++++--------------------
Src/BeebWinSpeech.cpp | 2 +-
Src/DiscEdit.cpp | 2 +-
Src/ExportFileDialog.cpp | 2 +-
Src/RomConfigFile.cpp | 2 +-
Src/TapeControlDialog.cpp | 2 +-
Src/TeletextDialog.cpp | 4 +--
11 files changed, 63 insertions(+), 62 deletions(-)
diff --git a/Src/BeebMem.cpp b/Src/BeebMem.cpp
index a692a5be..ffc5b385 100644
--- a/Src/BeebMem.cpp
+++ b/Src/BeebMem.cpp
@@ -140,12 +140,12 @@ static bool Sh_CPUX, Sh_CPUE;
/* End of Master 128 Specific Stuff, note initilised anyway regardless of Model Type in use */
/* ROM file data */
-char RomPath[_MAX_PATH];
-char RomFile[_MAX_PATH];
+char RomPath[MAX_PATH];
+char RomFile[MAX_PATH];
RomConfigFile RomConfig;
// SCSI and IDE hard drive file location
-char HardDrivePath[_MAX_PATH]; // JGH
+char HardDrivePath[MAX_PATH]; // JGH
// FDD Extension board variables
int EFDCAddr; // 1770 FDC location
diff --git a/Src/BeebMem.h b/Src/BeebMem.h
index 6f141853..6333326b 100644
--- a/Src/BeebMem.h
+++ b/Src/BeebMem.h
@@ -87,10 +87,10 @@ extern bool Sh_Display;
/* End of Master 128 Specific Stuff, note initilised anyway regardless of Model Type in use */
extern RomConfigFile RomConfig;
-extern char RomPath[_MAX_PATH];
-extern char RomFile[_MAX_PATH];
+extern char RomPath[MAX_PATH];
+extern char RomFile[MAX_PATH];
-extern char HardDrivePath[_MAX_PATH]; // JGH
+extern char HardDrivePath[MAX_PATH]; // JGH
unsigned char BeebReadMem(int Address);
void BeebWriteMem(int Address, unsigned char Value);
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index dc09395b..a414124a 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -263,16 +263,16 @@ BeebWin::BeebWin()
// File paths
// Get the applications path - used for non-user files
- char AppPath[_MAX_PATH];
+ char AppPath[MAX_PATH];
char AppDrive[_MAX_DRIVE];
char AppDir[_MAX_DIR];
- GetModuleFileName(nullptr, AppPath, _MAX_PATH);
+ GetModuleFileName(nullptr, AppPath, MAX_PATH);
_splitpath(AppPath, AppDrive, AppDir, nullptr, nullptr);
_makepath(m_AppPath, AppDrive, AppDir, nullptr, nullptr);
// Read user data path from registry
if (!RegGetStringValue(HKEY_CURRENT_USER, CFG_REG_KEY, "UserDataFolder",
- m_UserDataPath, _MAX_PATH))
+ m_UserDataPath, MAX_PATH))
{
// Default user data path to a sub-directory in My Docs
if (SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, m_UserDataPath) == NOERROR)
@@ -393,12 +393,12 @@ bool BeebWin::Initialise()
// Read disc images path from registry
if (!RegGetStringValue(HKEY_CURRENT_USER, CFG_REG_KEY, "DiscsPath",
- m_DiscPath, _MAX_PATH))
+ m_DiscPath, MAX_PATH))
{
// Default disc images path to a sub-directory of UserData path
strcpy(m_DiscPath, m_UserDataPath);
- char DefaultPath[_MAX_PATH];
+ char DefaultPath[MAX_PATH];
m_Preferences.GetStringValue("DiscsPath", DefaultPath);
GetDataPath(m_DiscPath, DefaultPath);
strcpy(m_DiscPath, DefaultPath);
@@ -483,7 +483,7 @@ bool BeebWin::Initialise()
}
}
- char fontFilename[_MAX_PATH];
+ char fontFilename[MAX_PATH];
strcpy(fontFilename, GetAppPath());
strcat(fontFilename, "teletext.fnt");
@@ -525,7 +525,7 @@ void BeebWin::ApplyPrefs()
}
else if (PathIsRelative(EconetCfgPath))
{
- char Filename[_MAX_PATH];
+ char Filename[MAX_PATH];
strcpy(Filename, EconetCfgPath);
strcpy(EconetCfgPath, m_UserDataPath);
strcat(EconetCfgPath, Filename);
@@ -538,7 +538,7 @@ void BeebWin::ApplyPrefs()
}
else if (PathIsRelative(AUNMapPath))
{
- char Filename[_MAX_PATH];
+ char Filename[MAX_PATH];
strcpy(Filename, AUNMapPath);
strcpy(AUNMapPath, m_UserDataPath);
strcat(AUNMapPath, Filename);
@@ -546,13 +546,13 @@ void BeebWin::ApplyPrefs()
strcpy(RomPath, m_UserDataPath);
- char Path[_MAX_PATH];
+ char Path[MAX_PATH];
m_Preferences.GetStringValue("HardDrivePath", Path);
GetDataPath(m_UserDataPath, Path);
strcpy(HardDrivePath, Path);
// Load key maps
- char KeyMapPath[_MAX_PATH];
+ char KeyMapPath[MAX_PATH];
strcpy(KeyMapPath, "Logical.kmap");
GetDataPath(m_UserDataPath, KeyMapPath);
ReadKeyMap(KeyMapPath, &LogicalKeyMap);
@@ -680,8 +680,9 @@ void BeebWin::Shutdown()
WSACleanup();
- if (m_WriteInstructionCounts) {
- char FileName[_MAX_PATH];
+ if (m_WriteInstructionCounts)
+ {
+ char FileName[MAX_PATH];
strcpy(FileName, m_UserDataPath);
strcat(FileName, "InstructionCounts.txt");
@@ -5225,11 +5226,11 @@ void BeebWin::ParseCommandLine()
// Assume it's a file name
if (m_CommandLineFileName1[0] == '\0')
{
- strncpy(m_CommandLineFileName1, __argv[i], _MAX_PATH);
+ strncpy(m_CommandLineFileName1, __argv[i], MAX_PATH);
}
else if (m_CommandLineFileName2[0] == '\0')
{
- strncpy(m_CommandLineFileName2, __argv[i], _MAX_PATH);
+ strncpy(m_CommandLineFileName2, __argv[i], MAX_PATH);
}
}
@@ -5251,7 +5252,7 @@ void BeebWin::CheckForLocalPrefs(const char *path, bool bLoadPrefs)
if (path[0] == '\0')
return;
- char file[_MAX_PATH];
+ char file[MAX_PATH];
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
@@ -5594,7 +5595,7 @@ bool BeebWin::CheckUserDataPath(bool Persist)
bool success = true;
bool copy_user_files = false;
bool store_user_data_path = false;
- char path[_MAX_PATH];
+ char path[MAX_PATH];
// Change all '/' to '\'
MakePreferredPath(m_UserDataPath);
@@ -5696,7 +5697,7 @@ bool BeebWin::CheckUserDataPath(bool Persist)
{
// Get fully qualified user data path
char *f;
- if (GetFullPathName(m_UserDataPath, _MAX_PATH, path, &f) != 0)
+ if (GetFullPathName(m_UserDataPath, MAX_PATH, path, &f) != 0)
strcpy(m_UserDataPath, path);
}
diff --git a/Src/BeebWin.h b/Src/BeebWin.h
index ca5b18fb..4176d944 100644
--- a/Src/BeebWin.h
+++ b/Src/BeebWin.h
@@ -725,7 +725,7 @@ class BeebWin
KeyboardMappingType m_KeyboardMapping;
bool m_KeyMapAS;
bool m_KeyMapFunc;
- char m_UserKeyMapPath[_MAX_PATH];
+ char m_UserKeyMapPath[MAX_PATH];
bool m_DisableKeysWindows;
bool m_DisableKeysBreak;
bool m_DisableKeysEscape;
@@ -735,10 +735,10 @@ class BeebWin
int m_vkeyPressed[256][2][2];
// File paths
- char m_AppPath[_MAX_PATH];
- char m_UserDataPath[_MAX_PATH];
+ char m_AppPath[MAX_PATH];
+ char m_UserDataPath[MAX_PATH];
bool m_CustomData;
- char m_DiscPath[_MAX_PATH]; // JGH
+ char m_DiscPath[MAX_PATH]; // JGH
bool m_WriteProtectDisc[2];
bool m_WriteProtectOnLoad;
@@ -772,8 +772,8 @@ class BeebWin
std::string m_SerialPort;
// Command line
- char m_CommandLineFileName1[_MAX_PATH];
- char m_CommandLineFileName2[_MAX_PATH];
+ char m_CommandLineFileName1[MAX_PATH];
+ char m_CommandLineFileName2[MAX_PATH];
std::string m_DebugScriptFileName;
std::string m_DebugLabelsFileName;
bool m_HasCommandLineModel;
diff --git a/Src/BeebWinIo.cpp b/Src/BeebWinIo.cpp
index ba70324d..1df416a5 100644
--- a/Src/BeebWinIo.cpp
+++ b/Src/BeebWinIo.cpp
@@ -130,7 +130,7 @@ void BeebWin::EjectDiscImage(int Drive)
bool BeebWin::ReadDisc(int Drive, bool bCheckForPrefs)
{
- char FileName[_MAX_PATH];
+ char FileName[MAX_PATH];
FileName[0] = '\0';
const char* Filter =
@@ -141,7 +141,7 @@ bool BeebWin::ReadDisc(int Drive, bool bCheckForPrefs)
"Single Sided Disc (*.*)\0*.*\0"
"Double Sided Disc (*.*)\0*.*\0";
- char DefaultPath[_MAX_PATH];
+ char DefaultPath[MAX_PATH];
DefaultPath[0] = '\0';
m_Preferences.GetStringValue(CFG_DISCS_PATH, DefaultPath);
@@ -364,7 +364,7 @@ bool BeebWin::Load8271DiscImage(const char *FileName, int Drive, int Tracks, Dis
void BeebWin::LoadTape(void)
{
- char FileName[_MAX_PATH];
+ char FileName[MAX_PATH];
FileName[0] = '\0';
const char* Filter =
@@ -372,7 +372,7 @@ void BeebWin::LoadTape(void)
"UEF Tape File (*.uef)\0*.uef\0"
"CSW Tape File (*.csw)\0*.csw\0";
- char DefaultPath[_MAX_PATH];
+ char DefaultPath[MAX_PATH];
DefaultPath[0] = '\0';
m_Preferences.GetStringValue(CFG_TAPES_PATH, DefaultPath);
@@ -424,7 +424,7 @@ bool BeebWin::LoadTape(const char *FileName)
bool BeebWin::NewTapeImage(char *FileName, int Size)
{
- char DefaultPath[_MAX_PATH];
+ char DefaultPath[MAX_PATH];
const char* filter = "UEF Tape File (*.uef)\0*.uef\0";
m_Preferences.GetStringValue(CFG_TAPES_PATH, DefaultPath);
@@ -454,7 +454,7 @@ bool BeebWin::NewTapeImage(char *FileName, int Size)
void BeebWin::SelectFDC()
{
- char DefaultPath[_MAX_PATH];
+ char DefaultPath[MAX_PATH];
char FileName[256];
FileName[0] = '\0';
@@ -491,7 +491,7 @@ void BeebWin::NewDiscImage(int Drive)
"ADFS M (80 Track) Disc (*.adf)\0*.adf\0"
"ADFS L (160 Track) Disc (*.adl)\0*.adl\0";
- char DefaultPath[_MAX_PATH];
+ char DefaultPath[MAX_PATH];
DefaultPath[0] = '\0';
m_Preferences.GetStringValue(CFG_DISCS_PATH, DefaultPath);
@@ -503,7 +503,7 @@ void BeebWin::NewDiscImage(int Drive)
if ((MachineType != Model::Master128 && MachineType != Model::MasterET) && NativeFDC && FilterIndex >= 5)
FilterIndex = 1;
- char FileName[_MAX_PATH];
+ char FileName[MAX_PATH];
FileName[0] = '\0';
FileDialog Dialog(m_hWnd, FileName, sizeof(FileName), DefaultPath, Filter);
@@ -620,12 +620,12 @@ void BeebWin::CreateDFSDiscImage(const char *FileName, int Drive,
/****************************************************************************/
void BeebWin::SaveState()
{
- char FileName[_MAX_PATH];
+ char FileName[MAX_PATH];
FileName[0] = '\0';
const char* Filter = "UEF State File (*.uefstate)\0*.uefstate\0";
- char DefaultPath[_MAX_PATH];
+ char DefaultPath[MAX_PATH];
DefaultPath[0] = '\0';
m_Preferences.GetStringValue(CFG_STATES_PATH, DefaultPath);
@@ -655,12 +655,12 @@ void BeebWin::SaveState()
/****************************************************************************/
void BeebWin::RestoreState()
{
- char FileName[_MAX_PATH];
+ char FileName[MAX_PATH];
FileName[0] = '\0';
const char* filter = "UEF State File (*.uefstate; *.uef)\0*.uefstate;*.uef\0";
- char DefaultPath[_MAX_PATH];
+ char DefaultPath[MAX_PATH];
DefaultPath[0] = '\0';
m_Preferences.GetStringValue(CFG_STATES_PATH, DefaultPath);
@@ -822,8 +822,8 @@ void BeebWin::UpdatePrinterPortMenu()
bool BeebWin::GetPrinterFileName()
{
- char StartPath[_MAX_PATH];
- char FileName[_MAX_PATH];
+ char StartPath[MAX_PATH];
+ char FileName[MAX_PATH];
FileName[0] = '\0';
const char* Filter = "Printer Output (*.*)\0*.*\0";
@@ -1016,8 +1016,8 @@ void BeebWin::UpdateVideoCaptureFrameSkipMenu()
void BeebWin::CaptureVideo()
{
- char DefaultPath[_MAX_PATH];
- char FileName[_MAX_PATH];
+ char DefaultPath[MAX_PATH];
+ char FileName[MAX_PATH];
FileName[0] = '\0';
const char* filter = "AVI File (*.avi)\0*.avi\0";
@@ -1150,7 +1150,7 @@ bool BeebWin::IsCapturing() const
/****************************************************************************/
void BeebWin::QuickLoad()
{
- char FileName[_MAX_PATH];
+ char FileName[MAX_PATH];
strcpy(FileName, m_UserDataPath);
strcat(FileName, "BeebState\\quicksave.uefstate");
@@ -1169,8 +1169,8 @@ void BeebWin::QuickLoad()
void BeebWin::QuickSave()
{
- char FileName1[_MAX_PATH];
- char FileName2[_MAX_PATH];
+ char FileName1[MAX_PATH];
+ char FileName2[MAX_PATH];
// Bump old quicksave files down
for (int i = 1; i <= 9; ++i)
@@ -1327,7 +1327,7 @@ void BeebWin::LoadFDC(char *DLLName, bool save)
if (strcmp(DLLName, "None") != 0)
{
- char path[_MAX_PATH];
+ char path[MAX_PATH];
strcpy(path, DLLName);
GetDataPath(m_AppPath, path);
@@ -1476,7 +1476,7 @@ void BeebWin::LoadEmuUEF(FILE *SUEF, int Version)
/****************************************************************************/
void BeebWin::GetDataPath(const char *folder, char *path)
{
- char newPath[_MAX_PATH];
+ char newPath[MAX_PATH];
// If path is absolute then use it
if (path[0] == '\\' || path[0] == '/' ||
@@ -1496,7 +1496,7 @@ void BeebWin::GetDataPath(const char *folder, char *path)
/****************************************************************************/
void BeebWin::LoadUserKeyMap()
{
- char FileName[_MAX_PATH];
+ char FileName[MAX_PATH];
FileName[0] = '\0';
const char* filter = "Key Map File (*.kmap)\0*.kmap\0";
@@ -1512,7 +1512,7 @@ void BeebWin::LoadUserKeyMap()
/****************************************************************************/
void BeebWin::SaveUserKeyMap()
{
- char FileName[_MAX_PATH];
+ char FileName[MAX_PATH];
FileName[0] = '\0';
const char* filter = "Key Map File (*.kmap)\0*.kmap\0";
@@ -1893,8 +1893,8 @@ void BeebWin::ImportDiscFiles(int menuId)
void BeebWin::SelectHardDriveFolder()
{
- char DefaultPath[_MAX_PATH];
- char FileName[_MAX_PATH];
+ char DefaultPath[MAX_PATH];
+ char FileName[MAX_PATH];
FileName[0] = '\0';
const char* filter =
@@ -2092,7 +2092,7 @@ bool BeebWin::GetImageFile(char *FileName, int Size)
FileName[0] = '\0';
- char DefaultPath[_MAX_PATH];
+ char DefaultPath[MAX_PATH];
m_Preferences.GetStringValue(CFG_IMAGE_PATH, DefaultPath);
GetDataPath(m_UserDataPath, DefaultPath);
diff --git a/Src/BeebWinSpeech.cpp b/Src/BeebWinSpeech.cpp
index d460683d..a0086cca 100644
--- a/Src/BeebWinSpeech.cpp
+++ b/Src/BeebWinSpeech.cpp
@@ -246,7 +246,7 @@ void BeebWin::InitVoiceMenu()
int BeebWin::TextToSpeechGetSelectedVoice()
{
- char TokenId[_MAX_PATH];
+ char TokenId[MAX_PATH];
TokenId[0] = '\0';
int Index = 0;
diff --git a/Src/DiscEdit.cpp b/Src/DiscEdit.cpp
index bcd44b60..1c2d75c1 100644
--- a/Src/DiscEdit.cpp
+++ b/Src/DiscEdit.cpp
@@ -348,7 +348,7 @@ bool dfs_import_file(const char *szDiscFile,
{
bool success = true;
- char infname[_MAX_PATH];
+ char infname[MAX_PATH];
char dfsname[DFS_MAX_NAME_LEN + 3];
int startSector = 0;
int catIndex = 0;
diff --git a/Src/ExportFileDialog.cpp b/Src/ExportFileDialog.cpp
index 8095c819..2623bb08 100644
--- a/Src/ExportFileDialog.cpp
+++ b/Src/ExportFileDialog.cpp
@@ -237,7 +237,7 @@ void ExportFileDialog::ExportSelectedFiles()
if (FileExists(LocalFileName.c_str()))
{
- char FileName[_MAX_PATH];
+ char FileName[MAX_PATH];
const char* Filter = "All Files (*.*)\0*.*\0";
strcpy(FileName, Entry->HostFileName.c_str());
diff --git a/Src/RomConfigFile.cpp b/Src/RomConfigFile.cpp
index 2bcbd818..d06a51b8 100644
--- a/Src/RomConfigFile.cpp
+++ b/Src/RomConfigFile.cpp
@@ -184,7 +184,7 @@ bool RomConfigFile::Load(const char *FileName)
continue;
}
- if (Line.size() >= _MAX_PATH)
+ if (Line.size() >= MAX_PATH)
{
Success = false;
break;
diff --git a/Src/TapeControlDialog.cpp b/Src/TapeControlDialog.cpp
index e70d160f..e23a8263 100644
--- a/Src/TapeControlDialog.cpp
+++ b/Src/TapeControlDialog.cpp
@@ -262,7 +262,7 @@ void TapeControlRecord()
if (!TapeState.Recording)
{
// Query for new file name
- char FileName[_MAX_PATH];
+ char FileName[MAX_PATH];
FileName[0] = '\0';
if (mainWin->NewTapeImage(FileName, sizeof(FileName)))
diff --git a/Src/TeletextDialog.cpp b/Src/TeletextDialog.cpp
index 17f54fca..56ada5d6 100644
--- a/Src/TeletextDialog.cpp
+++ b/Src/TeletextDialog.cpp
@@ -213,8 +213,8 @@ INT_PTR TeletextDialog::OnCommand(int Notification, int nCommandID)
void TeletextDialog::SelectFile(int Channel)
{
- char DefaultPath[_MAX_PATH];
- char FileName[_MAX_PATH];
+ char DefaultPath[MAX_PATH];
+ char FileName[MAX_PATH];
FileName[0] = '\0';
strcpy(DefaultPath, m_DiscsPath.c_str());
From bf769dd8423019802888e4d662d04fa0c4455cc6 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Tue, 30 Jul 2024 20:53:52 +0100
Subject: [PATCH 018/101] Use size_t data type
---
Src/BeebWin.cpp | 29 ++++++++++++++---------------
1 file changed, 14 insertions(+), 15 deletions(-)
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index a414124a..dd0efbd3 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -1501,7 +1501,7 @@ void BeebWin::UpdateDisplayRendererMenu()
UINT SelectedMenuItemID = 0;
- for (int i = 0; i < _countof(MenuItems); i++)
+ for (size_t i = 0; i < _countof(MenuItems); i++)
{
if (m_DisplayRenderer == MenuItems[i].DisplayRenderer)
{
@@ -1592,7 +1592,7 @@ void BeebWin::UpdateSoundSampleRateMenu()
UINT SelectedMenuItemID = 0;
- for (int i = 0; i < _countof(MenuItems); i++)
+ for (size_t i = 0; i < _countof(MenuItems); i++)
{
if (SoundSampleRate == MenuItems[i].SampleRate)
{
@@ -1628,7 +1628,7 @@ void BeebWin::UpdateSoundVolumeMenu()
UINT SelectedMenuItemID = 0;
- for (int i = 0; i < _countof(MenuItems); i++)
+ for (size_t i = 0; i < _countof(MenuItems); i++)
{
if (SoundVolume == MenuItems[i].Volume)
{
@@ -1692,7 +1692,7 @@ void BeebWin::UpdateMonitorMenu()
UINT SelectedMenuItemID = 0;
- for (int i = 0; i < _countof(MenuItems); i++)
+ for (size_t i = 0; i < _countof(MenuItems); i++)
{
if (m_MonitorType == MenuItems[i].Type)
{
@@ -1717,7 +1717,7 @@ void BeebWin::UpdateModelMenu()
UINT SelectedMenuItemID = 0;
- for (int i = 0; i < _countof(MenuItems); i++)
+ for (size_t i = 0; i < _countof(MenuItems); i++)
{
if (MachineType == MenuItems[i].Type)
{
@@ -1920,7 +1920,7 @@ void BeebWin::UpdateTubeMenu()
UINT SelectedMenuItemID = 0;
- for (int i = 0; i < _countof(MenuItems); i++)
+ for (size_t i = 0; i < _countof(MenuItems); i++)
{
if (TubeType == MenuItems[i].Device)
{
@@ -2021,7 +2021,7 @@ void BeebWin::UpdateJoystickMenu()
UINT SelectedMenuItemID = 0;
- for (int i = 0; i < _countof(MenuItems); i++)
+ for (size_t i = 0; i < _countof(MenuItems); i++)
{
if (m_JoystickOption == MenuItems[i].Joystick)
{
@@ -2981,7 +2981,7 @@ void BeebWin::UpdateDirectXFullScreenModeMenu()
UINT SelectedMenuItemID = 0;
- for (int i = 0; i < _countof(MenuItems); i++)
+ for (size_t i = 0; i < _countof(MenuItems); i++)
{
if (m_DDFullScreenMode == MenuItems[i].Mode)
{
@@ -3045,7 +3045,7 @@ void BeebWin::UpdateWindowSizeMenu()
int SelectedMenuItemID = 0;
- for (int i = 0; i < _countof(MenuItems); i++)
+ for (size_t i = 0; i < _countof(MenuItems); i++)
{
if (m_XWinSize == MenuItems[i].Width &&
m_YWinSize == MenuItems[i].Height)
@@ -3192,7 +3192,7 @@ void BeebWin::UpdateKeyboardMappingMenu()
UINT SelectedMenuItemID = 0;
- for (int i = 0; i < _countof(MenuItems); i++)
+ for (size_t i = 0; i < _countof(MenuItems); i++)
{
if (m_KeyboardMapping == MenuItems[i].Type)
{
@@ -3238,7 +3238,7 @@ void BeebWin::SetTapeSpeedMenu()
UINT SelectedMenuItemID = 0;
- for (int i = 0; i < _countof(MenuItems); i++)
+ for (size_t i = 0; i < _countof(MenuItems); i++)
{
if (TapeState.ClockSpeed == MenuItems[i].ClockSpeed)
{
@@ -3454,7 +3454,7 @@ void BeebWin::UpdateAMXSizeMenu()
UINT SelectedMenuItemID = 0;
- for (int i = 0; i < _countof(MenuItems); i++)
+ for (size_t i = 0; i < _countof(MenuItems); i++)
{
if (m_AMXSize == MenuItems[i].AMXSize)
{
@@ -3517,7 +3517,7 @@ void BeebWin::UpdateAMXAdjustMenu()
UINT SelectedMenuItemID = 0;
- for (int i = 0; i < _countof(MenuItems); i++)
+ for (size_t i = 0; i < _countof(MenuItems); i++)
{
if (m_AMXAdjust == MenuItems[i].AMXAdjust)
{
@@ -4094,8 +4094,7 @@ void BeebWin::HandleCommand(UINT MenuID)
case IDM_ALLOWWRITES_ROMC:
case IDM_ALLOWWRITES_ROMD:
case IDM_ALLOWWRITES_ROME:
- case IDM_ALLOWWRITES_ROMF:
- {
+ case IDM_ALLOWWRITES_ROMF: {
int slot = MenuID - IDM_ALLOWWRITES_ROM0;
RomWritable[slot] = !RomWritable[slot];
CheckMenuItem(MenuID, RomWritable[slot]);
From 57c90ea9671cf65aa8af2de5f6d7a8684dec1d02 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Tue, 30 Jul 2024 21:03:52 +0100
Subject: [PATCH 019/101] Renamed AVIWriter to AviWriter
---
Src/{AVIWriter.cpp => AviWriter.cpp} | 32 ++++++++++++++--------------
Src/{AVIWriter.h => AviWriter.h} | 13 +++++------
Src/BeebWinIo.cpp | 2 +-
3 files changed, 24 insertions(+), 23 deletions(-)
rename Src/{AVIWriter.cpp => AviWriter.cpp} (92%)
rename Src/{AVIWriter.h => AviWriter.h} (93%)
diff --git a/Src/AVIWriter.cpp b/Src/AviWriter.cpp
similarity index 92%
rename from Src/AVIWriter.cpp
rename to Src/AviWriter.cpp
index 79cc9474..3ede3f9d 100644
--- a/Src/AVIWriter.cpp
+++ b/Src/AviWriter.cpp
@@ -31,12 +31,12 @@ Boston, MA 02110-1301, USA.
/*--------------------------------------------------------------------------*/
-AVIWriter *aviWriter = nullptr;
+AviWriter *aviWriter = nullptr;
/*--------------------------------------------------------------------------*/
-AVIWriter::AVIWriter() :
- m_pAVIFile(nullptr),
+AviWriter::AviWriter() :
+ m_pAviFile(nullptr),
m_pAudioStream(nullptr),
m_pCompressedAudioStream(nullptr),
m_pVideoStream(nullptr),
@@ -52,7 +52,7 @@ AVIWriter::AVIWriter() :
/*--------------------------------------------------------------------------*/
-HRESULT AVIWriter::Initialise(const CHAR *pszFileName,
+HRESULT AviWriter::Initialise(const CHAR *pszFileName,
const WAVEFORMATEX *WaveFormat,
const bmiData *BitmapFormat,
int fps)
@@ -63,7 +63,7 @@ HRESULT AVIWriter::Initialise(const CHAR *pszFileName,
m_BitmapFormat = *BitmapFormat;
DeleteFile(pszFileName);
- HRESULT hr = AVIFileOpen(&m_pAVIFile,
+ HRESULT hr = AVIFileOpen(&m_pAviFile,
pszFileName,
OF_WRITE | OF_CREATE,
NULL);
@@ -81,7 +81,7 @@ HRESULT AVIWriter::Initialise(const CHAR *pszFileName,
m_nSampleSize = StreamInfo.dwSampleSize;
- hr = AVIFileCreateStream(m_pAVIFile, &m_pAudioStream, &StreamInfo);
+ hr = AVIFileCreateStream(m_pAviFile, &m_pAudioStream, &StreamInfo);
}
if (SUCCEEDED(hr) && WaveFormat)
@@ -109,7 +109,7 @@ HRESULT AVIWriter::Initialise(const CHAR *pszFileName,
StreamInfo.rcFrame.bottom = m_BitmapFormat.bmiHeader.biHeight;
strcpy(&StreamInfo.szName[0], "BeebEm Video Capture");
- hr = AVIFileCreateStream(m_pAVIFile, &m_pVideoStream, &StreamInfo);
+ hr = AVIFileCreateStream(m_pAviFile, &m_pVideoStream, &StreamInfo);
}
bmiData outputData = m_BitmapFormat;
@@ -152,7 +152,7 @@ HRESULT AVIWriter::Initialise(const CHAR *pszFileName,
/*--------------------------------------------------------------------------*/
-AVIWriter::~AVIWriter()
+AviWriter::~AviWriter()
{
Close();
AVIFileExit();
@@ -160,7 +160,7 @@ AVIWriter::~AVIWriter()
/*--------------------------------------------------------------------------*/
-void AVIWriter::Close()
+void AviWriter::Close()
{
if (m_pCompressedAudioStream != nullptr)
{
@@ -198,18 +198,18 @@ void AVIWriter::Close()
m_pVideoStream = nullptr;
}
- if (m_pAVIFile != nullptr)
+ if (m_pAviFile != nullptr)
{
- AVIFileRelease(m_pAVIFile);
- m_pAVIFile = nullptr;
+ AVIFileRelease(m_pAviFile);
+ m_pAviFile = nullptr;
}
}
/*--------------------------------------------------------------------------*/
-HRESULT AVIWriter::WriteSound(BYTE *pBuffer, ULONG nBytesToWrite)
+HRESULT AviWriter::WriteSound(BYTE *pBuffer, ULONG nBytesToWrite)
{
- if (m_pAudioStream == nullptr || m_pAVIFile == nullptr)
+ if (m_pAudioStream == nullptr || m_pAviFile == nullptr)
{
return E_UNEXPECTED;
}
@@ -241,12 +241,12 @@ HRESULT AVIWriter::WriteSound(BYTE *pBuffer, ULONG nBytesToWrite)
/*--------------------------------------------------------------------------*/
-HRESULT AVIWriter::WriteVideo(BYTE *pBuffer)
+HRESULT AviWriter::WriteVideo(BYTE *pBuffer)
{
if (m_videoCompressor == nullptr ||
m_videoBuffer == nullptr ||
m_lastVideoFrame == nullptr ||
- m_pAVIFile == nullptr)
+ m_pAviFile == nullptr)
{
return E_UNEXPECTED;
}
diff --git a/Src/AVIWriter.h b/Src/AviWriter.h
similarity index 93%
rename from Src/AVIWriter.h
rename to Src/AviWriter.h
index 3c648b85..49511b09 100644
--- a/Src/AVIWriter.h
+++ b/Src/AviWriter.h
@@ -31,11 +31,11 @@ Boston, MA 02110-1301, USA.
#include "BeebWin.h"
-class AVIWriter
+class AviWriter
{
public:
- AVIWriter();
- virtual ~AVIWriter();
+ AviWriter();
+ virtual ~AviWriter();
// Open file
HRESULT Initialise(const CHAR *psFileName,
@@ -48,7 +48,7 @@ class AVIWriter
HRESULT WriteVideo(BYTE *pBuffer);
private:
- PAVIFILE m_pAVIFile;
+ PAVIFILE m_pAviFile;
WAVEFORMATEX m_WaveFormat;
PAVISTREAM m_pAudioStream;
@@ -65,6 +65,7 @@ class AVIWriter
LONG m_nFrame;
};
-extern AVIWriter *aviWriter;
+extern AviWriter *aviWriter;
+
+#endif
-#endif
\ No newline at end of file
diff --git a/Src/BeebWinIo.cpp b/Src/BeebWinIo.cpp
index 1df416a5..5e7fe8fd 100644
--- a/Src/BeebWinIo.cpp
+++ b/Src/BeebWinIo.cpp
@@ -1045,7 +1045,7 @@ void BeebWin::CaptureVideo()
// Close AVI file if currently capturing
EndVideo();
- aviWriter = new AVIWriter();
+ aviWriter = new AviWriter();
WAVEFORMATEX wf;
WAVEFORMATEX *wfp = nullptr;
From bb7ab0d7808ae866d1b2a830c88d174661bf9f66 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Tue, 30 Jul 2024 21:05:34 +0100
Subject: [PATCH 020/101] Removed unused function
---
Src/BeebWin.cpp | 9 ---------
Src/BeebWin.h | 1 -
2 files changed, 10 deletions(-)
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index dd0efbd3..4d42f812 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -1317,15 +1317,6 @@ void BeebWin::HideMenu(bool hide)
}
}
-void BeebWin::TrackPopupMenu(int x, int y)
-{
- ::TrackPopupMenu(m_hMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON,
- x, y,
- 0,
- m_hWnd,
- NULL);
-}
-
/****************************************************************************/
void BeebWin::CheckMenuItem(UINT id, bool Checked)
diff --git a/Src/BeebWin.h b/Src/BeebWin.h
index 4176d944..e312afc6 100644
--- a/Src/BeebWin.h
+++ b/Src/BeebWin.h
@@ -355,7 +355,6 @@ class BeebWin
void UserKeyboardDialogClosed();
void ShowMenu(bool on);
void HideMenu(bool hide);
- void TrackPopupMenu(int x, int y);
bool IsFullScreen() const { return m_FullScreen; }
void ResetTiming(void);
int TranslateKey(int vkey, bool keyUp, int &row, int &col);
From 43f1e4dcbf5d1a37a9b725c47c8dba7492b086e7 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Tue, 30 Jul 2024 21:57:15 +0100
Subject: [PATCH 021/101] Added ToHexDigit() function
---
Src/BeebWin.cpp | 3 ++-
Src/IP232.cpp | 7 +++----
Src/StringUtils.cpp | 10 ++++++++++
Src/StringUtils.h | 1 +
4 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index 4d42f812..f20c3298 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -92,6 +92,7 @@ using std::max;
#include "SoundStreamer.h"
#include "Speech.h"
#include "SprowCoPro.h"
+#include "StringUtils.h"
#include "SysVia.h"
#include "TapeControlDialog.h"
#include "Teletext.h"
@@ -1934,7 +1935,7 @@ void BeebWin::SetRomMenu()
CHAR Title[19];
Title[0] = '&';
- _itoa(i, &Title[1], 16);
+ Title[1] = ToHexDigit(i);
Title[2] = ' ';
// Get the Rom Title.
diff --git a/Src/IP232.cpp b/Src/IP232.cpp
index d70a1dc1..a965a59a 100644
--- a/Src/IP232.cpp
+++ b/Src/IP232.cpp
@@ -45,6 +45,7 @@ Boston, MA 02110-1301, USA.
#include "Messages.h"
#include "RingBuffer.h"
#include "Serial.h"
+#include "StringUtils.h"
#include "Thread.h"
constexpr int IP232_CONNECTION_DELAY = 8192; // Cycles to wait after connection
@@ -502,12 +503,10 @@ static void DebugReceivedData(unsigned char* pData, int Length)
DebugDisplayTraceF(DebugType::RemoteServer, true,
"IP232: Read %d bytes from server", Length);
- static const char HexDigit[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
-
for (i = 0; i < Length; i++)
{
- info[i * 2] = HexDigit[(pData[i] >> 4) & 0xf];
- info[(i * 2) + 1] = HexDigit[pData[i] & 0x0f];
+ info[i * 2] = ToHexDigit((pData[i] >> 4) & 0xf);
+ info[(i * 2) + 1] = ToHexDigit(pData[i] & 0x0f);
}
info[i * 2] = 0;
diff --git a/Src/StringUtils.cpp b/Src/StringUtils.cpp
index 987c041f..a4c073f6 100644
--- a/Src/StringUtils.cpp
+++ b/Src/StringUtils.cpp
@@ -63,6 +63,16 @@ bool ParseNumber(const std::string& str, int* pValue)
return true;
}
+char ToHexDigit(int Value)
+{
+ static const char HexDigit[16] =
+ {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+ };
+
+ return HexDigit[Value];
+}
+
bool StringEndsWith(const std::string& str, const std::string& suffix)
{
return str.size() >= suffix.size() &&
diff --git a/Src/StringUtils.h b/Src/StringUtils.h
index 3bc78009..ed49d331 100644
--- a/Src/StringUtils.h
+++ b/Src/StringUtils.h
@@ -25,6 +25,7 @@ Boston, MA 02110-1301, USA.
void trim(std::string& str);
bool ParseNumber(const std::string& str, int* pValue);
+char ToHexDigit(int Value);
bool StringEndsWith(const std::string& str, const std::string& suffix);
std::string WStr2Str(const std::wstring& str);
std::wstring Str2WStr(const std::string& str);
From 9eee1d5312af6ad38021330d16b1dfa461005b10 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Tue, 30 Jul 2024 22:03:50 +0100
Subject: [PATCH 022/101] Added comments
---
Src/SysVia.cpp | 2 ++
Src/UserVia.cpp | 2 ++
2 files changed, 4 insertions(+)
diff --git a/Src/SysVia.cpp b/Src/SysVia.cpp
index b0c9de11..b1871b8d 100644
--- a/Src/SysVia.cpp
+++ b/Src/SysVia.cpp
@@ -731,6 +731,8 @@ unsigned char SysVIARead(int Address)
case 1:
SysVIAState.ifr &= 0xfc;
UpdateIFRTopBit();
+ // Fall through...
+
case 15:
// slow data bus read
tmp = SlowDataBusRead();
diff --git a/Src/UserVia.cpp b/Src/UserVia.cpp
index 5f4acea6..98b1c152 100644
--- a/Src/UserVia.cpp
+++ b/Src/UserVia.cpp
@@ -356,6 +356,8 @@ unsigned char UserVIARead(int Address)
case 1:
UserVIAState.ifr &= 0xfc;
UpdateIFRTopBit();
+ // Fall through...
+
case 15:
tmp = 255;
break;
From cf553d50668126546ae3aaef85181e8f3069ad04 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Tue, 30 Jul 2024 22:04:15 +0100
Subject: [PATCH 023/101] Removed unnecessary #includes
---
Src/Via.cpp | 5 -----
1 file changed, 5 deletions(-)
diff --git a/Src/Via.cpp b/Src/Via.cpp
index 5e01513b..042bcc07 100644
--- a/Src/Via.cpp
+++ b/Src/Via.cpp
@@ -20,13 +20,8 @@ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
****************************************************************/
-#include
-
#include
-#include
-#include
-
#include "Via.h"
#include "Debug.h"
#include "SysVia.h"
From edcba55920ca8408a2eebd3e82825b9d5fa0f6a6 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Tue, 30 Jul 2024 22:08:23 +0100
Subject: [PATCH 024/101] Use inline functions
---
Src/6502core.cpp | 4 ----
Src/Tube.cpp | 7 ++-----
2 files changed, 2 insertions(+), 9 deletions(-)
diff --git a/Src/6502core.cpp b/Src/6502core.cpp
index efd495bb..5848350e 100644
--- a/Src/6502core.cpp
+++ b/Src/6502core.cpp
@@ -57,11 +57,7 @@ Boston, MA 02110-1301, USA.
#include "Z80mem.h"
#include "Z80.h"
-#ifdef WIN32
#define INLINE inline
-#else
-#define INLINE
-#endif
static CPU CPUType;
static int CurrentInstruction;
diff --git a/Src/Tube.cpp b/Src/Tube.cpp
index 4acb528e..bc50f74a 100644
--- a/Src/Tube.cpp
+++ b/Src/Tube.cpp
@@ -24,6 +24,8 @@ Boston, MA 02110-1301, USA.
/* Mike Wyatt 7/6/97 - Added undocumented instructions */
/* Copied for 65C02 Tube core - 13/04/01 */
+#include
+
#include
#include
#include
@@ -43,12 +45,7 @@ Boston, MA 02110-1301, USA.
#include "Z80mem.h"
#include "Z80.h"
-#ifdef WIN32
-#include
#define INLINE inline
-#else
-#define INLINE
-#endif
// Some interrupt set macros
#define SETTUBEINT(a) TubeintStatus |= 1 << a
From 472d62544e10be78193d2385c9f43d2cab73789b Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Tue, 30 Jul 2024 22:09:08 +0100
Subject: [PATCH 025/101] Updated comments
---
Src/Sound.h | 2 +-
Src/Video.h | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/Src/Sound.h b/Src/Sound.h
index e2e09ed8..70a88ca9 100644
--- a/Src/Sound.h
+++ b/Src/Sound.h
@@ -50,7 +50,7 @@ extern double SoundTuning;
void SoundInit();
void SoundReset();
-// Called in sysvia.cpp when a write to one of the 76489's registers occurs
+// Called in SysVia.cpp when a write to one of the 76489's registers occurs
void Sound_RegWrite(int Value);
void ClickRelay(bool RelayState);
diff --git a/Src/Video.h b/Src/Video.h
index 23cd848b..4fd7b6c2 100644
--- a/Src/Video.h
+++ b/Src/Video.h
@@ -24,6 +24,7 @@ Boston, MA 02110-1301, USA.
#ifndef VIDEO_HEADER
#define VIDEO_HEADER
+
#include
extern int VideoTriggerCount;
From 6a1268a91a05331f39701eda5fa8525a587bff80 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Tue, 30 Jul 2024 22:10:33 +0100
Subject: [PATCH 026/101] Added CentreMessageBox() function
---
Src/BeebWin.cpp | 33 +++++++++++++++++++++++----------
1 file changed, 23 insertions(+), 10 deletions(-)
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index f20c3298..de4ebe17 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -131,6 +131,10 @@ const char DefaultBlurIntensities[8] = { 100, 88, 75, 62, 50, 38, 25, 12 };
/****************************************************************************/
+static int CentreMessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
+
+/****************************************************************************/
+
BeebWin::BeebWin()
{
// Main window
@@ -5921,9 +5925,6 @@ void BeebWin::OpenDebugWindow()
/****************************************************************************/
-static HHOOK hCBTHook = nullptr;
-static LRESULT CALLBACK CBTMessageBox(int Message, WPARAM wParam, LPARAM lParam);
-
MessageResult BeebWin::Report(MessageType type, const char *format, ...)
{
va_list args;
@@ -5975,12 +5976,7 @@ MessageResult BeebWin::ReportV(MessageType type, const char *format, va_list arg
break;
}
- hCBTHook = SetWindowsHookEx(WH_CBT, CBTMessageBox, nullptr, GetCurrentThreadId());
-
- int ID = MessageBox(m_hWnd, buffer, WindowTitle, Type);
-
- UnhookWindowsHookEx(hCBTHook);
- hCBTHook = nullptr;
+ int ID = CentreMessageBox(m_hWnd, buffer, WindowTitle, Type);
if (type == MessageType::Question)
{
@@ -6013,7 +6009,12 @@ MessageResult BeebWin::ReportV(MessageType type, const char *format, va_list arg
/****************************************************************************/
-LRESULT CALLBACK CBTMessageBox(int nCode, WPARAM wParam, LPARAM lParam)
+static HHOOK hCBTHook = nullptr;
+static LRESULT CALLBACK CBTMessageBox(int Message, WPARAM wParam, LPARAM lParam);
+
+/****************************************************************************/
+
+static LRESULT CALLBACK CBTMessageBox(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HCBT_ACTIVATE)
{
@@ -6026,3 +6027,15 @@ LRESULT CALLBACK CBTMessageBox(int nCode, WPARAM wParam, LPARAM lParam)
}
/****************************************************************************/
+
+static int CentreMessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
+{
+ hCBTHook = SetWindowsHookEx(WH_CBT, CBTMessageBox, nullptr, GetCurrentThreadId());
+
+ int ID = MessageBox(m_hWnd, buffer, WindowTitle, Type);
+
+ UnhookWindowsHookEx(hCBTHook);
+ hCBTHook = nullptr;
+}
+
+/****************************************************************************/
From 040176f2ac7a19d7b5482b324b21fa085c42f2c6 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Tue, 30 Jul 2024 22:11:27 +0100
Subject: [PATCH 027/101] Removed using namespace directive
---
Src/BeebWin.cpp | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index de4ebe17..5781bfba 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -109,8 +109,6 @@ using std::max;
#include "Z80mem.h"
#include "Z80.h"
-using namespace Gdiplus;
-
// Some LED based constants
constexpr int LED_COL_BASE = 64;
@@ -441,8 +439,9 @@ bool BeebWin::Initialise()
return false;
}
- GdiplusStartupInput gdiplusStartupInput;
- if (GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL) != Status::Ok)
+ Gdiplus::GdiplusStartupInput gdiplusStartupInput;
+
+ if (Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL) != Gdiplus::Status::Ok)
{
return false;
}
From 0ebd9fe9ffd77a4c14500a35c3d94d8572f56a1c Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Tue, 30 Jul 2024 22:11:59 +0100
Subject: [PATCH 028/101] Minor refactoring
---
Src/BeebWin.cpp | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index 5781bfba..aab7a470 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -114,10 +114,6 @@ constexpr int LED_COL_BASE = 64;
static const char *CFG_REG_KEY = "Software\\BeebEm";
-static const unsigned char CFG_DISABLE_WINDOWS_KEYS[24] = {
- 00,00,00,00,00,00,00,00,03,00,00,00,00,00,0x5B,0xE0,00,00,0x5C,0xE0,00,00,00,00
-};
-
CArm *arm = nullptr;
CSprowCoPro *sprow = nullptr;
@@ -1828,6 +1824,11 @@ void BeebWin::UpdateSFXMenu()
/****************************************************************************/
+static const unsigned char CFG_DISABLE_WINDOWS_KEYS[24] =
+{
+ 00,00,00,00,00,00,00,00,03,00,00,00,00,00,0x5B,0xE0,00,00,0x5C,0xE0,00,00,00,00
+};
+
void BeebWin::DisableWindowsKeys()
{
bool Reboot = false;
From a573c1d48add6a082b88f8f37807ecd6556d6c0c Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 3 Aug 2024 20:38:57 +0100
Subject: [PATCH 029/101] Added missing #includes
---
Src/Arm.cpp | 2 ++
Src/BeebWin.cpp | 10 ++++++----
Src/Sasi.cpp | 2 ++
Src/Scsi.cpp | 2 ++
Src/UefState.cpp | 2 ++
Src/Video.cpp | 2 ++
Src/Z80Support.cpp | 2 ++
7 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/Src/Arm.cpp b/Src/Arm.cpp
index f9ce2216..fa488c8b 100644
--- a/Src/Arm.cpp
+++ b/Src/Arm.cpp
@@ -25,6 +25,8 @@ Boston, MA 02110-1301, USA.
// http://www.davidsharp.com
//////////////////////////////////////////////////////////////////////
+#include
+
#include
#include
#include
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index aab7a470..09d287ce 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -125,7 +125,7 @@ const char DefaultBlurIntensities[8] = { 100, 88, 75, 62, 50, 38, 25, 12 };
/****************************************************************************/
-static int CentreMessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
+static int CentreMessageBox(HWND hWnd, LPCTSTR pszText, LPCTSTR pszCaption, UINT Type);
/****************************************************************************/
@@ -646,7 +646,7 @@ BeebWin::~BeebWin()
if (m_hDCBitmap != NULL)
DeleteDC(m_hDCBitmap);
- GdiplusShutdown(m_gdiplusToken);
+ Gdiplus::GdiplusShutdown(m_gdiplusToken);
CoUninitialize();
}
@@ -6028,14 +6028,16 @@ static LRESULT CALLBACK CBTMessageBox(int nCode, WPARAM wParam, LPARAM lParam)
/****************************************************************************/
-static int CentreMessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
+static int CentreMessageBox(HWND hWnd, LPCTSTR pszText, LPCTSTR pszCaption, UINT Type)
{
hCBTHook = SetWindowsHookEx(WH_CBT, CBTMessageBox, nullptr, GetCurrentThreadId());
- int ID = MessageBox(m_hWnd, buffer, WindowTitle, Type);
+ int Result = MessageBox(hWnd, pszText, pszCaption, Type);
UnhookWindowsHookEx(hCBTHook);
hCBTHook = nullptr;
+
+ return Result;
}
/****************************************************************************/
diff --git a/Src/Sasi.cpp b/Src/Sasi.cpp
index ba1aa3d0..d0d12255 100644
--- a/Src/Sasi.cpp
+++ b/Src/Sasi.cpp
@@ -30,6 +30,8 @@ Offset Description Access
+03 write irq enable W
*/
+#include
+
#include
#include
diff --git a/Src/Scsi.cpp b/Src/Scsi.cpp
index 40a30452..a0a6637e 100644
--- a/Src/Scsi.cpp
+++ b/Src/Scsi.cpp
@@ -30,6 +30,8 @@ Offset Description Access
+03 write irq enable W
*/
+#include
+
#include
#include
diff --git a/Src/UefState.cpp b/Src/UefState.cpp
index 81583d7b..83f7ef2d 100644
--- a/Src/UefState.cpp
+++ b/Src/UefState.cpp
@@ -21,6 +21,8 @@ Boston, MA 02110-1301, USA.
// UEF savestate code.
+#include
+
#include
#include "UefState.h"
diff --git a/Src/Video.cpp b/Src/Video.cpp
index 6034d253..a2098cef 100644
--- a/Src/Video.cpp
+++ b/Src/Video.cpp
@@ -22,6 +22,8 @@ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
****************************************************************/
+#include
+
#include
#include
diff --git a/Src/Z80Support.cpp b/Src/Z80Support.cpp
index 96e662a7..f06cc253 100644
--- a/Src/Z80Support.cpp
+++ b/Src/Z80Support.cpp
@@ -18,6 +18,8 @@ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
****************************************************************/
+#include
+
#include
#include
From fafeaccb7be2aeca730c474e31c5e1e5ef911c27 Mon Sep 17 00:00:00 2001
From: Steven Inglis
Date: Thu, 8 Aug 2024 16:07:12 +0100
Subject: [PATCH 030/101] Add Wordwise+2 and beebug master rom support.
---
Src/PALRom.cpp | 22 ++++++++++++++++++++++
Src/PALRom.h | 3 ++-
2 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/Src/PALRom.cpp b/Src/PALRom.cpp
index c7fc055e..7f950e62 100644
--- a/Src/PALRom.cpp
+++ b/Src/PALRom.cpp
@@ -181,6 +181,17 @@ static uint8_t wapted_device(int ROMSEL, int offset)
}
}
+static uint8_t wwplusii_device(int ROMSEL, int offset)
+{
+ switch (offset & 0x3fe0)
+ {
+ case 0x3f80: PALRom[ROMSEL].Bank = 0; break;
+ case 0x3fa0: PALRom[ROMSEL].Bank = 1; break;
+ }
+
+ return PALRom[ROMSEL].Rom[(offset & 0x3fff) | (PALRom[ROMSEL].Bank << 14)];
+}
+
uint8_t PALRomRead(int ROMSEL, int offset)
{
switch (PALRom[ROMSEL].Type)
@@ -215,6 +226,9 @@ uint8_t PALRomRead(int ROMSEL, int offset)
case PALRomType::watted:
return wapted_device(ROMSEL, offset);
+
+ case PALRomType::wwplusii:
+ return wwplusii_device(ROMSEL, offset);
}
}
@@ -274,6 +288,14 @@ PALRomType GuessRomType(uint8_t *Rom, uint32_t Size)
{
return PALRomType::watqst;
}
+ else if (strstr(RomName, "WORDWISE-P") && Size == PALROM_32K && Crc == 0x1F560E1F)
+ {
+ return PALRomType::wwplusii;
+ }
+ else if (strstr(RomName, "MASTER ROM") && Size == PALROM_32K && Crc == 0x6F0CB588)
+ {
+ return PALRomType::wwplusii;
+ }
return PALRomType::none;
}
diff --git a/Src/PALRom.h b/Src/PALRom.h
index a487c7dc..9294a9f0 100644
--- a/Src/PALRom.h
+++ b/Src/PALRom.h
@@ -42,7 +42,8 @@ enum class PALRomType {
presabep,
watqst,
watwap,
- watted
+ watted,
+ wwplusii
};
constexpr int PALROM_32K = 32768;
From 5f165b5dc9087e88971aeabc4c98d3d0bfc6e9a0 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Wed, 14 Aug 2024 15:57:16 +0100
Subject: [PATCH 031/101] Changed BeebWin::LoadFDC() to return success or
failure
---
Src/BeebWin.h | 2 +-
Src/BeebWinIo.cpp | 71 ++++++++++++++++++++++++++++++-----------------
2 files changed, 47 insertions(+), 26 deletions(-)
diff --git a/Src/BeebWin.h b/Src/BeebWin.h
index e312afc6..b649ac7a 100644
--- a/Src/BeebWin.h
+++ b/Src/BeebWin.h
@@ -267,7 +267,7 @@ class BeebWin
void SelectTube(TubeDevice Device);
void UpdateTubeMenu();
void SelectFDC();
- void LoadFDC(char *DLLName, bool save);
+ bool LoadFDC(char *DLLName, bool Save);
void UpdateLEDMenu();
void SetDriveControl(unsigned char value);
unsigned char GetDriveControl(void);
diff --git a/Src/BeebWinIo.cpp b/Src/BeebWinIo.cpp
index 5e7fe8fd..58715a77 100644
--- a/Src/BeebWinIo.cpp
+++ b/Src/BeebWinIo.cpp
@@ -1305,63 +1305,84 @@ bool BeebWin::LoadCSWTape(const char *FileName)
}
/****************************************************************************/
-// if DLLName is NULL then FDC setting is read from the registry
+
+// If DLLName is NULL then FDC setting is read from Preferences.cfg
// else the named DLL is read in
-// if save is true then DLL selection is saved in registry
+// If Save is true then DLL selection is saved to Preferences.cfg
-void BeebWin::LoadFDC(char *DLLName, bool save)
+bool BeebWin::LoadFDC(char *DLLName, bool Save)
{
- char CfgName[20];
- sprintf(CfgName, "FDCDLL%d", static_cast(MachineType));
+ Ext1770Result Result = Ext1770Result::Success;
Ext1770Reset();
-
NativeFDC = true;
+ char CfgName[20];
+ sprintf(CfgName, "FDCDLL%d", static_cast(MachineType));
+
if (DLLName == nullptr)
{
if (!m_Preferences.GetStringValue(CfgName, FDCDLL))
+ {
strcpy(FDCDLL, "None");
+ }
+
DLLName = FDCDLL;
}
if (strcmp(DLLName, "None") != 0)
{
- char path[MAX_PATH];
- strcpy(path, DLLName);
- GetDataPath(m_AppPath, path);
+ char DLLPath[MAX_PATH];
+ strcpy(DLLPath, DLLName);
+ GetDataPath(m_AppPath, DLLPath);
- Ext1770Result Result = Ext1770Init(path);
+ Result = Ext1770Init(DLLPath);
if (Result == Ext1770Result::Success)
{
NativeFDC = false; // at last, a working DLL!
}
- else if (Result == Ext1770Result::LoadFailed)
- {
- Report(MessageType::Error, "Unable to load FDD Extension Board DLL\nReverting to native 8271");
- strcpy(DLLName, "None");
- }
- else // if (Result == InvalidDLL)
+ else
{
- Report(MessageType::Error, "Invalid FDD Extension Board DLL\nReverting to native 8271");
+ if (Result == Ext1770Result::LoadFailed)
+ {
+ Report(MessageType::Error, "Unable to load FDD Extension Board DLL\nReverting to native 8271");
+ }
+ else // if (Result == InvalidDLL)
+ {
+ Report(MessageType::Error, "Invalid FDD Extension Board DLL\nReverting to native 8271");
+ }
+
strcpy(DLLName, "None");
}
}
- if (save)
- {
- m_Preferences.SetStringValue(CfgName, DLLName);
- }
-
// Set menu options
CheckMenuItem(IDM_8271, NativeFDC);
CheckMenuItem(IDM_FDC_DLL, !NativeFDC);
- DisplayCycles = 7000000;
+ if (Result == Ext1770Result::Success)
+ {
+ if (Save)
+ {
+ m_Preferences.SetStringValue(CfgName, DLLName);
+ }
+
+ if (NativeFDC || MachineType == Model::Master128)
+ {
+ DisplayCycles = 0;
+ }
+ else
+ {
+ DisplayCycles = 7000000;
+ }
- if (NativeFDC || MachineType == Model::Master128)
- DisplayCycles = 0;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
}
void BeebWin::SetDriveControl(unsigned char Value)
From d1e54169ae67f4918865a76ba4da43fb7be8ea5e Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Wed, 14 Aug 2024 22:42:59 +0100
Subject: [PATCH 032/101] Disable rounded corners on Windows 11
The previous change only affected the main BeebEm window.
This change disables rounded corners for most dialog boxes.
---
Src/BeebEm.vcxproj | 2 +
Src/BeebEm.vcxproj.filters | 6 ++
Src/BeebWin.cpp | 51 ++++------------
Src/BeebWin.h | 1 -
Src/Debug.cpp | 3 +
Src/Dialog.cpp | 37 ++----------
Src/Dialog.h | 2 -
Src/SelectKeyDialog.cpp | 3 +
Src/TapeControlDialog.cpp | 3 +
Src/UserKeyboardDialog.cpp | 3 +
Src/UserPortBreakoutBox.cpp | 3 +
Src/WindowUtils.cpp | 113 ++++++++++++++++++++++++++++++++++++
Src/WindowUtils.h | 30 ++++++++++
13 files changed, 181 insertions(+), 76 deletions(-)
create mode 100644 Src/WindowUtils.cpp
create mode 100644 Src/WindowUtils.h
diff --git a/Src/BeebEm.vcxproj b/Src/BeebEm.vcxproj
index 2a0a8e51..c3b4889f 100644
--- a/Src/BeebEm.vcxproj
+++ b/Src/BeebEm.vcxproj
@@ -246,6 +246,7 @@
+
@@ -418,6 +419,7 @@
+
diff --git a/Src/BeebEm.vcxproj.filters b/Src/BeebEm.vcxproj.filters
index 74a08c4e..ae1b13c3 100644
--- a/Src/BeebEm.vcxproj.filters
+++ b/Src/BeebEm.vcxproj.filters
@@ -264,6 +264,9 @@
Source Files
+
+ Source Files
+
Source Files
@@ -572,6 +575,9 @@
Header Files
+
+ Header Files
+
Header Files
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index 09d287ce..cd53a88a 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -106,6 +106,7 @@ using std::max;
#include "UserVia.h"
#include "Version.h"
#include "Video.h"
+#include "WindowUtils.h"
#include "Z80mem.h"
#include "Z80.h"
@@ -374,6 +375,8 @@ BeebWin::BeebWin()
bool BeebWin::Initialise()
{
+ InitWindowUtils();
+
// Parse command line
ParseCommandLine();
bool bFound = FindCommandLineFile(m_CommandLineFileName1);
@@ -700,6 +703,8 @@ void BeebWin::Shutdown()
// Release FDC DLL.
Ext1770Reset();
+
+ ExitWindowUtils();
}
/****************************************************************************/
@@ -1236,6 +1241,9 @@ bool BeebWin::CreateBeebWindow()
return false;
}
+ // Windows 11 draws windows with rounded corners by default,
+ // so we disable them so the Beeb video image isn't affected.
+ // See https://stardot.org.uk/forums/viewtopic.php?f=4&t=26874
DisableRoundedCorners(m_hWnd);
ShowWindow(m_hWnd, nCmdShow); // Show the window
@@ -1246,45 +1254,6 @@ bool BeebWin::CreateBeebWindow()
return true;
}
-/****************************************************************************/
-
-// Windows 11 draws windows with rounded corners by default, so this function
-// disables them, so the Beeb video image isn't affected.
-//
-// See https://stardot.org.uk/forums/viewtopic.php?f=4&t=26874
-
-void BeebWin::DisableRoundedCorners(HWND hWnd)
-{
- HMODULE hDwmApi = LoadLibrary("dwmapi.dll");
-
- if (hDwmApi == nullptr)
- {
- return;
- }
-
- typedef HRESULT (STDAPICALLTYPE* DWM_SET_WINDOW_ATTRIBUTE)(HWND, DWORD, LPCVOID, DWORD);
-
- DWM_SET_WINDOW_ATTRIBUTE DwmSetWindowAttribute = reinterpret_cast(
- GetProcAddress(hDwmApi, "DwmSetWindowAttribute")
- );
-
- if (DwmSetWindowAttribute != nullptr)
- {
- const DWORD DWMWCP_DONOTROUND = 1;
- const DWORD DWMWA_WINDOW_CORNER_PREFERENCE = 33;
- const DWORD CornerPreference = DWMWCP_DONOTROUND;
-
- DwmSetWindowAttribute(
- hWnd,
- DWMWA_WINDOW_CORNER_PREFERENCE,
- &CornerPreference,
- sizeof(CornerPreference)
- );
- }
-
- FreeLibrary(hDwmApi);
-}
-
/****************************************************************************/
void BeebWin::FlashWindow()
{
@@ -6020,7 +5989,9 @@ static LRESULT CALLBACK CBTMessageBox(int nCode, WPARAM wParam, LPARAM lParam)
{
HWND hWnd = (HWND)wParam;
- CenterDialog(mainWin->GethWnd(), hWnd);
+ DisableRoundedCorners(hWnd);
+
+ CentreWindow(mainWin->GethWnd(), hWnd);
}
return CallNextHookEx(hCBTHook, nCode, wParam, lParam);
diff --git a/Src/BeebWin.h b/Src/BeebWin.h
index b649ac7a..b0ee49e4 100644
--- a/Src/BeebWin.h
+++ b/Src/BeebWin.h
@@ -402,7 +402,6 @@ class BeebWin
bool InitClass();
void UpdateOptionsMenu();
bool CreateBeebWindow();
- void DisableRoundedCorners(HWND hWnd);
void FlashWindow();
void CreateBitmap(void);
void InitMenu();
diff --git a/Src/Debug.cpp b/Src/Debug.cpp
index 955448a8..948745cf 100644
--- a/Src/Debug.cpp
+++ b/Src/Debug.cpp
@@ -48,6 +48,7 @@ Boston, MA 02110-1301, USA.
#include "Serial.h"
#include "StringUtils.h"
#include "Tube.h"
+#include "WindowUtils.h"
#include "Z80mem.h"
#include "Z80.h"
@@ -1026,6 +1027,8 @@ void DebugOpenDialog(HINSTANCE hinst, HWND /* hwndMain */)
hCurrentDialog = hwndDebug;
hCurrentAccelTable = haccelDebug;
+
+ DisableRoundedCorners(hwndDebug);
ShowWindow(hwndDebug, SW_SHOW);
hwndInfo = GetDlgItem(hwndDebug, IDC_DEBUGINFO);
diff --git a/Src/Dialog.cpp b/Src/Dialog.cpp
index 98fab3db..64b5cc3e 100644
--- a/Src/Dialog.cpp
+++ b/Src/Dialog.cpp
@@ -23,6 +23,7 @@ Boston, MA 02110-1301, USA.
#include
#include "Dialog.h"
+#include "WindowUtils.h"
/****************************************************************************/
@@ -65,7 +66,9 @@ INT_PTR CALLBACK Dialog::sDlgProc(HWND hwnd,
dialog = reinterpret_cast(lParam);
dialog->m_hwnd = hwnd;
- CenterDialog(dialog->m_hwndParent, hwnd);
+ DisableRoundedCorners(hwnd);
+
+ CentreWindow(dialog->m_hwndParent, hwnd);
}
else
{
@@ -134,35 +137,3 @@ void Dialog::EnableDlgItem(int nID, bool bEnable)
}
/****************************************************************************/
-
-void CenterDialog(HWND hWndParent, HWND hWnd)
-{
- RECT rcParent;
- GetWindowRect(hWndParent, &rcParent);
-
- RECT rcDialog;
- GetWindowRect(hWnd, &rcDialog);
-
- RECT rc;
- CopyRect(&rc, &rcParent);
-
- // Offset the owner and dialog box rectangles so that right and bottom
- // values represent the width and height, and then offset the owner again
- // to discard space taken up by the dialog box.
-
- OffsetRect(&rcDialog, -rcDialog.left, -rcDialog.top);
- OffsetRect(&rc, -rc.left, -rc.top);
- OffsetRect(&rc, -rcDialog.right, -rcDialog.bottom);
-
- // The new position is the sum of half the remaining space and the owner's
- // original position.
-
- SetWindowPos(hWnd,
- HWND_TOP,
- rcParent.left + (rc.right / 2),
- rcParent.top + (rc.bottom / 2),
- 0, 0, // Ignores size arguments.
- SWP_NOSIZE);
-}
-
-/****************************************************************************/
diff --git a/Src/Dialog.h b/Src/Dialog.h
index ce394b1b..707e8829 100644
--- a/Src/Dialog.h
+++ b/Src/Dialog.h
@@ -64,6 +64,4 @@ class Dialog
HWND m_hwnd;
};
-void CenterDialog(HWND hWndParent, HWND hWnd);
-
#endif
diff --git a/Src/SelectKeyDialog.cpp b/Src/SelectKeyDialog.cpp
index e838f52b..228f3063 100644
--- a/Src/SelectKeyDialog.cpp
+++ b/Src/SelectKeyDialog.cpp
@@ -29,6 +29,7 @@ Boston, MA 02110-1301, USA.
#include "Main.h"
#include "Messages.h"
#include "Resource.h"
+#include "WindowUtils.h"
/****************************************************************************/
@@ -76,6 +77,8 @@ bool SelectKeyDialog::Open()
if (m_hwnd != nullptr)
{
+ DisableRoundedCorners(m_hwnd);
+
EnableWindow(m_hwndParent, FALSE);
return true;
diff --git a/Src/TapeControlDialog.cpp b/Src/TapeControlDialog.cpp
index e23a8263..4e695e47 100644
--- a/Src/TapeControlDialog.cpp
+++ b/Src/TapeControlDialog.cpp
@@ -27,6 +27,7 @@ Boston, MA 02110-1301, USA.
#include "Main.h"
#include "Resource.h"
#include "Serial.h"
+#include "WindowUtils.h"
// Tape control dialog box variables
std::vector TapeMap;
@@ -48,6 +49,8 @@ void TapeControlOpenDialog(HINSTANCE hinst, HWND /* hwndMain */)
hwndTapeControl = CreateDialog(hinst, MAKEINTRESOURCE(IDD_TAPECONTROL),
NULL, TapeControlDlgProc);
hCurrentDialog = hwndTapeControl;
+
+ DisableRoundedCorners(hwndTapeControl);
ShowWindow(hwndTapeControl, SW_SHOW);
hwndMap = GetDlgItem(hwndTapeControl, IDC_TAPE_CONTROL_MAP);
diff --git a/Src/UserKeyboardDialog.cpp b/Src/UserKeyboardDialog.cpp
index c10c1f38..9c8088c4 100644
--- a/Src/UserKeyboardDialog.cpp
+++ b/Src/UserKeyboardDialog.cpp
@@ -33,6 +33,7 @@ Boston, MA 02110-1301, USA.
#include "Messages.h"
#include "Resource.h"
#include "SelectKeyDialog.h"
+#include "WindowUtils.h"
static void SetKeyColour(COLORREF aColour);
static void SelectKeyMapping(HWND hwnd, UINT ctrlID, HWND hwndCtrl);
@@ -86,6 +87,8 @@ bool UserKeyboardDialog(HWND hwndParent)
if (hwndUserKeyboard != nullptr)
{
+ DisableRoundedCorners(hwndUserKeyboard);
+
EnableWindow(hwndParent, FALSE);
return true;
diff --git a/Src/UserPortBreakoutBox.cpp b/Src/UserPortBreakoutBox.cpp
index fbc86de3..3650c3b8 100644
--- a/Src/UserPortBreakoutBox.cpp
+++ b/Src/UserPortBreakoutBox.cpp
@@ -27,6 +27,7 @@ Boston, MA 02110-1301, USA.
#include "Resource.h"
#include "SelectKeyDialog.h"
#include "UserVia.h"
+#include "WindowUtils.h"
/****************************************************************************/
@@ -75,6 +76,8 @@ bool UserPortBreakoutDialog::Open()
if (m_hwnd != nullptr)
{
+ DisableRoundedCorners(m_hwnd);
+
hCurrentDialog = m_hwnd;
return true;
}
diff --git a/Src/WindowUtils.cpp b/Src/WindowUtils.cpp
new file mode 100644
index 00000000..e314f62d
--- /dev/null
+++ b/Src/WindowUtils.cpp
@@ -0,0 +1,113 @@
+/****************************************************************
+BeebEm - BBC Micro and Master 128 Emulator
+Copyright (C) 2024 Chris Needham
+
+This program 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.
+
+This program 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 this program; if not, write to the Free
+Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
+****************************************************************/
+
+#include
+
+#include "WindowUtils.h"
+
+/****************************************************************************/
+
+typedef HRESULT(STDAPICALLTYPE* DWM_SET_WINDOW_ATTRIBUTE)(HWND, DWORD, LPCVOID, DWORD);
+
+static HMODULE hDwmApi = nullptr;
+static DWM_SET_WINDOW_ATTRIBUTE DwmSetWindowAttribute = nullptr;
+
+/****************************************************************************/
+
+void InitWindowUtils()
+{
+ hDwmApi = LoadLibrary("dwmapi.dll");
+
+ if (hDwmApi != nullptr)
+ {
+ DwmSetWindowAttribute = reinterpret_cast(
+ GetProcAddress(hDwmApi, "DwmSetWindowAttribute")
+ );
+ }
+}
+
+/****************************************************************************/
+
+void ExitWindowUtils()
+{
+ if (hDwmApi != nullptr)
+ {
+ FreeLibrary(hDwmApi);
+
+ hDwmApi = nullptr;
+ DwmSetWindowAttribute = nullptr;
+ }
+}
+
+/****************************************************************************/
+
+void CentreWindow(HWND hWndParent, HWND hWnd)
+{
+ if (hWndParent == nullptr || hWnd == nullptr)
+ {
+ return;
+ }
+
+ RECT rcParent;
+ GetWindowRect(hWndParent, &rcParent);
+
+ RECT rcWindow;
+ GetWindowRect(hWnd, &rcWindow);
+
+ RECT rc;
+ CopyRect(&rc, &rcParent);
+
+ // Offset the owner and dialog box rectangles so that right and bottom
+ // values represent the width and height, and then offset the owner again
+ // to discard space taken up by the dialog box.
+
+ OffsetRect(&rcWindow, -rcWindow.left, -rcWindow.top);
+ OffsetRect(&rc, -rc.left, -rc.top);
+ OffsetRect(&rc, -rcWindow.right, -rcWindow.bottom);
+
+ // The new position is the sum of half the remaining space and the owner's
+ // original position.
+
+ SetWindowPos(hWnd,
+ HWND_TOP,
+ rcParent.left + (rc.right / 2),
+ rcParent.top + (rc.bottom / 2),
+ 0, 0, // Ignores size arguments.
+ SWP_NOSIZE);
+}
+
+/****************************************************************************/
+
+void DisableRoundedCorners(HWND hWnd)
+{
+ if (DwmSetWindowAttribute != nullptr)
+ {
+ const DWORD DWMWCP_DONOTROUND = 1;
+ const DWORD DWMWA_WINDOW_CORNER_PREFERENCE = 33;
+ const DWORD CornerPreference = DWMWCP_DONOTROUND;
+
+ DwmSetWindowAttribute(hWnd,
+ DWMWA_WINDOW_CORNER_PREFERENCE,
+ &CornerPreference,
+ sizeof(CornerPreference));
+ }
+}
+
+/****************************************************************************/
diff --git a/Src/WindowUtils.h b/Src/WindowUtils.h
new file mode 100644
index 00000000..80f04475
--- /dev/null
+++ b/Src/WindowUtils.h
@@ -0,0 +1,30 @@
+/****************************************************************
+BeebEm - BBC Micro and Master 128 Emulator
+Copyright (C) 2024 Chris Needham
+
+This program 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.
+
+This program 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 this program; if not, write to the Free
+Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
+****************************************************************/
+
+#ifndef WINDOW_UTILS_HEADER
+#define WINDOW_UTILS_HEADER
+
+void InitWindowUtils();
+void ExitWindowUtils();
+
+void CentreWindow(HWND hWndParent, HWND hWnd);
+void DisableRoundedCorners(HWND hWnd);
+
+#endif
From 88b8c7e9104122218ed7b72810995bb8311cbaf4 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Thu, 15 Aug 2024 20:02:53 +0100
Subject: [PATCH 033/101] Fixed LoadHardwarePreferences() and
LoadTubePreferences()
---
Src/BeebWin.h | 4 +-
Src/BeebWinPrefs.cpp | 153 ++++++++++++++++++++++++++++++++-----------
2 files changed, 115 insertions(+), 42 deletions(-)
diff --git a/Src/BeebWin.h b/Src/BeebWin.h
index b0ee49e4..cb46f77d 100644
--- a/Src/BeebWin.h
+++ b/Src/BeebWin.h
@@ -580,8 +580,8 @@ class BeebWin
// Preferences
void LoadPreferences();
- void LoadHardwarePreferences();
- void LoadTubePreferences();
+ void LoadHardwarePreferences(int Version);
+ void LoadTubePreferences(int Version);
void LoadWindowPosPreferences(int Version);
void LoadTimingPreferences(int Version);
void LoadDisplayPreferences(int Version);
diff --git a/Src/BeebWinPrefs.cpp b/Src/BeebWinPrefs.cpp
index f345128d..69e144c7 100644
--- a/Src/BeebWinPrefs.cpp
+++ b/Src/BeebWinPrefs.cpp
@@ -306,8 +306,8 @@ void BeebWin::LoadPreferences()
m_PrefsFileName.c_str());
}
- LoadHardwarePreferences();
- LoadTubePreferences();
+ LoadHardwarePreferences(Version);
+ LoadTubePreferences(Version);
LoadWindowPosPreferences(Version);
LoadTimingPreferences(Version);
LoadDisplayPreferences(Version);
@@ -334,13 +334,44 @@ void BeebWin::LoadPreferences()
/****************************************************************************/
-void BeebWin::LoadHardwarePreferences()
+void BeebWin::LoadHardwarePreferences(int Version)
{
- std::string Value;
- m_Preferences.GetStringValue(CFG_MACHINE_TYPE, Value, MachineTypeStr[0]);
+ if (Version >= 3)
+ {
+ std::string Value;
- MachineType = static_cast(FindEnum(Value, MachineTypeStr, 0));
+ m_Preferences.GetStringValue(CFG_MACHINE_TYPE, Value, MachineTypeStr[0]);
+
+ MachineType = static_cast(FindEnum(Value, MachineTypeStr, 0));
+ }
+ else
+ {
+ unsigned char Type = 0;
+
+ if (m_Preferences.GetBinaryValue(CFG_MACHINE_TYPE, &Type, 1))
+ {
+ switch (Type)
+ {
+ case 0:
+ default:
+ MachineType = Model::B;
+ break;
+
+ case 1:
+ MachineType = Model::IntegraB;
+ break;
+
+ case 2:
+ MachineType = Model::BPlus;
+ break;
+
+ case 3:
+ MachineType = Model::Master128;
+ break;
+ }
+ }
+ }
if (!m_Preferences.GetBoolValue(CFG_BASIC_HARDWARE_ONLY, BasicHardwareOnly, false))
{
@@ -361,52 +392,94 @@ void BeebWin::LoadHardwarePreferences()
/****************************************************************************/
-void BeebWin::LoadTubePreferences()
+void BeebWin::LoadTubePreferences(int Version)
{
std::string Value;
- if (m_Preferences.GetStringValue(CFG_TUBE_TYPE, Value, TubeDeviceStr[0]))
+ if (Version >= 3)
{
- TubeType = static_cast(FindEnum(Value, TubeDeviceStr, 0));
+ if (m_Preferences.GetStringValue(CFG_TUBE_TYPE, Value, TubeDeviceStr[0]))
+ {
+ TubeType = static_cast(FindEnum(Value, TubeDeviceStr, 0));
+ }
}
else
{
- // For backwards compatibility with BeebEm 4.14 or earlier.
- bool TubeEnabled;
- bool AcornZ80;
- bool TorchTube;
- bool Tube186Enabled;
- bool ArmTube;
-
- m_Preferences.GetBoolValue(CFG_TUBE_ENABLED_OLD, TubeEnabled, false);
- m_Preferences.GetBoolValue(CFG_TUBE_ACORN_Z80_OLD, AcornZ80, false);
- m_Preferences.GetBoolValue(CFG_TUBE_TORCH_Z80_OLD, TorchTube, false);
- m_Preferences.GetBoolValue(CFG_TUBE_186_OLD, Tube186Enabled, false);
- m_Preferences.GetBoolValue(CFG_TUBE_ARM_OLD, ArmTube, false);
+ unsigned char Type = 0;
- if (TubeEnabled)
- {
- TubeType = TubeDevice::Acorn65C02;
- }
- else if (AcornZ80)
- {
- TubeType = TubeDevice::AcornZ80;
- }
- else if (TorchTube)
- {
- TubeType = TubeDevice::TorchZ80;
- }
- else if (Tube186Enabled)
+ if (m_Preferences.GetBinaryValue(CFG_TUBE_TYPE, &Type, 1))
{
- TubeType = TubeDevice::Master512CoPro;
- }
- else if (ArmTube)
- {
- TubeType = TubeDevice::AcornArm;
+ switch (Type)
+ {
+ case 0:
+ default:
+ TubeType = TubeDevice::None;
+ break;
+
+ case 1:
+ TubeType = TubeDevice::Acorn65C02;
+ break;
+
+ case 2:
+ TubeType = TubeDevice::Master512CoPro;
+ break;
+
+ case 3:
+ TubeType = TubeDevice::AcornZ80;
+ break;
+
+ case 4:
+ TubeType = TubeDevice::TorchZ80;
+ break;
+
+ case 5:
+ TubeType = TubeDevice::AcornArm;
+ break;
+
+ case 6:
+ TubeType = TubeDevice::SprowArm;
+ break;
+ }
}
else
{
- TubeType = TubeDevice::None;
+ // For backwards compatibility with BeebEm 4.14 or earlier.
+ bool TubeEnabled;
+ bool AcornZ80;
+ bool TorchTube;
+ bool Tube186Enabled;
+ bool ArmTube;
+
+ m_Preferences.GetBoolValue(CFG_TUBE_ENABLED_OLD, TubeEnabled, false);
+ m_Preferences.GetBoolValue(CFG_TUBE_ACORN_Z80_OLD, AcornZ80, false);
+ m_Preferences.GetBoolValue(CFG_TUBE_TORCH_Z80_OLD, TorchTube, false);
+ m_Preferences.GetBoolValue(CFG_TUBE_186_OLD, Tube186Enabled, false);
+ m_Preferences.GetBoolValue(CFG_TUBE_ARM_OLD, ArmTube, false);
+
+ if (TubeEnabled)
+ {
+ TubeType = TubeDevice::Acorn65C02;
+ }
+ else if (AcornZ80)
+ {
+ TubeType = TubeDevice::AcornZ80;
+ }
+ else if (TorchTube)
+ {
+ TubeType = TubeDevice::TorchZ80;
+ }
+ else if (Tube186Enabled)
+ {
+ TubeType = TubeDevice::Master512CoPro;
+ }
+ else if (ArmTube)
+ {
+ TubeType = TubeDevice::AcornArm;
+ }
+ else
+ {
+ TubeType = TubeDevice::None;
+ }
}
}
}
From cc66730146c847274859fa914857a8389eb7df92 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Thu, 15 Aug 2024 22:06:30 +0100
Subject: [PATCH 034/101] Fixed ARM coprocessor emulation
See #140
---
Src/Arm.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Src/Arm.cpp b/Src/Arm.cpp
index fa488c8b..a4fd7e3f 100644
--- a/Src/Arm.cpp
+++ b/Src/Arm.cpp
@@ -1215,7 +1215,7 @@ void CArm::run()
{
uint rn = getField(currentInstruction, 16, 19); // base address register
uint rd = getField(currentInstruction, 12, 15); // get register to store
- performDataTransferStoreWord(getRegister(rn) - getDataTransferValueImmediate(), (uint8)getRegisterWithPSRAndPipelining(rd));
+ performDataTransferStoreWord(getRegister(rn) - getDataTransferValueImmediate(), getRegisterWithPSRAndPipelining(rd));
break;
}
// ldr rd, [rn, -imm]
From d9e36f0243b19e2df977e6b88bc896d32206e621 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Thu, 15 Aug 2024 22:39:31 +0100
Subject: [PATCH 035/101] Fixed Edit/Copy command
---
Src/BeebWinIo.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/Src/BeebWinIo.cpp b/Src/BeebWinIo.cpp
index 58715a77..006b0e00 100644
--- a/Src/BeebWinIo.cpp
+++ b/Src/BeebWinIo.cpp
@@ -1573,8 +1573,10 @@ void BeebWin::OnCopy()
TogglePrinter(); // Turn printer back on
UpdatePrinterPortMenu();
- m_PrinterBuffer.resize(5);
+ m_PrinterBuffer.clear();
+ m_ClipboardBuffer.resize(5);
+ m_ClipboardLength = 5;
m_ClipboardBuffer[0] = 2;
m_ClipboardBuffer[1] = 'L';
m_ClipboardBuffer[2] = '.';
From dbf63b47b37892d5119cbf20320a36ee92aea751 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Fri, 16 Aug 2024 19:23:26 +0100
Subject: [PATCH 036/101] Removed unused code from Arm.cpp
---
Src/Arm.cpp | 311 ++++++----------------------------------------------
Src/Arm.h | 71 +++---------
2 files changed, 48 insertions(+), 334 deletions(-)
diff --git a/Src/Arm.cpp b/Src/Arm.cpp
index a4fd7e3f..c643a9df 100644
--- a/Src/Arm.cpp
+++ b/Src/Arm.cpp
@@ -34,7 +34,7 @@ Boston, MA 02110-1301, USA.
#include "Arm.h"
#include "ArmDisassembler.h" // gives access to disassembler
#include "BeebMem.h"
-#include "Log.h"
+#include "DebugTrace.h"
#include "Tube.h"
#include "UefState.h"
@@ -82,55 +82,6 @@ CArm::InitResult CArm::init(const char *ROMPath)
// reset processor state to initial values
reset();
- // reset instruction execution counter
- executionCount = 0;
-
- // ??? profiling usage of different modes
- previousProcessorMode = SVC_MODE;
- modeCounter = 0;
-
- // ??? profiling usage of different exceptions
- if(dynamicProfilingExceptionFreq)
- {
- // resetCounter = 0;
- undefCounter = 0;
- swiCounter = 0;
- prefAbortCounter = 0;
- dataAbortCounter = 0;
- addrExcepCounter = 0;
- irqCounter = 0;
- fiqCounter = 0;
- exceptionLastExecutionCount = 0;
- }
-
- if(dynamicProfilingRegisterUse)
- {
- for(int regNumber=0; regNumber<16; regNumber++)
- {
- registerGotCounter[regNumber] = 0;
- registerSetCounter[regNumber] = 0;
- }
- }
-
- if(dynamicProfilingConditionalExecution)
- {
- for(int condition=0; condition<16; condition++)
- {
- conditionallyExecuted[condition] =0;
- conditionallyNotExecuted[condition] = 0;
- }
- }
-
- if(dynamicProfilingCoprocessorUse)
- {
- lastCopro = 0;
- }
-
- modeTotal[USR_MODE] = 0;
- modeTotal[FIQ_MODE] = 0;
- modeTotal[IRQ_MODE] = 0;
- modeTotal[SVC_MODE] = 0;
-
/////////////////////////////
// set up test environment
/////////////////////////////
@@ -140,9 +91,6 @@ CArm::InitResult CArm::init(const char *ROMPath)
r[15] = 0;
prefetchInvalid = true;
conditionFlags = 0;
- trace = 0;
-
- WriteLog("init_arm()\n");
// load file into test memory
FILE *ROMFile = fopen(ROMPath, "rb");
@@ -160,13 +108,6 @@ CArm::InitResult CArm::init(const char *ROMPath)
memset(ramMemory, 0, 0x400000);
memcpy(ramMemory, romMemory, 0x4000);
- /* uint32 memoryValue = 0;
- for(int x=0; x<4*11; x+=4)
- {
- (void)readWord(x, memoryValue);
- TRACE("%x = %x\n", x, memoryValue);
- } */
-
return InitResult::Success;
}
@@ -175,6 +116,7 @@ void CArm::exec(int count)
uint32 ci;
char disassembly[256];
char addressS[64];
+ static const bool trace = false;
while (count > 0)
{
@@ -190,8 +132,7 @@ void CArm::exec(int count)
Arm_disassemble(pc, ci, disassembly);
sprintf(addressS, "0x%08x : %02x %02x %02x %02x ", pc,
- ci & 0xff, (ci >> 8) & 0xff, (ci >> 16) & 0xff, (ci >> 24) & 0xff );
-
+ ci & 0xff, (ci >> 8) & 0xff, (ci >> 16) & 0xff, (ci >> 24) & 0xff );
}
else
{
@@ -200,23 +141,16 @@ void CArm::exec(int count)
Arm_disassemble(pc - 4, ci, disassembly);
sprintf(addressS, "0x%08x : %02x %02x %02x %02x ", pc - 4,
- ci & 0xff, (ci >> 8) & 0xff, (ci >> 16) & 0xff, (ci >> 24) & 0xff );
+ ci & 0xff, (ci >> 8) & 0xff, (ci >> 16) & 0xff, (ci >> 24) & 0xff );
}
- WriteLog(" r0 = %08x r1 = %08x r2 = %08x r3 = %08x r4 = %08x r5 = %08x r6 = %08x r7 = %08x r8 = %08x : ",
- getRegister(0), getRegister(1), getRegister(2), getRegister(3), getRegister(4),
- getRegister(5), getRegister(6), getRegister(7), getRegister(8));
+ DebugTrace(" r0 = %08x r1 = %08x r2 = %08x r3 = %08x r4 = %08x r5 = %08x r6 = %08x r7 = %08x r8 = %08x : ",
+ getRegister(0), getRegister(1), getRegister(2), getRegister(3), getRegister(4),
+ getRegister(5), getRegister(6), getRegister(7), getRegister(8));
- WriteLog("%s : %08x : %s\n", addressS, val, disassembly);
-
- trace--;
+ DebugTrace("%s : %08x : %s\n", addressS, val, disassembly);
}
- // if ( ((pc & 0xffff) >= 0x1c48) && ((pc & 0xffff) <= 0x1c60) )
- // {
- // trace = 100;
- // }
-
run();
count--;
}
@@ -224,19 +158,6 @@ void CArm::exec(int count)
CArm::~CArm()
{
- // ??? output mode counter info
- //CString modeInfo;
- //modeInfo.Format("usr=%d fiq=%d irq=%d svc=%d \n", modeTotal[USR_MODE], modeTotal[FIQ_MODE], modeTotal[IRQ_MODE], modeTotal[SVC_MODE] );
- //reportFile.WriteString(modeInfo);
-
- if(dynamicProfilingExceptionFreq)
- dynamicProfilingExceptionFrequencyReport();
-
- if(dynamicProfilingRegisterUse)
- dynamicProfilingRegisterUsageReport();
-
- if(dynamicProfilingConditionalExecution)
- dynamicProfilingConditionalExeReport();
}
void CArm::run()
@@ -244,19 +165,6 @@ void CArm::run()
// note, if the while(true) loop is placed inside run() as it may need to be for speed
// then returns after exceptions need to be changed to continues!
- // ??? profile usage of processor modes
- //modeTotal[processorMode]++;
- //modeCounter++;
- //if(previousProcessorMode != processorMode)
- //{
- // CString modeInfo;
- // modeInfo.Format("mode=%d count=%d\n",previousProcessorMode, modeCounter-1);
- // reportFile.WriteString(modeInfo);
- //
- // modeCounter = 0;
- // previousProcessorMode = processorMode;
- //}
-
// has prefetch been invalidated by previously executed instruction
if(prefetchInvalid)
{
@@ -285,12 +193,6 @@ void CArm::run()
return;
}
- // increment total instruction executed counter
- executionCount++;
-
- if(dynamicProfilingConditionalExecution)
- dynamicProfilingConditionalExe(currentInstruction);
-
// instruction condition codes match PSR so that instruction should be executed
if( executeConditionally(currentInstruction) )
{
@@ -571,11 +473,6 @@ void CArm::run()
case 0x1A:
{
setDestination( getDataProcessingRegisterOperand2() );
-
- // ??? remove keepRunning - for simple code only
- // checks for mov pc,r14
- //if(currentInstruction == 0xE1A0F00E)
- // keepRunning = false;
break;
}
// movS rd, rn, rm
@@ -2699,9 +2596,9 @@ void CArm::run()
break;
}
- default : // ??? DISPLAY ERROR MESSAGE - I'VE MISSED OUT AN INSTRUCTION CASE
- WriteLog("ERROR UNKNOWN OPCODE %02x\n", getField(currentInstruction, 20, 27) );
- break;
+ default: // ??? DISPLAY ERROR MESSAGE - I'VE MISSED OUT AN INSTRUCTION CASE
+ DebugTrace("ERROR UNKNOWN OPCODE %02x\n", getField(currentInstruction, 20, 27));
+ break;
} // end instruction decoding switch
} // end conditional execution
@@ -2735,7 +2632,7 @@ void CArm::run()
{
if (processorMode != FIQ_MODE)
{
-// WriteLog("Entering FIQ Mode\n");
+ // DebugTrace("Entering FIQ Mode\n");
exceptionFastInterruptRequest();
}
}
@@ -2743,7 +2640,7 @@ void CArm::run()
{
if (processorMode != IRQ_MODE)
{
-// WriteLog("Entering IRQ Mode\n");
+ // DebugTrace("Entering IRQ Mode\n");
exceptionInterruptRequest();
}
}
@@ -2751,7 +2648,7 @@ void CArm::run()
{
if (processorMode != IRQ_MODE)
{
-// WriteLog("Entering IRQ Mode\n");
+ // DebugTrace("Entering IRQ Mode\n");
exceptionInterruptRequest();
}
}
@@ -3623,7 +3520,7 @@ inline bool CArm::performDataTransferLoadWord(uint32 address, uint32 &destinatio
// in ARM610 datasheet and tested on Risc PC.
if( address & 3 )
{
- WriteLog("LoadWord from non word aligned address %08x, pc = %08x\n", address, pc);
+ DebugTrace("LoadWord from non word aligned address %08x, pc = %08x\n", address, pc);
destination = rorOperator(destination, (address & 3)<<3 );
}
@@ -3710,12 +3607,12 @@ inline bool CArm::readWord(uint32 address, uint32& destination)
if ((address & ~0x1f) == 0x1000000)
{
-// WriteLog("Read word from tube %08x, reg %d\n", address, (address & 0x1c) >> 2);
+ // DebugTrace("Read word from tube %08x, reg %d\n", address, (address & 0x1c) >> 2);
destination = 0xff;
return true;
}
- if ( (address >= 0x3000000) && (address < 0x3004000) )
+ if (address >= 0x3000000 && address < 0x3004000)
{
value |= romMemory[(address & 0x3fff)];
value |= romMemory[(address & 0x3fff) +1]<<8;
@@ -3725,8 +3622,10 @@ inline bool CArm::readWord(uint32 address, uint32& destination)
return true;
}
- WriteLog("Bad ARM read word from %08x\n", address);
+ DebugTrace("Bad ARM read word from %08x\n", address);
+
destination = 0xff;
+
return false;
}
@@ -3743,11 +3642,12 @@ inline bool CArm::writeWord(uint32 address, uint32 data)
if ((address & ~0x1f) == 0x1000000)
{
-// WriteLog("Write word %08x to tube %08x, reg %d\n", data, address, (address & 0x1c) >> 2);
+ // DebugTrace("Write word %08x to tube %08x, reg %d\n", data, address, (address & 0x1c) >> 2);
return true;
}
- WriteLog("Bad ARM write word %08x to %08x\n", data, address);
+ DebugTrace("Bad ARM write word %08x to %08x\n", data, address);
+
return false;
}
@@ -3766,7 +3666,7 @@ inline bool CArm::readByte(uint32 address, uint8 &destination)
if ((address & ~0x1f) == 0x1000000)
{
destination = ReadTubeFromParasiteSide((address & 0x1c) >> 2);
-// WriteLog("Read byte from tube %08x, reg %d returned %d\n", address, (address & 0x1c) >> 2, destination);
+ // DebugTrace("Read byte from tube %08x, reg %d returned %d\n", address, (address & 0x1c) >> 2, destination);
return true;
}
@@ -3777,8 +3677,10 @@ inline bool CArm::readByte(uint32 address, uint8 &destination)
return true;
}
- WriteLog("Bad ARM read byte from %08x\n", address);
+ DebugTrace("Bad ARM read byte from %08x\n", address);
+
destination = 0xff;
+
return false;
}
@@ -3786,40 +3688,18 @@ inline bool CArm::writeByte(uint32 address, uint8 value)
{
if (address < 0x1000000)
{
-
-/*
- if ( ( (value & 0xff) == 0) && (address == 0xc501) )
- {
-
- uint32 val;
- readWord(0xc500, val);
-
- WriteLog("Write 0 to 0xc501 - %08x\n", val);
- trace = 10;
- }
-*/
-
ramMemory[(address & 0x3fffff)] = value & 0xff;
-
-// if ((value & 0xff) == 255)
-// {
-// WriteLog("Write byte %02x to %08x\n", value, address);
-// trace = 1;
-// }
-
return true;
}
if ((address & ~0x1f) == 0x1000000)
{
-// WriteLog("Write byte %02x (%c) to tube %08x, reg %d\n", value,
-// ((value & 127) > 31) && ((value & 127) != 127) ? value & 127 : '.',
-// address, (address & 0x1c) >> 2);
- WriteTubeFromParasiteSide((address & 0x1c) >> 2, value);
- return TRUE;
+ WriteTubeFromParasiteSide((address & 0x1c) >> 2, value);
+ return true;
}
- WriteLog("Bad ARM write byte %02x to %08x\n", value, address);
+ DebugTrace("Bad ARM write byte %02x to %08x\n", value, address);
+
return false;
}
@@ -4375,9 +4255,6 @@ inline void CArm::setProcessorStatusFlags(uint32 mask, uint32 value)
// if it's r15 then don't update PSR but do invalidate the prefetch
inline void CArm::setRegisterWithPrefetch(uint regNumber, uint32 value)
{
- if(dynamicProfilingRegisterUse)
- dynamicProfilingRegisterUsage(regNumber, false);
-
// if r15 then only adjust PC (not PSR as well)
if(regNumber == 15)
{
@@ -4394,27 +4271,18 @@ inline void CArm::setRegisterWithPrefetch(uint regNumber, uint32 value)
// plain accessor method for registers, adjusts PSR if r15 etc.
inline void CArm::setRegister(uint regNumber, uint32 value)
{
- if(dynamicProfilingRegisterUse)
- dynamicProfilingRegisterUsage(regNumber, false);
-
r[regNumber] = value;
}
// get the plain value of a register (without psr if r15)
inline uint32 CArm::getRegister(uint regNumber)
{
- if(dynamicProfilingRegisterUse)
- dynamicProfilingRegisterUsage(regNumber, true);
-
return r[regNumber];
}
// get the value of a register (with psr if r15)
inline uint32 CArm::getRegisterWithPSR(uint regNumber)
{
- if(dynamicProfilingRegisterUse)
- dynamicProfilingRegisterUsage(regNumber, true);
-
if(regNumber == 15)
{
return ( r[15] | getProcessorStatusRegister() );
@@ -4428,9 +4296,6 @@ inline uint32 CArm::getRegisterWithPSR(uint regNumber)
// get the value of a register (if r15 then +4 for pipelining effect)
inline uint32 CArm::getRegisterWithPipelining(uint regNumber)
{
- if(dynamicProfilingRegisterUse)
- dynamicProfilingRegisterUsage(regNumber, true);
-
if(regNumber == 15)
{
return r[15] + 4;
@@ -4444,9 +4309,6 @@ inline uint32 CArm::getRegisterWithPipelining(uint regNumber)
// get the value of a register (if r15 then with PSR and +4 for pipelining effect)
inline uint32 CArm::getRegisterWithPSRAndPipelining(uint regNumber)
{
- if(dynamicProfilingRegisterUse)
- dynamicProfilingRegisterUsage(regNumber, true);
-
if(regNumber == 15)
{
return ( r[15] | getProcessorStatusRegister() ) + 4;
@@ -4618,9 +4480,6 @@ inline void CArm::exceptionReset()
setProcessorStatusFlags(M1_FLAG | M2_FLAG | I_FLAG | F_FLAG, SVC_MODE | I_FLAG | F_FLAG );
// jump to reset vector
setRegisterWithPrefetch(15, RESET_VECTOR);
-
- if(dynamicProfilingExceptionFreq)
- dynamicProfilingExceptionFrequency("Reset Exception", resetCounter);
}
// note, in each of these cases, calling setProcessorStatusFlags can cahnge the processor
@@ -4642,9 +4501,6 @@ inline void CArm::exceptionUndefinedInstruction()
// jump to address exception vector
setRegisterWithPrefetch(15, UNDEFINED_INSTRUCTION_VECTOR);
-
- if(dynamicProfilingExceptionFreq)
- dynamicProfilingExceptionFrequency("Undefined Instruction Exception", undefCounter);
}
inline void CArm::exceptionSoftwareInterrupt()
@@ -4661,9 +4517,6 @@ inline void CArm::exceptionSoftwareInterrupt()
// jump to address exception vector
setRegisterWithPrefetch(15, SOFTWARE_INTERRUPT_VECTOR);
-
- if(dynamicProfilingExceptionFreq)
- dynamicProfilingExceptionFrequency("SWI Exception", swiCounter);
}
inline void CArm::exceptionPrefetchAbort()
@@ -4680,9 +4533,6 @@ inline void CArm::exceptionPrefetchAbort()
// jump to vector
setRegisterWithPrefetch(15, PREFETCH_ABORT_VECTOR);
-
- if(dynamicProfilingExceptionFreq)
- dynamicProfilingExceptionFrequency("Prefetch Abort Exception", prefAbortCounter);
}
inline void CArm::exceptionDataAbort()
@@ -4699,10 +4549,6 @@ inline void CArm::exceptionDataAbort()
// jump to vector
setRegisterWithPrefetch(15, DATA_ABORT_VECTOR);
-
- if(dynamicProfilingExceptionFreq)
- dynamicProfilingExceptionFrequency("Data Abort Exception", dataAbortCounter);
-
}
inline void CArm::exceptionInterruptRequest()
@@ -4719,9 +4565,6 @@ inline void CArm::exceptionInterruptRequest()
// jump to vector
setRegisterWithPrefetch(15, INTERRUPT_REQUEST_VECTOR);
-
- if(dynamicProfilingExceptionFreq)
- dynamicProfilingExceptionFrequency("IRQ Exception", irqCounter);
}
inline void CArm::exceptionFastInterruptRequest()
@@ -4738,15 +4581,11 @@ inline void CArm::exceptionFastInterruptRequest()
// jump to vector
setRegisterWithPrefetch(15, FAST_INTERRUPT_REQUEST_VECTOR);
-
- if(dynamicProfilingExceptionFreq)
- dynamicProfilingExceptionFrequency("FIQ Exception", fiqCounter);
}
// only occurs on 26 bit architectures
inline void CArm::exceptionAddress()
{
-
// make copy of PSR
uint32 psrCopy = getProcessorStatusRegister();
@@ -4759,9 +4598,6 @@ inline void CArm::exceptionAddress()
// jump to vector
setRegisterWithPrefetch(15, ADDRESS_EXCEPTION_VECTOR);
-
- if(dynamicProfilingExceptionFreq)
- dynamicProfilingExceptionFrequency("Address Exception", addrExcepCounter);
}
//////////////////////////////////////////////////////////////////////
@@ -4805,9 +4641,6 @@ inline bool CArm::coprocessorRegisterTransferRead()
// uint coprocessorNumber = getField(currentInstruction, 8, 11);
- if(dynamicProfilingCoprocessorUse)
- dynamicProfilingCoprocessorUsage(currentInstruction);
-
exceptionUndefinedInstruction();
return false;
}
@@ -4817,9 +4650,6 @@ inline bool CArm::coprocessorDataOperation()
{
// uint coprocessorNumber = getField(currentInstruction, 8, 11);
- if(dynamicProfilingCoprocessorUse)
- dynamicProfilingCoprocessorUsage(currentInstruction);
-
exceptionUndefinedInstruction();
return false;
}
@@ -4827,88 +4657,9 @@ inline bool CArm::coprocessorDataOperation()
// get the coprocessor data transfer immediate offset from the current instruction
inline uint32 CArm::coprocessorDataTransferOffset()
{
- if(dynamicProfilingCoprocessorUse)
- dynamicProfilingCoprocessorUsage(currentInstruction);
-
return (currentInstruction & 0xff) << 2;
}
-//////////////////////////////////////////////////////////////////////
-// Dynamic Profiling routines, for testing ARM feature usage
-//////////////////////////////////////////////////////////////////////
-
-void CArm::dynamicProfilingExceptionFrequency(const char *exceptionName, uint32 &counter)
-{
- WriteLog("%s executionCount=%d\n", exceptionName, executionCount - exceptionLastExecutionCount);
- exceptionLastExecutionCount = executionCount;
- counter++;
-}
-
-void CArm::dynamicProfilingExceptionFrequencyReport()
-{
- WriteLog(">>>>>>>>>> Report Totals\n");
- WriteLog("Reset = %d\n", resetCounter);
- WriteLog("Undefined Instruction = %d\n", undefCounter);
- WriteLog("SWI = %d\n", swiCounter);
- WriteLog("prefetch abort = %d\n", prefAbortCounter);
- WriteLog("data abort = %d\n", dataAbortCounter);
- WriteLog("address exception = %d\n", addrExcepCounter);
- WriteLog("IRQ exception = %d\n", irqCounter);
- WriteLog("FIQ exception = %d\n", fiqCounter);
-}
-
-void CArm::dynamicProfilingRegisterUsage(uint regNumber, bool get)
-{
- if(get)
- {
- registerGotCounter[regNumber]++;
- }
- else
- {
- registerSetCounter[regNumber]++;
- }
-}
-
-void CArm::dynamicProfilingRegisterUsageReport()
-{
- WriteLog("Register usage profiling");
-
- for(int regNumber=0; regNumber<16; regNumber++)
- {
- WriteLog("r%d got=%d set=%d\n", regNumber, registerGotCounter[regNumber], registerSetCounter[regNumber] );
- }
-}
-
-void CArm::dynamicProfilingConditionalExe(uint32 instruction)
-{
- if( executeConditionally(instruction) )
- {
- // executed
- conditionallyExecuted[ getField(instruction, 28, 31) ]++;
- }
- else
- {
- // not executed
- conditionallyNotExecuted[ getField(instruction, 28, 31) ]++;
- }
-}
-
-void CArm::dynamicProfilingConditionalExeReport()
-{
- WriteLog("Conditional Execution profiling");
-
- for(int condition=0; condition<16; condition++)
- {
- WriteLog("cond=%d exe=%d not=%d\n", condition, conditionallyExecuted[condition], conditionallyNotExecuted[condition] );
- }
-}
-
-void CArm::dynamicProfilingCoprocessorUsage(uint32 instruction)
-{
- WriteLog("copro number=%d instructions=%d\n", getField(instruction, 8, 11), executionCount - lastCopro);
- lastCopro = executionCount;
-}
-
void CArm::SaveState(FILE* SUEF)
{
UEFWrite32(pc, SUEF);
diff --git a/Src/Arm.h b/Src/Arm.h
index ea8ea7a4..6295927e 100644
--- a/Src/Arm.h
+++ b/Src/Arm.h
@@ -72,26 +72,17 @@ typedef unsigned int Reg;
typedef unsigned int Word;
typedef unsigned char Byte;
-// dynamic profiling options
-constexpr bool dynamicProfilingExceptionFreq = false;
-constexpr bool dynamicProfilingRegisterUse = false;
-constexpr bool dynamicProfilingConditionalExecution = false;
-constexpr bool dynamicProfilingCoprocessorUse = true;
-
class CArm
{
public:
- enum class InitResult {
+ enum class InitResult
+ {
Success,
FileNotFound
};
// functions
public:
- void dynamicProfilingCoprocessorUsage(uint32 currentInstruction);
- void dynamicProfilingExceptionFrequencyReport();
- void dynamicProfilingExceptionFrequency(const char *exceptionName, uint32& counter);
-
uint32 pc;
inline void performBranch();
@@ -212,54 +203,26 @@ class CArm
void LoadState(FILE* SUEF);
private:
- uint32 lastCopro; // num of instructions executed since last copro instruction profiled
- void dynamicProfilingConditionalExe(uint32 currentInstruction);
- void dynamicProfilingConditionalExeReport();
- void dynamicProfilingRegisterUsageReport();
- void dynamicProfilingRegisterUsage(uint regNumber, bool get);
-
// variables
- uint processorMode; // in bits 0-1
- uint interruptDisableFlag; // in bit 26
- uint fastInterruptDisableFlag; // in bit 27
- uint conditionFlags; // store NZCV flags in bits 0-3
- uint trace;
+ uint processorMode; // in bits 0-1
+ uint interruptDisableFlag; // in bit 26
+ uint fastInterruptDisableFlag; // in bit 27
+ uint conditionFlags; // store NZCV flags in bits 0-3
- bool prefetchInvalid;
- uint32 prefetchInstruction;
- uint32 currentInstruction;
- uint32 r[16]; // current bank of registers
- uint32 usrR[16]; // user mode registers
- uint32 svcR[16]; // supervisor mode registers
- uint32 irqR[16]; // interrupt mode registers
- uint32 fiqR[16]; // fast interrupt mode registers
- uint32 *curR[4]; // pointer to current mode's registers
+ bool prefetchInvalid;
+ uint32 prefetchInstruction;
+ uint32 currentInstruction;
+ uint32 r[16]; // current bank of registers
+ uint32 usrR[16]; // user mode registers
+ uint32 svcR[16]; // supervisor mode registers
+ uint32 irqR[16]; // interrupt mode registers
+ uint32 fiqR[16]; // fast interrupt mode registers
+ uint32 *curR[4]; // pointer to current mode's registers
// look up tables
uint32 immediateCarry[4096];
uint32 immediateValue[4096];
- // TEST ENVIRONMENT VARIABLES
- uint8 romMemory[0x4000]; // 16 KBytes of rom memory
- uint8 ramMemory[0x400000]; // 4 MBytes of ram memory
- bool keepRunning; // keep calling run()
-// CArmDecoder decoder; // create instance of disassembler
- uint32 executionCount;
- uint32 previousProcessorMode;
- uint32 modeCounter;
- uint32 modeTotal[4];
- uint32 resetCounter;
- uint32 undefCounter;
- uint32 swiCounter;
- uint32 prefAbortCounter;
- uint32 dataAbortCounter;
- uint32 addrExcepCounter;
- uint32 irqCounter;
- uint32 fiqCounter;
- uint32 exceptionLastExecutionCount;
- uint32 registerSetCounter[16];
- uint32 registerGotCounter[16];
- uint32 conditionallyExecuted[16];
- uint32 conditionallyNotExecuted[16];
- // END OF TEST ENVIRONMENT VARIABLES
+ uint8 romMemory[0x4000]; // 16 KBytes of rom memory
+ uint8 ramMemory[0x400000]; // 4 MBytes of ram memory
};
From 6436e38a270f08b5a558ad2577fd4096b492ada0 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 24 Aug 2024 11:43:07 +0100
Subject: [PATCH 037/101] Improved ARM coprocessor
- Added armModel variable, to enable ARM1, ARM2, or ARM3
instructions
- Added check for ROM file size
---
Help/armcopro.html | 60 ++++++++++++++++++++++++++++---
Src/Arm.cpp | 56 +++++++++++++++++++----------
Src/Arm.h | 79 +++++++++++++++++++++++++++++------------
Src/ArmDisassembler.cpp | 64 +++++++++++++++++++++------------
Src/ArmDisassembler.h | 24 +++----------
Src/BeebWin.cpp | 26 ++++++++------
Src/BeebWinPrefs.cpp | 1 -
Src/UefState.cpp | 4 +--
Src/Video.cpp | 2 +-
9 files changed, 214 insertions(+), 102 deletions(-)
diff --git a/Help/armcopro.html b/Help/armcopro.html
index 673dd23f..9e80150d 100644
--- a/Help/armcopro.html
+++ b/Help/armcopro.html
@@ -57,17 +57,26 @@ Acorn ARM Second Processor
Processor on the Hardware → Second
Processor menu. The ARM Second Processor has no operating system
but relies on a sideways ROM to provide a command line prompt to the
- user. Once you see the A* prompt, type
+
+
+ Once you see the A* prompt, type *HELP SUPERVISOR to see what in-built commands are
available.
The ARM Evaluation System came with 6 discs full of software. Disc 3 is
- included in the 'DiscIms' folder which contains ARM Basic. Load the
- armdisc3.adl disc image (ensuring you are in ADFS mode), type *MOUNT 4 and *AB to load
- ARM Basic. The remaining disc images plus a hard disc image containing
+ included in the DiscIms folder which contains
+ ARM Basic. Load the armdisc3.adl disc image
+ (ensuring you are in ADFS mode), type *MOUNT 4
+ and *AB to load ARM Basic. Type HELP . to list all BASIC commands.
+
+
+
+ The remaining disc images plus a hard disc image containing
all 6 disc images can be downloaded from Jon Welch's website:
Acorn ARM
Discs .
@@ -92,6 +101,47 @@
Acorn ARM Second Processor
site as well. If you have any manuals or other disc images that Jon
does not have feel free to send them to Jon to add to the library.
+
+ To use the hard disc image:
+
+
+
+ While BeebEm is not running,
+ download
+ the hard disc image and copy the file scsi1.dat
+ to your DiscIms folder.
+
+
+ Start BeebEm.
+
+
+ Type CONFIGURE TUBE to use the ARM
+ co-processor by default.
+
+
+ Type CONFIGURE FILE 13 to make ADFS the
+ default filing system (so you can read the disc image).
+
+
+ Type CONFIGURE MODE 0 to switch to a
+ screen mode with smaller font.
+
+
+ Press Ctrl + F12 to reset the machine so
+ configuration changes take effect (presses Ctrl +
+ Break in the emulator).
+
+
+ Type MOUNT 1 to mount the hard disc image
+ as drive 1.
+
+
+
+
+ To make sure all your settings are saved for next time so you don't
+ have to repeat the process, select the Options →
+ Save Preferences menu item.
+
diff --git a/Src/Arm.cpp b/Src/Arm.cpp
index c643a9df..224b64e5 100644
--- a/Src/Arm.cpp
+++ b/Src/Arm.cpp
@@ -32,7 +32,7 @@ Boston, MA 02110-1301, USA.
#include
#include "Arm.h"
-#include "ArmDisassembler.h" // gives access to disassembler
+#include "ArmDisassembler.h" // gives access to disassembler
#include "BeebMem.h"
#include "DebugTrace.h"
#include "Tube.h"
@@ -46,8 +46,14 @@ CArm::CArm()
{
}
+CArm::~CArm()
+{
+}
+
CArm::InitResult CArm::init(const char *ROMPath)
{
+ armModel = 1; // Emulate ARM1 instructions only.
+
// set up pointers to each bank of registers
curR[USR_MODE] = usrR;
curR[SVC_MODE] = svcR;
@@ -86,27 +92,32 @@ CArm::InitResult CArm::init(const char *ROMPath)
// set up test environment
/////////////////////////////
- processorMode = USR_MODE;
processorMode = SVC_MODE;
r[15] = 0;
prefetchInvalid = true;
conditionFlags = 0;
- // load file into test memory
+ // load ROM file into memory
FILE *ROMFile = fopen(ROMPath, "rb");
if (ROMFile != nullptr)
{
- fread(romMemory, 0x4000, 1, ROMFile);
+ size_t BytesRead = fread(romMemory, 1, ROM_SIZE, ROMFile);
+
fclose(ROMFile);
+
+ if (BytesRead != ROM_SIZE)
+ {
+ return InitResult::InvalidROM;
+ }
}
else
{
return InitResult::FileNotFound;
}
- memset(ramMemory, 0, 0x400000);
- memcpy(ramMemory, romMemory, 0x4000);
+ memset(ramMemory, 0, RAM_SIZE);
+ memcpy(ramMemory, romMemory, ROM_SIZE);
return InitResult::Success;
}
@@ -156,10 +167,6 @@ void CArm::exec(int count)
}
}
-CArm::~CArm()
-{
-}
-
void CArm::run()
{
// note, if the while(true) loop is placed inside run() as it may need to be for speed
@@ -205,7 +212,7 @@ void CArm::run()
// mul rd, rm, rs
case 0x00:
{
- if( isExtendedInstruction(currentInstruction) )
+ if (armModel >= 2 && isExtendedInstruction(currentInstruction))
{
// mul rd, rm, rs
performMul();
@@ -221,7 +228,7 @@ void CArm::run()
// mulS rd, rm, rs
case 0x01:
{
- if( isExtendedInstruction(currentInstruction) )
+ if (armModel >= 2 && isExtendedInstruction(currentInstruction))
{
// mulS rd, rm, rs
performMulS();
@@ -237,7 +244,7 @@ void CArm::run()
// mla rd, rm, rs
case 0x02:
{
- if( isExtendedInstruction(currentInstruction) )
+ if (armModel >= 2 && isExtendedInstruction(currentInstruction))
{
// mla rd, rm, rs
performMla();
@@ -253,7 +260,7 @@ void CArm::run()
// mlaS rd, rm, rs
case 0x03:
{
- if( isExtendedInstruction(currentInstruction) )
+ if (armModel >= 2 && isExtendedInstruction(currentInstruction))
{
// mlaS rd, rm, rs
performMlaS();
@@ -342,7 +349,7 @@ void CArm::run()
// swp rd, rn, rm
case 0x10:
{
- if( isExtendedInstruction(currentInstruction) )
+ if (armModel >= 3 && isExtendedInstruction(currentInstruction))
{
// swp rd, rn, rm
performSingleDataSwapWord();
@@ -402,7 +409,7 @@ void CArm::run()
// cmp rd, rn, rm - NOP
case 0x14:
{
- if( isExtendedInstruction(currentInstruction) )
+ if (armModel >= 3 && isExtendedInstruction(currentInstruction))
{
// swp rd, rn, rm
performSingleDataSwapByte();
@@ -630,6 +637,7 @@ void CArm::run()
// tst rn, imm
(void)andOperatorS( getDataProcessingImmediateOperand1(), getDataProcessingImmediateOperand2S() );
}
+ break;
}
// teq rd, rn, imm
case 0x32:
@@ -2550,7 +2558,6 @@ void CArm::run()
coprocessorDataOperation();
}
break;
- break;
}
// software interrupt
@@ -2658,7 +2665,7 @@ void CArm::run()
// instruction templates
//////////////////////////////////////////////////////////////////////
-// tests for bit patter 1001 in bits 4-7 to determine the difference
+// tests for bit pattern 1001 in bits 4-7 to determine the difference
// between a data processing instruction and a MUL or SWP instruction
inline bool CArm::isExtendedInstruction(uint32 instruction)
{
@@ -4692,9 +4699,11 @@ void CArm::SaveState(FILE* SUEF)
}
UEFWriteBuf(ramMemory, sizeof(ramMemory), SUEF);
+
+ UEFWrite8((unsigned char)armModel, SUEF);
}
-void CArm::LoadState(FILE* SUEF)
+void CArm::LoadState(FILE* SUEF, int Version)
{
pc = UEFRead32(SUEF);
processorMode = UEFRead8(SUEF);
@@ -4726,4 +4735,13 @@ void CArm::LoadState(FILE* SUEF)
}
UEFReadBuf(ramMemory, sizeof(ramMemory), SUEF);
+
+ if (Version >= 15)
+ {
+ armModel = UEFRead8(SUEF);
+ }
+ else
+ {
+ armModel = 1;
+ }
}
diff --git a/Src/Arm.h b/Src/Arm.h
index 6295927e..ae8ec088 100644
--- a/Src/Arm.h
+++ b/Src/Arm.h
@@ -18,6 +18,9 @@ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
****************************************************************/
+#ifndef ARM_HEADER
+#define ARM_HEADER
+
//////////////////////////////////////////////////////////////////////
// Arm.h: declarations for the CArm class.
// Part of Tarmac
@@ -46,7 +49,7 @@ constexpr unsigned int INTR_FLAGS = I_FLAG | F_FLAG;
constexpr unsigned int PSR_MASK = N_FLAG | Z_FLAG | C_FLAG | V_FLAG | INTR_FLAGS | MODE_FLAGS;
constexpr unsigned int PC_MASK = ~PSR_MASK;
-// processor modes for bits 0-1 of PSR
+// processor modes for bits 0-1 of PSR (MODE_FLAGS)
constexpr int USR_MODE = 0; // user
constexpr int FIQ_MODE = 1; // fast interrupt request
constexpr int IRQ_MODE = 2; // interrupt request
@@ -78,12 +81,22 @@ class CArm
enum class InitResult
{
Success,
- FileNotFound
+ FileNotFound,
+ InvalidROM
};
// functions
public:
- uint32 pc;
+ // construct / destruct
+ CArm();
+ virtual ~CArm();
+
+ // control
+ InitResult init(const char* ROMPath);
+ void exec(int count);
+ void run(void);
+ void reset();
+
inline void performBranch();
// logic
@@ -145,12 +158,12 @@ class CArm
inline uint32 getDataTransferValueRegister();
inline uint32 getDataTransferValueImmediate();
// for data processing instructions operands
- inline uint32 getDataProcessingImmediateOperand1(); // read op1 when op2 is immediate
- inline uint32 getDataProcessingImmediateOperand2(); // read op2 when op2 is immediate
- inline uint32 getDataProcessingImmediateOperand2S(); // read op2 when op2 is immediate and S is set
- inline uint32 getDataProcessingRegisterOperand1(); // read op1 when op2 is register
- inline uint32 getDataProcessingRegisterOperand2(); // read op2 when op2 is register
- inline uint32 getDataProcessingRegisterOperand2S(); // read op2 when op2 is register and S is set
+ inline uint32 getDataProcessingImmediateOperand1(); // read op1 when op2 is immediate
+ inline uint32 getDataProcessingImmediateOperand2(); // read op2 when op2 is immediate
+ inline uint32 getDataProcessingImmediateOperand2S(); // read op2 when op2 is immediate and S is set
+ inline uint32 getDataProcessingRegisterOperand1(); // read op1 when op2 is register
+ inline uint32 getDataProcessingRegisterOperand2(); // read op2 when op2 is register
+ inline uint32 getDataProcessingRegisterOperand2S(); // read op2 when op2 is register and S is set
// register access
inline uint32 getRegister(uint regNumber);
@@ -184,26 +197,17 @@ class CArm
inline void exceptionAddress();
inline void exceptionDataAbort();
- // control
- InitResult init(const char *ROMPath);
- void exec(int count);
- void run(void);
- void reset();
-
// utility
static inline bool getNegative(uint32 value);
static inline bool getPositive(uint32 value);
static inline bool isExtendedInstruction(uint32 instruction);
- // construct / destruct
- CArm();
- virtual ~CArm();
-
void SaveState(FILE* SUEF);
- void LoadState(FILE* SUEF);
+ void LoadState(FILE* SUEF, int Version);
private:
// variables
+ uint32 pc;
uint processorMode; // in bits 0-1
uint interruptDisableFlag; // in bit 26
uint fastInterruptDisableFlag; // in bit 27
@@ -219,10 +223,39 @@ class CArm
uint32 fiqR[16]; // fast interrupt mode registers
uint32 *curR[4]; // pointer to current mode's registers
+ // config
+
+ // ARM model (1, 2, or 3)
+ //
+ // ARM1: https://en.wikichip.org/wiki/acorn/microarchitectures/arm1
+ // https://en.wikichip.org/wiki/arm/armv1
+ //
+ // ARM2: https://en.wikichip.org/wiki/acorn/microarchitectures/arm2
+ // https://en.wikichip.org/wiki/arm/armv2
+ //
+ // Adds CDP - Coprocessor data process
+ // LDC - Load to coprocessor
+ // STC - Store from coprocessor
+ // MCR - Move to coprocessor
+ // MRC - Move from coprocessor
+ // MUL - Multiplication
+ // MLA - Multiplication and accumulate
+ //
+ // ARM3: https://en.wikichip.org/wiki/acorn/microarchitectures/arm3
+ //
+ // Adds SWP - Swap word memory-register
+
+ int armModel;
+
// look up tables
uint32 immediateCarry[4096];
uint32 immediateValue[4096];
-
- uint8 romMemory[0x4000]; // 16 KBytes of rom memory
- uint8 ramMemory[0x400000]; // 4 MBytes of ram memory
+
+ static constexpr int ROM_SIZE = 0x4000; // 16 KBytes of rom memory
+ static constexpr int RAM_SIZE = 0x400000; // 4 MBytes of ram memory
+
+ uint8 romMemory[ROM_SIZE];
+ uint8 ramMemory[RAM_SIZE];
};
+
+#endif
diff --git a/Src/ArmDisassembler.cpp b/Src/ArmDisassembler.cpp
index 35831d62..99ff7978 100644
--- a/Src/ArmDisassembler.cpp
+++ b/Src/ArmDisassembler.cpp
@@ -30,6 +30,26 @@ Boston, MA 02110-1301, USA.
#include "ArmDisassembler.h"
+static const char* decodeRegisterList(uint32 instruction);
+static char* decodeSingleDataSwap(uint32 address, uint32 instruction, char* buff);
+static char* decodeMultiply(uint32 address, uint32 instruction, char* buff);
+static const char* decodeConditionCode(uint32 instruction);
+static char* decodeSoftwareInterrupt(uint32 address, uint32 instruction, char* buff);
+static char* decodeCoProRegTransferOrDataOperation(uint32 address, uint32 instruction, char* buff);
+static char* decodeCoProDTPostIndex(uint32 address, uint32 instruction, char* buff);
+static char* decodeCoProDTPreIndex(uint32 address, uint32 instruction, char* buff);
+static char* decodeBranchWithLink(uint32 address, uint32 instruction, char* buff);
+static char* decodeBranch(uint32 address, uint32 instruction, char* buff);
+static char* decodeBlockDTPreIndex(uint32 address, uint32 instruction, char* buff);
+static char* decodeBlockDTPostIndex(uint32 address, uint32 instruction, char* buff);
+static char* decodeSingleDTRegOffsetPreIndex(uint32 address, uint32 instruction, char* buff);
+static char* decodeSingleDTRegOffsetPostIndex(uint32 address, uint32 instruction, char* buff);
+static char* decodeSingleDTImmOffsetPreIndex(uint32 address, uint32 instruction, char* buff);
+static char* decodeSingleDTImmOffsetPostIndex(uint32 address, uint32 instruction, char* buff);
+static char* decodeDataProcessing(uint32 address, uint32 instruction, char* buff);
+static char* decodeSingleDataSwapOrDataProcessing(uint32 address, uint32 instruction, char* buff);
+static char* decodeMultiplyOrDataProcessing(uint32 address, uint32 instruction, char* buff);
+
char *Arm_disassemble(uint32 address, uint32 instruction, char *buff)
{
// decode based on bits 24 - 27 of instruction
@@ -57,7 +77,7 @@ char *Arm_disassemble(uint32 address, uint32 instruction, char *buff)
return buff;
}
-char *decodeMultiplyOrDataProcessing(uint32 address, uint32 instruction, char *buff)
+static char *decodeMultiplyOrDataProcessing(uint32 address, uint32 instruction, char *buff)
{
// check for bit pattern 1001 in bits 4-7
if( getField(instruction, 4,7) == 0x09 )
@@ -72,7 +92,7 @@ char *decodeMultiplyOrDataProcessing(uint32 address, uint32 instruction, char *b
}
}
-char *decodeSingleDataSwapOrDataProcessing(uint32 address, uint32 instruction, char *buff)
+static char *decodeSingleDataSwapOrDataProcessing(uint32 address, uint32 instruction, char *buff)
{
// check for bit pattern 0000 1001 in bits 4-11
if( getField(instruction, 4,11) == 0x09)
@@ -87,7 +107,7 @@ char *decodeSingleDataSwapOrDataProcessing(uint32 address, uint32 instruction, c
}
}
-char *decodeDataProcessing(uint32 /* address */, uint32 instruction, char *buff)
+static char *decodeDataProcessing(uint32 /* address */, uint32 instruction, char *buff)
{
// table of opcode names
static const char* const opcodeNames[16] =
@@ -240,7 +260,7 @@ char *decodeDataProcessing(uint32 /* address */, uint32 instruction, char *buff)
return buff;
}
-char *decodeSingleDTImmOffsetPostIndex(uint32 /* address */, uint32 instruction, char *buff)
+static char *decodeSingleDTImmOffsetPostIndex(uint32 /* address */, uint32 instruction, char *buff)
{
// decode whether load or store from bit 20
if( getBit(instruction, 20) )
@@ -299,7 +319,7 @@ char *decodeSingleDTImmOffsetPostIndex(uint32 /* address */, uint32 instruction,
return buff;
}
-char *decodeSingleDTImmOffsetPreIndex(uint32 /* address */, uint32 instruction, char *buff)
+static char *decodeSingleDTImmOffsetPreIndex(uint32 /* address */, uint32 instruction, char *buff)
{
// decode whether load or store from bit 20
if( getBit(instruction, 20) )
@@ -361,7 +381,7 @@ char *decodeSingleDTImmOffsetPreIndex(uint32 /* address */, uint32 instruction,
return buff;
}
-char *decodeSingleDTRegOffsetPostIndex(uint32 /* address */, uint32 instruction, char *buff)
+static char *decodeSingleDTRegOffsetPostIndex(uint32 /* address */, uint32 instruction, char *buff)
{
// decode whether load or store from bit 20
if( getBit(instruction, 20) )
@@ -443,7 +463,7 @@ char *decodeSingleDTRegOffsetPostIndex(uint32 /* address */, uint32 instruction,
return buff;
}
-char *decodeSingleDTRegOffsetPreIndex(uint32 /* address */, uint32 instruction, char *buff)
+static char *decodeSingleDTRegOffsetPreIndex(uint32 /* address */, uint32 instruction, char *buff)
{
// decode whether load or store from bit 20
if( getBit(instruction, 20) )
@@ -493,7 +513,7 @@ char *decodeSingleDTRegOffsetPreIndex(uint32 /* address */, uint32 instruction,
uint32 imm = getField(instruction, 7,11);
// table of shift mnemonics
- const char* const shiftMnemonic[4] =
+ static const char* const shiftMnemonic[4] =
{
"lsl", "lsr", "asr", "ror"
};
@@ -530,7 +550,7 @@ char *decodeSingleDTRegOffsetPreIndex(uint32 /* address */, uint32 instruction,
return buff;
}
-char *decodeBlockDTPostIndex(uint32 /* address */, uint32 instruction, char *buff)
+static char *decodeBlockDTPostIndex(uint32 /* address */, uint32 instruction, char *buff)
{
// decode whether to load from or store to memory from bit 20
if( getBit(instruction, 20) )
@@ -594,7 +614,7 @@ char *decodeBlockDTPostIndex(uint32 /* address */, uint32 instruction, char *buf
return buff;
}
-char *decodeBlockDTPreIndex(uint32 /* address */, uint32 instruction, char *buff)
+static char *decodeBlockDTPreIndex(uint32 /* address */, uint32 instruction, char *buff)
{
// decode whether to load from or store to memory from bit 20
if( getBit(instruction, 20) )
@@ -660,7 +680,7 @@ char *decodeBlockDTPreIndex(uint32 /* address */, uint32 instruction, char *buff
static char registerList[128];
-const char *decodeRegisterList(uint32 instruction)
+static const char *decodeRegisterList(uint32 instruction)
{
uint8 run = 0;
char registerNumber[12];
@@ -747,7 +767,7 @@ const char *decodeRegisterList(uint32 instruction)
}
// ??? absolute address generated is wrong
-char *decodeBranch(uint32 address, uint32 instruction, char *buff)
+static char *decodeBranch(uint32 address, uint32 instruction, char *buff)
{
strcpy(buff, "b");
@@ -778,7 +798,7 @@ char *decodeBranch(uint32 address, uint32 instruction, char *buff)
return buff;
}
-char *decodeBranchWithLink(uint32 address, uint32 instruction, char *buff)
+static char *decodeBranchWithLink(uint32 address, uint32 instruction, char *buff)
{
strcpy(buff, "bl");
@@ -809,30 +829,30 @@ char *decodeBranchWithLink(uint32 address, uint32 instruction, char *buff)
return buff;
}
-char *decodeCoProDTPreIndex(uint32 /* address */, uint32 /* instruction */, char * buff)
+static char *decodeCoProDTPreIndex(uint32 /* address */, uint32 /* instruction */, char * buff)
{
strcpy(buff, "CO PRO DATA TRANSFER PRE INDEX");
return buff;
}
-char *decodeCoProDTPostIndex(uint32 /* address */, uint32 /* instruction */, char * buff)
+static char *decodeCoProDTPostIndex(uint32 /* address */, uint32 /* instruction */, char * buff)
{
strcpy(buff, "CO PRO DATA TRANSFER POST INDEX");
return buff;
}
-char *decodeCoProRegTransferOrDataOperation(uint32 /* address */, uint32 /* instruction */, char * buff)
+static char *decodeCoProRegTransferOrDataOperation(uint32 /* address */, uint32 /* instruction */, char * buff)
{
strcpy(buff, "CO PRO REG TRANSFER OR DATA OP");
return buff;
}
-char *decodeSoftwareInterrupt(uint32 /* address */, uint32 instruction, char *buff)
+static char *decodeSoftwareInterrupt(uint32 /* address */, uint32 instruction, char *buff)
{
strcpy(buff, "swi");
strcat(buff, decodeConditionCode(instruction));
- const char* const swiList[] = {
+ static const char* const swiList[] = {
"WriteC", "WriteS", "Write0", "NewLine", "ReadC", "CLI", "Byte",
"Word", "File", "Args", "BGet", "BPut", "Multiple", "Open",
"ReadLine", "Control", "GetEnv", "Exit", "SetEnv",
@@ -869,7 +889,7 @@ char *decodeSoftwareInterrupt(uint32 /* address */, uint32 instruction, char *bu
return buff;
}
-char *decodeMultiply(uint32 /* address */, uint32 instruction, char *buff)
+static char *decodeMultiply(uint32 /* address */, uint32 instruction, char *buff)
{
bool accumulate = false;
@@ -926,7 +946,7 @@ char *decodeMultiply(uint32 /* address */, uint32 instruction, char *buff)
return buff;
}
-char *decodeSingleDataSwap(uint32 /* address */, uint32 instruction, char *buff)
+static char *decodeSingleDataSwap(uint32 /* address */, uint32 instruction, char *buff)
{
// word or byte quantity, byte if bit 22 set
if(getBit(instruction,22))
@@ -962,10 +982,10 @@ char *decodeSingleDataSwap(uint32 /* address */, uint32 instruction, char *buff)
return buff;
}
-const char *decodeConditionCode(uint32 instruction)
+static const char *decodeConditionCode(uint32 instruction)
{
// table of condition code meanings, note that as convention dictates, AL is blank
- const char* const conditionCodes[16] =
+ static const char* const conditionCodes[16] =
{
"eq", "ne", "cs", "cc",
"mi", "pl", "vs", "vc",
diff --git a/Src/ArmDisassembler.h b/Src/ArmDisassembler.h
index 65b993e4..9bd6e8ee 100644
--- a/Src/ArmDisassembler.h
+++ b/Src/ArmDisassembler.h
@@ -18,6 +18,9 @@ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
****************************************************************/
+#ifndef ARMDISASSEMBLER_HEADER
+#define ARMDISASSEMBLER_HEADER
+
//////////////////////////////////////////////////////////////////////
// ArmDisassembler.h: declarations for the CArmDisassembler class.
// Part of Tarmac
@@ -28,22 +31,5 @@ Boston, MA 02110-1301, USA.
#include "TarmacGlobals.h"
char *Arm_disassemble(uint32 address, uint32 instruction, char *buff);
-const char *decodeRegisterList(uint32 instruction);
-char *decodeSingleDataSwap(uint32 address, uint32 instruction, char *buff);
-char *decodeMultiply(uint32 address, uint32 instruction, char *buff);
-const char *decodeConditionCode(uint32 instruction);
-char *decodeSoftwareInterrupt(uint32 address, uint32 instruction, char *buff);
-char *decodeCoProRegTransferOrDataOperation(uint32 address, uint32 instruction, char *buff);
-char *decodeCoProDTPostIndex(uint32 address, uint32 instruction, char *buff);
-char *decodeCoProDTPreIndex(uint32 address, uint32 instruction, char *buff);
-char *decodeBranchWithLink(uint32 address, uint32 instruction, char *buff);
-char *decodeBranch(uint32 address, uint32 instruction, char *buff);
-char *decodeBlockDTPreIndex(uint32 address, uint32 instruction, char *buff);
-char *decodeBlockDTPostIndex(uint32 address, uint32 instruction, char *buff);
-char *decodeSingleDTRegOffsetPreIndex(uint32 address, uint32 instruction, char *buff);
-char *decodeSingleDTRegOffsetPostIndex(uint32 address, uint32 instruction, char *buff);
-char *decodeSingleDTImmOffsetPreIndex(uint32 address, uint32 instruction, char *buff);
-char *decodeSingleDTImmOffsetPostIndex(uint32 address, uint32 instruction, char *buff);
-char *decodeDataProcessing(uint32 address, uint32 instruction, char *buff);
-char *decodeSingleDataSwapOrDataProcessing(uint32 address, uint32 instruction, char *buff);
-char *decodeMultiplyOrDataProcessing(uint32 address, uint32 instruction, char *buff);
+
+#endif
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index cd53a88a..73b4c477 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -1012,19 +1012,25 @@ void BeebWin::CreateArmCoPro()
CArm::InitResult Result = arm->init(ArmROMPath);
- switch (Result) {
- case CArm::InitResult::FileNotFound:
- Report(MessageType::Error, "ARM co-processor ROM file not found:\n %s",
- ArmROMPath);
+ if (Result != CArm::InitResult::Success)
+ {
+ DestroyArmCoPro();
- DestroyArmCoPro();
+ TubeType = TubeDevice::None;
+ UpdateTubeMenu();
- TubeType = TubeDevice::None;
- UpdateTubeMenu();
- break;
+ switch (Result)
+ {
+ case CArm::InitResult::FileNotFound:
+ Report(MessageType::Error, "ARM co-processor ROM file not found:\n %s",
+ ArmROMPath);
+ break;
- case CArm::InitResult::Success:
- break;
+ case CArm::InitResult::InvalidROM:
+ Report(MessageType::Error, "Invalid ARM co-processor ROM file (expected 4096 bytes):\n %s",
+ ArmROMPath);
+ break;
+ }
}
}
diff --git a/Src/BeebWinPrefs.cpp b/Src/BeebWinPrefs.cpp
index 69e144c7..c891a1dd 100644
--- a/Src/BeebWinPrefs.cpp
+++ b/Src/BeebWinPrefs.cpp
@@ -336,7 +336,6 @@ void BeebWin::LoadPreferences()
void BeebWin::LoadHardwarePreferences(int Version)
{
-
if (Version >= 3)
{
std::string Value;
diff --git a/Src/UefState.cpp b/Src/UefState.cpp
index 83f7ef2d..47b7f0ee 100644
--- a/Src/UefState.cpp
+++ b/Src/UefState.cpp
@@ -286,7 +286,7 @@ UEFStateResult SaveUEFState(const char *FileName)
fprintf(UEFState,"UEF File!");
fputc(0, UEFState); // UEF Header
- const unsigned char UEFMinorVersion = 14;
+ const unsigned char UEFMinorVersion = 15;
const unsigned char UEFMajorVersion = 0;
fputc(UEFMinorVersion, UEFState);
@@ -506,7 +506,7 @@ UEFStateResult LoadUEFState(const char *FileName)
break;
case 0x0479:
- arm->LoadState(UEFState);
+ arm->LoadState(UEFState, Version);
break;
case 0x047A:
diff --git a/Src/Video.cpp b/Src/Video.cpp
index a2098cef..7b6f7a62 100644
--- a/Src/Video.cpp
+++ b/Src/Video.cpp
@@ -1711,7 +1711,7 @@ void LoadVideoUEF(FILE *SUEF, int Version)
if (VideoULA_ControlReg & 2) HSyncModifier=12;
if (Version >= 13)
- {
+ {
VideoState.Addr = UEFRead32(SUEF);
VideoState.StartAddr = UEFRead32(SUEF);
VideoState.PixmapLine = UEFRead32(SUEF);
From 0fb1f57d8e1ba48ccb2c9508b3e8a83245bcf022 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 24 Aug 2024 11:45:23 +0100
Subject: [PATCH 038/101] Refactored RTC emulation
Removed dupicate code and added comments
---
Src/Rtc.cpp | 108 +++++++++++++++++++++++++++-------------------------
1 file changed, 57 insertions(+), 51 deletions(-)
diff --git a/Src/Rtc.cpp b/Src/Rtc.cpp
index 77018a56..ec35e50c 100644
--- a/Src/Rtc.cpp
+++ b/Src/Rtc.cpp
@@ -146,7 +146,7 @@ Boston, MA 02110-1301, USA.
// | 63 | 3F | |
// +----+----+-----------------------------------------------------------------+
-// Master 128 MC146818AP Real-Time Clock and RAM
+// Offset from PC clock (seconds)
static time_t RTCTimeOffset = 0;
struct CMOSType
@@ -218,6 +218,10 @@ unsigned char* pCMOS = nullptr;
/*-------------------------------------------------------------------------*/
+// Convert the contents of the RTC registers to a time_t, applying a
+// correction based on the PC clock because the RTC only stores a two-digit
+// year.
+
static time_t RTCConvertClock()
{
struct tm Base;
@@ -238,13 +242,14 @@ static time_t RTCConvertClock()
Base.tm_hour = BCDToBin(pCMOS[4]);
Base.tm_mday = BCDToBin(pCMOS[7]);
Base.tm_mon = BCDToBin(pCMOS[8]) - 1;
- Base.tm_year = BCDToBin(pCMOS[9]);
+ Base.tm_year = BCDToBin(pCMOS[9]); // Years since 1900
}
Base.tm_wday = -1;
Base.tm_yday = -1;
Base.tm_isdst = -1;
+ // Add the century from the PC clock.
time_t SysTime;
time(&SysTime);
struct tm *CurTime = localtime(&SysTime);
@@ -255,6 +260,34 @@ static time_t RTCConvertClock()
/*-------------------------------------------------------------------------*/
+static void RTCSetTimeAndDateRegisters(const struct tm* pTime)
+{
+ if (pCMOS[RTC146818_REG_B] & RTC146818_REG_B_BINARY)
+ {
+ // Update with current time values in binary format
+ pCMOS[0] = static_cast(pTime->tm_sec);
+ pCMOS[2] = static_cast(pTime->tm_min);
+ pCMOS[4] = static_cast(pTime->tm_hour);
+ pCMOS[6] = static_cast(pTime->tm_wday + 1);
+ pCMOS[7] = static_cast(pTime->tm_mday);
+ pCMOS[8] = static_cast(pTime->tm_mon + 1);
+ pCMOS[9] = static_cast(pTime->tm_year % 100);
+ }
+ else
+ {
+ // Update with current time values in BCD format
+ pCMOS[0] = BCD(static_cast(pTime->tm_sec));
+ pCMOS[2] = BCD(static_cast(pTime->tm_min));
+ pCMOS[4] = BCD(static_cast(pTime->tm_hour));
+ pCMOS[6] = BCD(static_cast(pTime->tm_wday + 1));
+ pCMOS[7] = BCD(static_cast(pTime->tm_mday));
+ pCMOS[8] = BCD(static_cast(pTime->tm_mon + 1));
+ pCMOS[9] = BCD(static_cast(pTime->tm_year % 100));
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+
void RTCInit()
{
// Select CMOS memory
@@ -279,28 +312,11 @@ void RTCInit()
time(&SysTime);
struct tm *CurTime = localtime(&SysTime);
- if (pCMOS[RTC146818_REG_B] & RTC146818_REG_B_BINARY)
- {
- pCMOS[0] = static_cast(CurTime->tm_sec);
- pCMOS[2] = static_cast(CurTime->tm_min);
- pCMOS[4] = static_cast(CurTime->tm_hour);
- pCMOS[6] = static_cast(CurTime->tm_wday + 1);
- pCMOS[7] = static_cast(CurTime->tm_mday);
- pCMOS[8] = static_cast(CurTime->tm_mon + 1);
- pCMOS[9] = static_cast(CurTime->tm_year % 100);
- }
- else
- {
- pCMOS[0] = BCD(static_cast(CurTime->tm_sec));
- pCMOS[2] = BCD(static_cast(CurTime->tm_min));
- pCMOS[4] = BCD(static_cast(CurTime->tm_hour));
- pCMOS[6] = BCD(static_cast(CurTime->tm_wday + 1));
- pCMOS[7] = BCD(static_cast(CurTime->tm_mday));
- pCMOS[8] = BCD(static_cast(CurTime->tm_mon + 1));
- pCMOS[9] = BCD(static_cast(CurTime->tm_year % 100));
- }
+ RTCSetTimeAndDateRegisters(CurTime);
RTCTimeOffset = SysTime - RTCConvertClock();
+
+ DebugTrace("RTCInit: RTCTimeOffset set to %d\n", (int)RTCTimeOffset);
}
/*-------------------------------------------------------------------------*/
@@ -312,28 +328,7 @@ static void RTCUpdate()
SysTime -= RTCTimeOffset;
struct tm *CurTime = localtime(&SysTime);
- if (pCMOS[RTC146818_REG_B] & RTC146818_REG_B_BINARY)
- {
- // Update with current time values in binary format
- pCMOS[0] = static_cast(CurTime->tm_sec);
- pCMOS[2] = static_cast(CurTime->tm_min);
- pCMOS[4] = static_cast(CurTime->tm_hour);
- pCMOS[6] = static_cast(CurTime->tm_wday + 1);
- pCMOS[7] = static_cast(CurTime->tm_mday);
- pCMOS[8] = static_cast(CurTime->tm_mon + 1);
- pCMOS[9] = static_cast(CurTime->tm_year % 100);
- }
- else
- {
- // Update with current time values in BCD format
- pCMOS[0] = BCD(static_cast(CurTime->tm_sec));
- pCMOS[2] = BCD(static_cast(CurTime->tm_min));
- pCMOS[4] = BCD(static_cast(CurTime->tm_hour));
- pCMOS[6] = BCD(static_cast(CurTime->tm_wday + 1));
- pCMOS[7] = BCD(static_cast(CurTime->tm_mday));
- pCMOS[8] = BCD(static_cast(CurTime->tm_mon + 1));
- pCMOS[9] = BCD(static_cast(CurTime->tm_year % 100));
- }
+ RTCSetTimeAndDateRegisters(CurTime);
}
/*-------------------------------------------------------------------------*/
@@ -343,6 +338,8 @@ void RTCChipEnable(bool Enable)
CMOS.ChipEnable = Enable;
}
+/*-------------------------------------------------------------------------*/
+
bool RTCIsChipEnable()
{
return CMOS.ChipEnable;
@@ -365,9 +362,9 @@ void RTCWriteData(unsigned char Value)
if (DebugEnabled)
{
- DebugDisplayTraceF(DebugType::CMOS, true,
- "CMOS: Write address %X value %02X",
- CMOS.Address, Value);
+ DebugDisplayTraceF(DebugType::CMOS, true,
+ "CMOS: Write address %X value %02X",
+ CMOS.Address, Value);
}
// Many thanks to Tom Lees for supplying me with info on the 146818 registers
@@ -375,6 +372,7 @@ void RTCWriteData(unsigned char Value)
if (CMOS.Address <= 0x9)
{
// Clock registers
+ DebugTrace("RTCWriteData: Set register %d to %02X\n", CMOS.Address, Value);
// BCD or binary format?
if (pCMOS[RTC146818_REG_B] & RTC146818_REG_B_BINARY)
@@ -405,6 +403,8 @@ void RTCWriteData(unsigned char Value)
time_t SysTime;
time(&SysTime);
RTCTimeOffset = SysTime - RTCConvertClock();
+
+ DebugTrace("RTCWriteData: RTCTimeOffset set to %d\n", (int)RTCTimeOffset);
}
// Write the value to CMOS anyway
@@ -434,9 +434,9 @@ unsigned char RTCReadData()
if (DebugEnabled)
{
- DebugDisplayTraceF(DebugType::CMOS, true,
- "CMOS: Read address %X value %02X",
- CMOS.Address, Value);
+ DebugDisplayTraceF(DebugType::CMOS, true,
+ "CMOS: Read address %X value %02X",
+ CMOS.Address, Value);
}
DebugTrace("RTC: Read address %02X value %02X\n", CMOS.Address, Value);
@@ -470,6 +470,8 @@ unsigned char RTCGetData(Model model, unsigned char Address)
return CMOS.Register[Index][Address];
}
+/*-------------------------------------------------------------------------*/
+
const unsigned char* RTCGetCMOSData(Model model)
{
const int Index = model == Model::Master128 ? 0 : 1;
@@ -477,9 +479,13 @@ const unsigned char* RTCGetCMOSData(Model model)
return &CMOS.Register[Index][14];
}
+/*-------------------------------------------------------------------------*/
+
void RTCSetCMOSData(Model model, const unsigned char* pData, int Size)
{
const int Index = model == Model::Master128 ? 0 : 1;
memcpy(&CMOS.Register[Index][14], pData, Size);
-}
\ No newline at end of file
+}
+
+/*-------------------------------------------------------------------------*/
From a7dddd8f3f568fdd14daba3f3797cf603332b66c Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 24 Aug 2024 20:01:56 +0100
Subject: [PATCH 039/101] Added more portable file name handling
---
Src/BeebMem.cpp | 32 +++--
Src/BeebWin.cpp | 298 ++++++++++++++++++++++++-----------------
Src/BeebWin.h | 3 +-
Src/BeebWinIo.cpp | 81 ++++++-----
Src/BeebWinPrefs.cpp | 19 ++-
Src/Disc8271.cpp | 9 +-
Src/FileUtils.cpp | 46 ++++++-
Src/FileUtils.h | 2 +
Src/Log.cpp | 9 +-
Src/Master512CoPro.cpp | 12 +-
Src/Sound.cpp | 3 +-
Src/Speech.cpp | 9 +-
Src/StringUtils.cpp | 37 +++++
Src/StringUtils.h | 1 +
Src/Tube.cpp | 7 +-
Src/Z80Support.cpp | 17 ++-
16 files changed, 381 insertions(+), 204 deletions(-)
diff --git a/Src/BeebMem.cpp b/Src/BeebMem.cpp
index ffc5b385..a2d23a99 100644
--- a/Src/BeebMem.cpp
+++ b/Src/BeebMem.cpp
@@ -728,31 +728,33 @@ static void FiddleACCCON(unsigned char newValue) {
}
/*----------------------------------------------------------------------------*/
-static void RomWriteThrough(int Address, unsigned char Value) {
- int bank = 0;
+
+static void RomWriteThrough(int Address, unsigned char Value)
+{
+ int Bank = 0;
// SW RAM board - bank to write to is selected by User VIA
if (SWRAMBoardEnabled)
{
- bank = (UserVIAState.orb & UserVIAState.ddrb) & 0xf;
+ Bank = (UserVIAState.orb & UserVIAState.ddrb) & 0xf;
- if (!RomWritable[bank])
+ if (!RomWritable[Bank])
{
- bank = ROM_BANK_COUNT;
+ Bank = ROM_BANK_COUNT;
}
}
else
{
// Find first writable bank
- while (bank < ROM_BANK_COUNT && !RomWritable[bank])
+ while (Bank < ROM_BANK_COUNT && !RomWritable[Bank])
{
- ++bank;
+ ++Bank;
}
}
- if (bank < ROM_BANK_COUNT)
+ if (Bank < ROM_BANK_COUNT)
{
- Roms[bank][Address - 0x8000] = Value;
+ Roms[Bank][Address - 0x8000] = Value;
}
}
@@ -1185,13 +1187,15 @@ char *ReadRomTitle(int bank, char *Title, int BufSize)
static std::string GetRomFileName(const std::string& RomName)
{
- if (RomName[0] != '\\' && RomName[1] != ':')
+ if (IsRelativePath(RomName.c_str()))
{
- std::string RomFileName = RomPath;
- RomFileName += "BeebFile\\";
- RomFileName += RomName;
+ char PathName[MAX_PATH];
+ strcpy(PathName, mainWin->GetUserDataPath());
+ AppendPath(PathName, "BeebFile");
+ AppendPath(PathName, RomName.c_str());
+ MakePreferredPath(PathName);
- return RomFileName;
+ return PathName;
}
else
{
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index 73b4c477..4f9f3be1 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -264,20 +264,21 @@ BeebWin::BeebWin()
// Get the applications path - used for non-user files
char AppPath[MAX_PATH];
- char AppDrive[_MAX_DRIVE];
- char AppDir[_MAX_DIR];
GetModuleFileName(nullptr, AppPath, MAX_PATH);
- _splitpath(AppPath, AppDrive, AppDir, nullptr, nullptr);
- _makepath(m_AppPath, AppDrive, AppDir, nullptr, nullptr);
+ GetPathFromFileName(AppPath, m_AppPath, MAX_PATH);
// Read user data path from registry
if (!RegGetStringValue(HKEY_CURRENT_USER, CFG_REG_KEY, "UserDataFolder",
m_UserDataPath, MAX_PATH))
{
// Default user data path to a sub-directory in My Docs
- if (SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, m_UserDataPath) == NOERROR)
+ if (SHGetFolderPath(NULL,
+ CSIDL_PERSONAL,
+ NULL,
+ SHGFP_TYPE_CURRENT,
+ m_UserDataPath) == NOERROR)
{
- strcat(m_UserDataPath, "\\BeebEm\\");
+ AppendPath(m_UserDataPath, "BeebEm");
}
}
@@ -389,7 +390,9 @@ bool BeebWin::Initialise()
// Check that user data directory exists
if (!CheckUserDataPath(!m_CustomData))
+ {
return false;
+ }
LoadPreferences();
@@ -433,6 +436,7 @@ bool BeebWin::Initialise()
INITCOMMONCONTROLSEX cc;
cc.dwSize = sizeof(cc);
cc.dwICC = ICC_LISTVIEW_CLASSES;
+
if (!InitCommonControlsEx(&cc))
{
return false;
@@ -486,15 +490,15 @@ bool BeebWin::Initialise()
}
}
- char fontFilename[MAX_PATH];
- strcpy(fontFilename, GetAppPath());
- strcat(fontFilename, "teletext.fnt");
+ char FontFilename[MAX_PATH];
+ strcpy(FontFilename, GetAppPath());
+ AppendPath(FontFilename, "Teletext.fnt");
- if (!BuildMode7Font(fontFilename))
+ if (!BuildMode7Font(FontFilename))
{
Report(MessageType::Error,
"Cannot open Teletext font file:\n %s",
- fontFilename);
+ FontFilename);
return false;
}
@@ -526,7 +530,7 @@ void BeebWin::ApplyPrefs()
strcpy(EconetCfgPath, m_UserDataPath);
strcat(EconetCfgPath, "Econet.cfg");
}
- else if (PathIsRelative(EconetCfgPath))
+ else if (IsRelativePath(EconetCfgPath))
{
char Filename[MAX_PATH];
strcpy(Filename, EconetCfgPath);
@@ -539,7 +543,7 @@ void BeebWin::ApplyPrefs()
strcpy(AUNMapPath, m_UserDataPath);
strcat(AUNMapPath, "AUNMap");
}
- else if (PathIsRelative(AUNMapPath))
+ else if (IsRelativePath(AUNMapPath))
{
char Filename[MAX_PATH];
strcpy(Filename, AUNMapPath);
@@ -556,12 +560,12 @@ void BeebWin::ApplyPrefs()
// Load key maps
char KeyMapPath[MAX_PATH];
- strcpy(KeyMapPath, "Logical.kmap");
- GetDataPath(m_UserDataPath, KeyMapPath);
+ strcpy(KeyMapPath, m_UserDataPath);
+ AppendPath(KeyMapPath, "Logical.kmap");
ReadKeyMap(KeyMapPath, &LogicalKeyMap);
- strcpy(KeyMapPath, "Default.kmap");
- GetDataPath(m_UserDataPath, KeyMapPath);
+ strcpy(KeyMapPath, m_UserDataPath);
+ AppendPath(KeyMapPath, "Default.kmap");
ReadKeyMap(KeyMapPath, &DefaultKeyMap);
InitMenu();
@@ -591,7 +595,7 @@ void BeebWin::ApplyPrefs()
PrinterDisable();
}
- /* Joysticks can only be initialised after the window is created (needs hwnd) */
+ // Joysticks can only be initialised after the window is created (needs hwnd)
if (m_JoystickOption == JoystickOption::Joystick)
InitJoystick();
@@ -1005,10 +1009,11 @@ void BeebWin::CreateArmCoPro()
{
arm = new CArm;
- char ArmROMPath[256];
+ char ArmROMPath[MAX_PATH];
strcpy(ArmROMPath, RomPath);
- strcat(ArmROMPath, "BeebFile/ARMeval_100.rom");
+ AppendPath(ArmROMPath, "BeebFile");
+ AppendPath(ArmROMPath, "ARMeval_100.rom");
CArm::InitResult Result = arm->init(ArmROMPath);
@@ -1048,7 +1053,8 @@ void BeebWin::CreateSprowCoPro()
char SprowROMPath[MAX_PATH];
strcpy(SprowROMPath, RomPath);
- strcat(SprowROMPath, "BeebFile/Sprow.rom");
+ AppendPath(SprowROMPath, "BeebFile");
+ AppendPath(SprowROMPath, "Sprow.rom");
sprow = new CSprowCoPro();
CSprowCoPro::InitResult Result = sprow->Init(SprowROMPath);
@@ -1079,6 +1085,7 @@ void BeebWin::DestroySprowCoPro()
}
/****************************************************************************/
+
void BeebWin::CreateBitmap()
{
if (m_hBitmap != NULL)
@@ -1102,15 +1109,18 @@ void BeebWin::CreateBitmap()
m_bmi.bmiHeader.biClrUsed = 68;
m_bmi.bmiHeader.biClrImportant = 68;
-#ifdef USE_PALETTE
+ #ifdef USE_PALETTE
+
__int16 *pInts = (__int16 *)&m_bmi.bmiColors[0];
for(int i=0; i<12; i++)
pInts[i] = i;
m_hBitmap = CreateDIBSection(m_hDCBitmap, (BITMAPINFO *)&m_bmi, DIB_PAL_COLORS,
- (void**)&m_screen, NULL,0);
-#else
+ (void**)&m_screen, NULL,0);
+
+ #else
+
for (int i = 0; i < 64; ++i)
{
float r = (float)(i & 1);
@@ -1159,7 +1169,8 @@ void BeebWin::CreateBitmap()
m_hBitmap = CreateDIBSection(m_hDCBitmap, (BITMAPINFO *)&m_bmi, DIB_RGB_COLORS,
(void**)&m_screen, NULL,0);
-#endif
+
+ #endif
m_screen_blur = (char *)calloc(m_bmi.bmiHeader.biSizeImage,1);
@@ -1261,6 +1272,7 @@ bool BeebWin::CreateBeebWindow()
}
/****************************************************************************/
+
void BeebWin::FlashWindow()
{
::FlashWindow(m_hWnd, TRUE);
@@ -2035,6 +2047,7 @@ void BeebWin::InitJoystick()
}
/****************************************************************************/
+
void BeebWin::ScaleJoystick(unsigned int x, unsigned int y)
{
if (m_JoystickOption == JoystickOption::Joystick)
@@ -3671,8 +3684,6 @@ void BeebWin::UpdateOptionsMenu()
void BeebWin::HandleCommand(UINT MenuID)
{
- char TmpPath[256];
-
SetSound(SoundState::Muted);
bool StayMuted = false;
@@ -4266,11 +4277,14 @@ void BeebWin::HandleCommand(UINT MenuID)
break;
}
- case IDM_VIEWREADME:
- strcpy(TmpPath, m_AppPath);
- strcat(TmpPath, "Help\\index.html");
- ShellExecute(m_hWnd, NULL, TmpPath, NULL, NULL, SW_SHOWNORMAL);
+ case IDM_VIEWREADME: {
+ char HelpPath[MAX_PATH];
+ strcpy(HelpPath, m_AppPath);
+ AppendPath(HelpPath, "Help");
+ AppendPath(HelpPath, "index.html");
+ ShellExecute(m_hWnd, NULL, HelpPath, NULL, NULL, SW_SHOWNORMAL);
break;
+ }
case IDM_EXIT:
PostMessage(m_hWnd, WM_CLOSE, 0, 0);
@@ -5069,20 +5083,20 @@ void BeebWin::ParseCommandLine()
while (i < __argc)
{
// Params with no arguments
- if (_stricmp(__argv[i], "-DisMenu") == 0)
+ if (StrCaseCmp(__argv[i], "-DisMenu") == 0)
{
m_DisableMenu = true;
}
- else if (_stricmp(__argv[i], "-NoAutoBoot") == 0)
+ else if (StrCaseCmp(__argv[i], "-NoAutoBoot") == 0)
{
m_NoAutoBoot = true;
}
- else if (_stricmp(__argv[i], "-StartPaused") == 0)
+ else if (StrCaseCmp(__argv[i], "-StartPaused") == 0)
{
m_StartPaused = true;
m_Paused = true;
}
- else if (_stricmp(__argv[i], "-FullScreen") == 0)
+ else if (StrCaseCmp(__argv[i], "-FullScreen") == 0)
{
m_StartFullScreen = true;
}
@@ -5095,8 +5109,8 @@ void BeebWin::ParseCommandLine()
{
invalid = false;
- const bool Data = _stricmp(__argv[i], "-Data") == 0;
- const bool CustomData = _stricmp(__argv[i], "-CustomData") == 0;
+ const bool Data = StrCaseCmp(__argv[i], "-Data") == 0;
+ const bool CustomData = StrCaseCmp(__argv[i], "-CustomData") == 0;
if (Data || CustomData)
{
@@ -5121,23 +5135,23 @@ void BeebWin::ParseCommandLine()
m_CustomData = true;
}
}
- else if (_stricmp(__argv[i], "-Prefs") == 0)
+ else if (StrCaseCmp(__argv[i], "-Prefs") == 0)
{
m_PrefsFileName = __argv[++i];
}
- else if (_stricmp(__argv[i], "-Roms") == 0)
+ else if (StrCaseCmp(__argv[i], "-Roms") == 0)
{
strcpy(RomFile, __argv[++i]);
}
- else if (_stricmp(__argv[i], "-EconetCfg") == 0)
+ else if (StrCaseCmp(__argv[i], "-EconetCfg") == 0)
{
strcpy(EconetCfgPath, __argv[++i]);
}
- else if (_stricmp(__argv[i], "-AUNMap") == 0)
+ else if (StrCaseCmp(__argv[i], "-AUNMap") == 0)
{
strcpy(AUNMapPath, __argv[++i]);
}
- else if (_stricmp(__argv[i], "-EcoStn") == 0)
+ else if (StrCaseCmp(__argv[i], "-EcoStn") == 0)
{
int a = atoi(__argv[++i]);
@@ -5146,7 +5160,7 @@ void BeebWin::ParseCommandLine()
else
EconetStationID = static_cast(a);
}
- else if (_stricmp(__argv[i], "-EcoFF") == 0)
+ else if (StrCaseCmp(__argv[i], "-EcoFF") == 0)
{
int a = atoi(__argv[++i]);
@@ -5155,19 +5169,19 @@ void BeebWin::ParseCommandLine()
else
EconetFlagFillTimeout = a;
}
- else if (_stricmp(__argv[i], "-KbdCmd") == 0)
+ else if (StrCaseCmp(__argv[i], "-KbdCmd") == 0)
{
m_KbdCmd = __argv[++i];
}
- else if (_stricmp(__argv[i], "-DebugScript") == 0)
+ else if (StrCaseCmp(__argv[i], "-DebugScript") == 0)
{
m_DebugScriptFileName = __argv[++i];
}
- else if (_stricmp(__argv[i], "-DebugLabels") == 0)
+ else if (StrCaseCmp(__argv[i], "-DebugLabels") == 0)
{
m_DebugLabelsFileName = __argv[++i];
}
- else if (_stricmp(__argv[i], "-AutoBootDelay") == 0)
+ else if (StrCaseCmp(__argv[i], "-AutoBootDelay") == 0)
{
int a = atoi(__argv[++i]);
@@ -5176,12 +5190,12 @@ void BeebWin::ParseCommandLine()
else
m_AutoBootDelay = a;
}
- else if (_stricmp(__argv[i], "-Model") == 0)
+ else if (StrCaseCmp(__argv[i], "-Model") == 0)
{
m_CommandLineModel = static_cast(FindEnum(__argv[++i], MachineTypeStr, 0));
m_HasCommandLineModel = true;
}
- else if (_stricmp(__argv[i], "-Tube") == 0)
+ else if (StrCaseCmp(__argv[i], "-Tube") == 0)
{
m_HasCommandLineTube = true;
m_CommandLineTube = static_cast(FindEnum(__argv[++i], TubeDeviceStr, 0));
@@ -5223,13 +5237,10 @@ void BeebWin::CheckForLocalPrefs(const char *path, bool bLoadPrefs)
return;
char file[MAX_PATH];
- char drive[_MAX_DRIVE];
- char dir[_MAX_DIR];
-
- _splitpath(path, drive, dir, NULL, NULL);
// Look for prefs file
- _makepath(file, drive, dir, "Preferences", "cfg");
+ GetPathFromFileName(path, file, MAX_PATH);
+ AppendPath(file, "Preferences.cfg");
if (FileExists(file))
{
@@ -5255,7 +5266,8 @@ void BeebWin::CheckForLocalPrefs(const char *path, bool bLoadPrefs)
}
// Look for ROMs file
- _makepath(file, drive, dir, "Roms", "cfg");
+ GetPathFromFileName(path, file, MAX_PATH);
+ AppendPath(file, "Roms.cfg");
if (FileExists(file))
{
@@ -5307,8 +5319,8 @@ bool BeebWin::FindCommandLineFile(char *FileName)
{
// Try getting it from Tapes directory
strcpy(TmpPath, m_UserDataPath);
- strcat(TmpPath, "Tapes/");
- strcat(TmpPath, FileName);
+ AppendPath(TmpPath, "Tapes");
+ AppendPath(TmpPath, FileName);
Found = FileExists(TmpPath);
}
@@ -5316,8 +5328,8 @@ bool BeebWin::FindCommandLineFile(char *FileName)
{
// Try getting it from BeebState directory
strcpy(TmpPath, m_UserDataPath);
- strcat(TmpPath, "BeebState/");
- strcat(TmpPath, FileName);
+ AppendPath(TmpPath, "BeebState");
+ AppendPath(TmpPath, FileName);
Found = FileExists(TmpPath);
}
@@ -5325,8 +5337,8 @@ bool BeebWin::FindCommandLineFile(char *FileName)
{
// Try getting it from DiscIms directory
strcpy(TmpPath, m_UserDataPath);
- strcat(TmpPath, "DiscIms/");
- strcat(TmpPath, FileName);
+ AppendPath(TmpPath, "DiscIms");
+ AppendPath(TmpPath, FileName);
Found = FileExists(TmpPath);
}
@@ -5562,10 +5574,10 @@ bool BeebWin::RebootSystem()
bool BeebWin::CheckUserDataPath(bool Persist)
{
- bool success = true;
- bool copy_user_files = false;
- bool store_user_data_path = false;
- char path[MAX_PATH];
+ bool Success = true;
+ bool CopyUserFiles = false;
+ bool UpdateUserDataPath = false;
+ char Path[MAX_PATH];
// Change all '/' to '\'
MakePreferredPath(m_UserDataPath);
@@ -5579,9 +5591,9 @@ bool BeebWin::CheckUserDataPath(bool Persist)
{
// Use data dir installed with BeebEm
strcpy(m_UserDataPath, m_AppPath);
- strcat(m_UserDataPath, "UserData\\");
+ AppendPath(m_UserDataPath, "UserData");
- store_user_data_path = true;
+ UpdateUserDataPath = true;
}
else
{
@@ -5590,108 +5602,123 @@ bool BeebWin::CheckUserDataPath(bool Persist)
if (result == ERROR_SUCCESS)
{
- copy_user_files = true;
+ CopyUserFiles = true;
}
else
{
Report(MessageType::Error, "Failed to create BeebEm data folder:\n %s",
m_UserDataPath);
- success = false;
+ Success = false;
}
}
}
else
{
// Check that essential files are in the user data folder
- sprintf(path, "%sBeebFile", m_UserDataPath);
+ strcpy(Path, m_UserDataPath);
+ AppendPath(Path, "BeebFile");
- if (!FolderExists(path))
- copy_user_files = true;
+ if (!FolderExists(Path))
+ {
+ CopyUserFiles = true;
+ }
- if (!copy_user_files)
+ if (!CopyUserFiles)
{
- sprintf(path, "%sBeebState", m_UserDataPath);
+ strcpy(Path, m_UserDataPath);
+ AppendPath(Path, "BeebState");
- if (!FolderExists(path))
- copy_user_files = true;
+ if (!FolderExists(Path))
+ {
+ CopyUserFiles = true;
+ }
}
- if (!copy_user_files)
+ if (!CopyUserFiles)
{
- sprintf(path, "%sEconet.cfg", m_UserDataPath);
+ strcpy(Path, m_UserDataPath);
+ AppendPath(Path, "Econet.cfg");
- if (!FileExists(path))
- copy_user_files = true;
+ if (!FileExists(Path))
+ {
+ CopyUserFiles = true;
+ }
}
- if (!copy_user_files)
+ if (!CopyUserFiles)
{
- sprintf(path, "%sAUNMap", m_UserDataPath);
+ strcpy(Path, m_UserDataPath);
+ AppendPath(Path, "AUNMap");
- if (!FileExists(path))
- copy_user_files = true;
+ if (!FileExists(Path))
+ {
+ CopyUserFiles = true;
+ }
}
- if (!copy_user_files)
+ if (!CopyUserFiles)
{
- sprintf(path, "%sPhroms.cfg", m_UserDataPath);
+ strcpy(Path, m_UserDataPath);
+ AppendPath(Path, "Phroms.cfg");
- if (!FileExists(path))
- copy_user_files = true;
+ if (!FileExists(Path))
+ {
+ CopyUserFiles = true;
+ }
}
- if (!copy_user_files)
+ if (!CopyUserFiles)
{
if (strcmp(RomFile, "Roms.cfg") == 0)
{
- sprintf(path, "%sRoms.cfg", m_UserDataPath);
+ strcpy(Path, m_UserDataPath);
+ AppendPath(Path, "Roms.cfg");
- if (!FileExists(path))
- copy_user_files = true;
+ if (!FileExists(Path))
+ {
+ CopyUserFiles = true;
+ }
}
}
- if (copy_user_files)
+ if (CopyUserFiles)
{
if (Report(MessageType::Question,
"Essential or new files missing from BeebEm data folder:\n %s"
"\n\nCopy essential or new files into folder?",
m_UserDataPath) != MessageResult::Yes)
{
- success = false;
+ Success = false;
}
}
}
- if (success)
+ if (Success)
{
// Get fully qualified user data path
char *f;
- if (GetFullPathName(m_UserDataPath, MAX_PATH, path, &f) != 0)
- strcpy(m_UserDataPath, path);
+ if (GetFullPathName(m_UserDataPath, MAX_PATH, Path, &f) != 0)
+ strcpy(m_UserDataPath, Path);
}
- if (success && copy_user_files)
+ if (Success && CopyUserFiles)
{
- SHFILEOPSTRUCT fileOp = {0};
- fileOp.hwnd = m_hWnd;
- fileOp.wFunc = FO_COPY;
- fileOp.fFlags = 0;
-
- strcpy(path, m_AppPath);
- strcat(path, "UserData\\*.*");
- path[strlen(path)+1] = 0; // need double 0
- fileOp.pFrom = path;
+ strcpy(Path, m_AppPath);
+ AppendPath(Path, "UserData");
+ AppendPath(Path, "*.*");
+ Path[strlen(Path) + 1] = 0; // need double 0
- m_UserDataPath[strlen(m_UserDataPath)+1] = 0; // need double 0
- fileOp.pTo = m_UserDataPath;
+ char UserDataPath[MAX_PATH];
+ strcpy(UserDataPath, m_UserDataPath);
+ UserDataPath[strlen(UserDataPath) + 1] = 0; // need double 0
- if (SHFileOperation(&fileOp) || fileOp.fAnyOperationsAborted)
+ if (!CopyFiles(Path, UserDataPath))
{
Report(MessageType::Error, "Copy failed. Manually copy files from:\n %s"
"\n\nTo BeebEm data folder:\n %s",
- path, m_UserDataPath);
- success = false;
+ Path, m_UserDataPath);
+
+ Success = false;
}
else
{
@@ -5700,40 +5727,64 @@ bool BeebWin::CheckUserDataPath(bool Persist)
}
}
- if (success)
+ if (Success)
{
// Check that roms file exists and create its full path
- if (PathIsRelative(RomFile))
+ if (IsRelativePath(RomFile))
{
- sprintf(path, "%s%s", m_UserDataPath, RomFile);
- strcpy(RomFile, path);
+ strcpy(Path, m_UserDataPath);
+ AppendPath(Path, RomFile);
+ strcpy(RomFile, Path);
}
if (!FileExists(RomFile))
{
Report(MessageType::Error, "Cannot open ROMs file:\n %s", RomFile);
- success = false;
+ Success = false;
}
}
- if (success)
+ if (Success)
{
// Fill out full path of prefs file
- if (PathIsRelative(m_PrefsFileName.c_str()))
+ if (IsRelativePath(m_PrefsFileName.c_str()))
{
- sprintf(path, "%s%s", m_UserDataPath, m_PrefsFileName.c_str());
- m_PrefsFileName = path;
+ strcpy(Path, m_UserDataPath);
+ AppendPath(Path, m_PrefsFileName.c_str());
+
+ m_PrefsFileName = Path;
}
}
- if (success && Persist && (copy_user_files || store_user_data_path))
+ if (Success && Persist && (CopyUserFiles || UpdateUserDataPath))
{
StoreUserDataPath();
}
- return success;
+ return Success;
}
+/****************************************************************************/
+
+bool BeebWin::CopyFiles(const char* SourceFileSpec, const char* DestPath)
+{
+ SHFILEOPSTRUCT fileOp = {0};
+ fileOp.hwnd = m_hWnd;
+ fileOp.wFunc = FO_COPY;
+ fileOp.fFlags = 0;
+ fileOp.pFrom = SourceFileSpec;
+ fileOp.pTo = DestPath;
+
+ if (SHFileOperation(&fileOp) || fileOp.fAnyOperationsAborted)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+/****************************************************************************/
+
void BeebWin::StoreUserDataPath()
{
// Store user data path in registry
@@ -5763,7 +5814,6 @@ void BeebWin::SelectUserDataPath()
case FolderSelectDialog::Result::OK:
PathBackup = m_UserDataPath;
strcpy(m_UserDataPath, Dialog.GetFolder().c_str());
- strcat(m_UserDataPath, "\\");
// Check folder contents
if (!CheckUserDataPath(true))
diff --git a/Src/BeebWin.h b/Src/BeebWin.h
index cb46f77d..66cb97d5 100644
--- a/Src/BeebWin.h
+++ b/Src/BeebWin.h
@@ -363,12 +363,13 @@ class BeebWin
bool FindCommandLineFile(char *FileName);
void HandleCommandLineFile(int Drive, const char *FileName);
bool CheckUserDataPath(bool Persist);
+ bool CopyFiles(const char* SourceFileSpec, const char* DestPath);
void SelectUserDataPath(void);
void StoreUserDataPath(void);
bool NewTapeImage(char *FileName, int Size);
const char *GetAppPath() const { return m_AppPath; }
const char *GetUserDataPath() const { return m_UserDataPath; }
- void GetDataPath(const char *folder, char *path);
+ void GetDataPath(const char *Folder, char *Path);
void QuickLoad();
void QuickSave();
void LoadUEFState(const char *FileName);
diff --git a/Src/BeebWinIo.cpp b/Src/BeebWinIo.cpp
index 006b0e00..0b51ea8b 100644
--- a/Src/BeebWinIo.cpp
+++ b/Src/BeebWinIo.cpp
@@ -58,6 +58,7 @@ using std::max;
#include "Resource.h"
#include "Serial.h"
#include "Sound.h"
+#include "StringUtils.h"
#include "TapeControlDialog.h"
#include "Tube.h"
#include "UefState.h"
@@ -171,6 +172,7 @@ bool BeebWin::ReadDisc(int Drive, bool bCheckForPrefs)
switch (Dialog.GetFilterIndex())
{
case 1:
+ default:
Type = GetFileTypeFromExtension(FileName);
break;
@@ -430,9 +432,9 @@ bool BeebWin::NewTapeImage(char *FileName, int Size)
m_Preferences.GetStringValue(CFG_TAPES_PATH, DefaultPath);
GetDataPath(m_UserDataPath, DefaultPath);
- FileDialog fileDialog(m_hWnd, FileName, Size, DefaultPath, filter);
+ FileDialog Dialog(m_hWnd, FileName, Size, DefaultPath, filter);
- bool Result = fileDialog.Save();
+ bool Result = Dialog.Save();
if (Result)
{
@@ -463,8 +465,9 @@ void BeebWin::SelectFDC()
strcpy(DefaultPath, m_AppPath);
strcat(DefaultPath, "Hardware");
- FileDialog fileDialog(m_hWnd, FileName, sizeof(FileName), DefaultPath, filter);
- if (fileDialog.Open())
+ FileDialog Dialog(m_hWnd, FileName, sizeof(FileName), DefaultPath, filter);
+
+ if (Dialog.Open())
{
// Make path relative to app path
if (_strnicmp(FileName, m_AppPath, strlen(m_AppPath)) == 0)
@@ -797,7 +800,7 @@ void BeebWin::UpdatePrinterPortMenu()
UINT SelectedMenuItemID = 0;
- for (int i = 0; i < _countof(MenuItems); i++)
+ for (size_t i = 0; i < _countof(MenuItems); i++)
{
if (m_PrinterPort == MenuItems[i].PrinterPort)
{
@@ -972,7 +975,7 @@ void BeebWin::UpdateVideoCaptureResolutionMenu()
UINT SelectedMenuItemID = 0;
- for (int i = 0; i < _countof(MenuItems); i++)
+ for (size_t i = 0; i < _countof(MenuItems); i++)
{
if (m_VideoCaptureResolution == MenuItems[i].Resolution)
{
@@ -999,7 +1002,7 @@ void BeebWin::UpdateVideoCaptureFrameSkipMenu()
UINT SelectedMenuItemID = 0;
- for (int i = 0; i < _countof(MenuItems); i++)
+ for (size_t i = 0; i < _countof(MenuItems); i++)
{
if (m_AviFrameSkip == MenuItems[i].FrameSkip)
{
@@ -1152,7 +1155,8 @@ void BeebWin::QuickLoad()
{
char FileName[MAX_PATH];
strcpy(FileName, m_UserDataPath);
- strcat(FileName, "BeebState\\quicksave.uefstate");
+ AppendPath(FileName, "BeebState");
+ AppendPath(FileName, "quicksave.uefstate");
if (FileExists(FileName))
{
@@ -1162,7 +1166,8 @@ void BeebWin::QuickLoad()
{
// For backwards compatiblity with existing quicksave files:
strcpy(FileName, m_UserDataPath);
- strcat(FileName, "BeebState\\quicksave.uef");
+ AppendPath(FileName, "BeebState");
+ AppendPath(FileName, "quicksave.uef");
LoadUEFState(FileName);
}
}
@@ -1175,15 +1180,26 @@ void BeebWin::QuickSave()
// Bump old quicksave files down
for (int i = 1; i <= 9; ++i)
{
- sprintf(FileName1, "%sBeebState\\quicksave%d.uefstate", m_UserDataPath, i);
+ char FileName[100];
+ sprintf(FileName, "quicksave%d.uefstate", i);
+
+ strcpy(FileName1, m_UserDataPath);
+ AppendPath(FileName1, "BeebState");
+ AppendPath(FileName1, FileName);
if (i == 9)
{
- sprintf(FileName2, "%sBeebState\\quicksave.uefstate", m_UserDataPath);
+ strcpy(FileName2, m_UserDataPath);
+ AppendPath(FileName2, "BeebState");
+ AppendPath(FileName2, "quicksave.uefstate");
}
else
{
- sprintf(FileName2, "%sBeebState\\quicksave%d.uefstate", m_UserDataPath, i + 1);
+ sprintf(FileName, "quicksave%d.uefstate", i);
+
+ strcpy(FileName2, m_UserDataPath);
+ AppendPath(FileName2, "BeebState");
+ AppendPath(FileName2, FileName);
}
MoveFileEx(FileName2, FileName1, MOVEFILE_REPLACE_EXISTING);
@@ -1495,26 +1511,25 @@ void BeebWin::LoadEmuUEF(FILE *SUEF, int Version)
}
/****************************************************************************/
-void BeebWin::GetDataPath(const char *folder, char *path)
+
+void BeebWin::GetDataPath(const char *Folder, char *Path)
{
- char newPath[MAX_PATH];
+ char NewPath[MAX_PATH];
- // If path is absolute then use it
- if (path[0] == '\\' || path[0] == '/' ||
- (strlen(path) > 2 && path[1] == ':' && (path[2] == '\\' || path[2] == '/')))
+ if (IsRelativePath(Path))
{
- // Absolute path - just use it as is
+ strcpy(NewPath, Folder);
+ AppendPath(NewPath, Path);
+ strcpy(Path, NewPath);
}
else
{
- // Relative path
- strcpy(newPath, folder);
- strcat(newPath, path);
- strcpy(path, newPath);
+ // Absolute path - just use it as is
}
}
/****************************************************************************/
+
void BeebWin::LoadUserKeyMap()
{
char FileName[MAX_PATH];
@@ -1522,8 +1537,9 @@ void BeebWin::LoadUserKeyMap()
const char* filter = "Key Map File (*.kmap)\0*.kmap\0";
- FileDialog fileDialog(m_hWnd, FileName, sizeof(FileName), m_UserDataPath, filter);
- if (fileDialog.Open())
+ FileDialog Dialog(m_hWnd, FileName, sizeof(FileName), m_UserDataPath, filter);
+
+ if (Dialog.Open())
{
if (ReadKeyMap(FileName, &UserKeyMap))
strcpy(m_UserKeyMapPath, FileName);
@@ -1531,6 +1547,7 @@ void BeebWin::LoadUserKeyMap()
}
/****************************************************************************/
+
void BeebWin::SaveUserKeyMap()
{
char FileName[MAX_PATH];
@@ -1538,9 +1555,9 @@ void BeebWin::SaveUserKeyMap()
const char* filter = "Key Map File (*.kmap)\0*.kmap\0";
- FileDialog fileDialog(m_hWnd, FileName, sizeof(FileName), m_UserDataPath, filter);
+ FileDialog Dialog(m_hWnd, FileName, sizeof(FileName), m_UserDataPath, filter);
- if (fileDialog.Save())
+ if (Dialog.Save())
{
if (!HasFileExt(FileName, ".kmap"))
{
@@ -1846,7 +1863,7 @@ void BeebWin::ImportDiscFiles(int menuId)
char baseName[MAX_PATH];
strcpy(baseName, fileName);
int Len = (int)strlen(baseName);
- if (Len > 4 && _stricmp(baseName + Len - 4, ".inf") == 0)
+ if (Len > 4 && StrCaseCmp(baseName + Len - 4, ".inf") == 0)
baseName[Len - 4] = 0;
// Check for duplicate
@@ -1854,7 +1871,7 @@ void BeebWin::ImportDiscFiles(int menuId)
for (i = 0; i < numFiles; ++i)
{
- if (_stricmp(baseName, fileNames[i]) == 0)
+ if (StrCaseCmp(baseName, fileNames[i]) == 0)
break;
}
@@ -1927,9 +1944,9 @@ void BeebWin::SelectHardDriveFolder()
m_Preferences.GetStringValue(CFG_HARD_DRIVE_PATH, DefaultPath);
GetDataPath(m_UserDataPath, DefaultPath);
- FileDialog fileDialog(m_hWnd, FileName, sizeof(FileName), DefaultPath, filter);
+ FileDialog Dialog(m_hWnd, FileName, sizeof(FileName), DefaultPath, filter);
- if (fileDialog.Open())
+ if (Dialog.Open())
{
unsigned int PathLength = (unsigned int)(strrchr(FileName, '\\') - FileName);
strncpy(DefaultPath, FileName, PathLength);
@@ -1971,7 +1988,7 @@ void BeebWin::UpdateBitmapCaptureFormatMenu()
UINT SelectedMenuItemID = 0;
- for (int i = 0; i < _countof(MenuItems); i++)
+ for (size_t i = 0; i < _countof(MenuItems); i++)
{
if (m_BitmapCaptureFormat == MenuItems[i].Format)
{
@@ -2002,7 +2019,7 @@ void BeebWin::UpdateBitmapCaptureResolutionMenu()
UINT SelectedMenuItemID = 0;
- for (int i = 0; i < _countof(MenuItems); i++)
+ for (size_t i = 0; i < _countof(MenuItems); i++)
{
if (m_BitmapCaptureResolution == MenuItems[i].Resolution)
{
diff --git a/Src/BeebWinPrefs.cpp b/Src/BeebWinPrefs.cpp
index c891a1dd..0d57f6f4 100644
--- a/Src/BeebWinPrefs.cpp
+++ b/Src/BeebWinPrefs.cpp
@@ -933,17 +933,26 @@ void BeebWin::LoadInputPreferences(int Version)
if (m_Preferences.GetStringValue(CFG_OPTIONS_USER_KEY_MAP_FILE, m_UserKeyMapPath))
{
- strcpy(Path, m_UserKeyMapPath);
- GetDataPath(m_UserDataPath, Path);
+ if (IsRelativePath(m_UserKeyMapPath))
+ {
+ strcpy(Path, m_UserDataPath);
+ AppendPath(Path, m_UserKeyMapPath);
+ }
+ else
+ {
+ strcpy(Path, m_UserKeyMapPath);
+ }
+
if (ReadKeyMap(Path, &UserKeyMap))
+ {
ReadDefault = false;
+ }
}
if (ReadDefault)
{
- strcpy(m_UserKeyMapPath, "DefaultUser.kmap");
- strcpy(Path, m_UserKeyMapPath);
- GetDataPath(m_UserDataPath, Path);
+ strcpy(Path, m_UserDataPath);
+ AppendPath(Path, "DefaultUser.kmap");
ReadKeyMap(Path, &UserKeyMap);
}
}
diff --git a/Src/Disc8271.cpp b/Src/Disc8271.cpp
index d5d95d99..933c93cf 100644
--- a/Src/Disc8271.cpp
+++ b/Src/Disc8271.cpp
@@ -36,6 +36,7 @@ Boston, MA 02110-1301, USA.
#include "Log.h"
#include "Main.h"
#include "Sound.h"
+#include "StringUtils.h"
#include "SysVia.h"
#include "Tube.h"
#include "UefState.h"
@@ -2956,11 +2957,11 @@ void Load8271UEF(FILE *SUEF, int Version)
const char *ext = strrchr(FileName, '.');
- if (ext != nullptr && _stricmp(ext + 1, "dsd") == 0)
+ if (ext != nullptr && StrCaseCmp(ext + 1, "dsd") == 0)
{
LoadSuccess = mainWin->Load8271DiscImage(FileName, 0, 80, DiscType::DSD);
}
- else if (Version >= 14 && ext != nullptr && _stricmp(ext + 1, "fsd") == 0)
+ else if (Version >= 14 && ext != nullptr && StrCaseCmp(ext + 1, "fsd") == 0)
{
LoadSuccess = mainWin->Load8271DiscImage(FileName, 0, 80, DiscType::FSD);
}
@@ -2988,11 +2989,11 @@ void Load8271UEF(FILE *SUEF, int Version)
const char *ext = strrchr(FileName, '.');
- if (ext != nullptr && _stricmp(ext + 1, "dsd") == 0)
+ if (ext != nullptr && StrCaseCmp(ext + 1, "dsd") == 0)
{
LoadSuccess = mainWin->Load8271DiscImage(FileName, 1, 80, DiscType::DSD);
}
- else if (Version >= 14 && ext != nullptr && _stricmp(ext + 1, "fsd") == 0)
+ else if (Version >= 14 && ext != nullptr && StrCaseCmp(ext + 1, "fsd") == 0)
{
LoadSuccess = mainWin->Load8271DiscImage(FileName, 1, 80, DiscType::FSD);
}
diff --git a/Src/FileUtils.cpp b/Src/FileUtils.cpp
index 2fb78f01..38c43067 100644
--- a/Src/FileUtils.cpp
+++ b/Src/FileUtils.cpp
@@ -19,10 +19,12 @@ Boston, MA 02110-1301, USA.
****************************************************************/
#include
+#include
#include
#include "FileUtils.h"
+#include "StringUtils.h"
/****************************************************************************/
@@ -77,7 +79,7 @@ bool HasFileExt(const char* FileName, const char* Ext)
const size_t FileNameLen = strlen(FileName);
return FileNameLen >= ExtLen &&
- _stricmp(FileName + FileNameLen - ExtLen, Ext) == 0;
+ StrCaseCmp(FileName + FileNameLen - ExtLen, Ext) == 0;
}
/****************************************************************************/
@@ -153,3 +155,45 @@ void MakePreferredPath(char* PathName)
}
/****************************************************************************/
+
+void AppendPath(char* pszPath, const char* pszPathToAppend)
+{
+ size_t Len = strlen(pszPath);
+
+ if (Len > 0)
+ {
+ if (pszPath[Len - 1] != DIR_SEPARATOR)
+ {
+ pszPath[Len] = DIR_SEPARATOR;
+ pszPath[++Len] = '\0';
+ }
+ }
+
+ if (Len > 0 && pszPathToAppend[0] == DIR_SEPARATOR)
+ {
+ strcpy(&pszPath[Len], pszPathToAppend + 1);
+ }
+ else
+ {
+ strcpy(&pszPath[Len], pszPathToAppend);
+ }
+
+ MakePreferredPath(pszPath);
+}
+
+/****************************************************************************/
+
+bool IsRelativePath(const char* pszPath)
+{
+ #ifdef WIN32
+
+ return !!PathIsRelative(pszPath);
+
+ #else
+
+ return pszPath[0] != '/';
+
+ #endif
+}
+
+/****************************************************************************/
diff --git a/Src/FileUtils.h b/Src/FileUtils.h
index 8dca0fcb..ed5312d0 100644
--- a/Src/FileUtils.h
+++ b/Src/FileUtils.h
@@ -33,6 +33,8 @@ std::string ReplaceFileExt(const std::string& FileName, const char* Ext);
void GetPathFromFileName(const char* FileName, char* Path, size_t Size);
void MakeFileName(char* Path, size_t Size, const char* DirName, const char* FileName, ...);
void MakePreferredPath(char* PathName);
+void AppendPath(char* pszPath, const char* pszPathToAppend);
+bool IsRelativePath(const char* pszPath);
/*----------------------------------------------------------------------------*/
diff --git a/Src/Log.cpp b/Src/Log.cpp
index 109db6d4..94b8e6c6 100644
--- a/Src/Log.cpp
+++ b/Src/Log.cpp
@@ -26,6 +26,7 @@ Boston, MA 02110-1301, USA.
#include
#include "Log.h"
+#include "FileUtils.h"
#include "Main.h"
static FILE *LogFile = nullptr;
@@ -39,11 +40,11 @@ void OpenLog()
{
LogFile = nullptr;
- char Path[256];
- strcpy(Path, mainWin->GetUserDataPath());
- strcat(Path, "BeebEm.log");
+ char PathName[MAX_PATH];
+ strcpy(PathName, mainWin->GetUserDataPath());
+ AppendPath(PathName, "BeebEm.log");
- // LogFile = fopen(Path, "wt");
+ // LogFile = fopen(PathName, "wt");
}
void CloseLog()
diff --git a/Src/Master512CoPro.cpp b/Src/Master512CoPro.cpp
index a82ce2ba..10547ca9 100644
--- a/Src/Master512CoPro.cpp
+++ b/Src/Master512CoPro.cpp
@@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include
#include "Master512CoPro.h"
+#include "FileUtils.h"
#include "Main.h"
#include "Log.h"
#include "Tube.h"
@@ -3757,11 +3758,12 @@ void Master512CoPro::LoadBIOS()
{
memset(m_Memory, 0, 0x100000);
- char path[256];
- strcpy(path, mainWin->GetUserDataPath());
- strcat(path, "BeebFile/BIOS.rom");
+ char PathName[MAX_PATH];
+ strcpy(PathName, mainWin->GetUserDataPath());
+ AppendPath(PathName, "BeebFile");
+ AppendPath(PathName, "BIOS.rom");
- FILE* f = fopen(path, "rb");
+ FILE* f = fopen(PathName, "rb");
if (f != nullptr)
{
@@ -3773,7 +3775,7 @@ void Master512CoPro::LoadBIOS()
}
else
{
- mainWin->Report(MessageType::Error, "Could not open BIOS image file:\n %s", path);
+ mainWin->Report(MessageType::Error, "Could not open BIOS image file:\n %s", PathName);
}
}
diff --git a/Src/Sound.cpp b/Src/Sound.cpp
index 73dbb5ee..0bbde2ea 100644
--- a/Src/Sound.cpp
+++ b/Src/Sound.cpp
@@ -33,6 +33,7 @@ Boston, MA 02110-1301, USA.
#include "6502core.h"
#include "AviWriter.h"
#include "BeebWin.h"
+#include "FileUtils.h"
#include "Main.h"
#include "SoundStreamer.h"
#include "Speech.h"
@@ -543,7 +544,7 @@ void LoadSoundSamples()
char FileName[MAX_PATH];
strcpy(FileName, mainWin->GetAppPath());
- strcat(FileName, SoundSamples[i].pFilename);
+ AppendPath(FileName, SoundSamples[i].pFilename);
FILE *fd = fopen(FileName, "rb");
diff --git a/Src/Speech.cpp b/Src/Speech.cpp
index 98e0b84e..5e8a645e 100644
--- a/Src/Speech.cpp
+++ b/Src/Speech.cpp
@@ -46,6 +46,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "Speech.h"
#include "6502core.h"
#include "BeebWin.h"
+#include "FileUtils.h"
#include "Log.h"
#include "Main.h"
#include "Sound.h"
@@ -1394,7 +1395,7 @@ bool SpeechInit()
// This section rewritten for V.1.32 to take account of roms.cfg file.
char Path[MAX_PATH];
strcpy(Path, mainWin->GetUserDataPath());
- strcat(Path, "Phroms.cfg");
+ AppendPath(Path, "Phroms.cfg");
FILE *RomCfg = fopen(Path, "rt");
@@ -1418,11 +1419,11 @@ bool SpeechInit()
char PhromPath[MAX_PATH];
strcpy(PhromPath, RomName);
- if (RomName[0] != '\\' && RomName[1] != ':')
+ if (IsRelativePath(RomName))
{
strcpy(PhromPath, mainWin->GetUserDataPath());
- strcat(PhromPath, "Phroms\\");
- strcat(PhromPath, RomName);
+ AppendPath(PhromPath, "Phroms");
+ AppendPath(PhromPath, RomName);
}
if (strncmp(RomName, "EMPTY", 5) != 0)
diff --git a/Src/StringUtils.cpp b/Src/StringUtils.cpp
index a4c073f6..698d2783 100644
--- a/Src/StringUtils.cpp
+++ b/Src/StringUtils.cpp
@@ -23,8 +23,14 @@ Boston, MA 02110-1301, USA.
#include
#include
+#ifndef WIN32
+#include // For strcasecmp
+#endif
+
#include "StringUtils.h"
+/****************************************************************************/
+
static void trimLeft(std::string& str)
{
auto pos = std::find_if(str.begin(), str.end(), [](int ch) {
@@ -34,6 +40,8 @@ static void trimLeft(std::string& str)
str.erase(str.begin(), pos);
}
+/****************************************************************************/
+
static void trimRight(std::string& str)
{
auto pos = std::find_if(str.rbegin(), str.rend(), [](int ch) {
@@ -43,12 +51,16 @@ static void trimRight(std::string& str)
str.erase(pos.base(), str.end());
}
+/****************************************************************************/
+
void trim(std::string& str)
{
trimLeft(str);
trimRight(str);
}
+/****************************************************************************/
+
bool ParseNumber(const std::string& str, int* pValue)
{
try
@@ -63,6 +75,8 @@ bool ParseNumber(const std::string& str, int* pValue)
return true;
}
+/****************************************************************************/
+
char ToHexDigit(int Value)
{
static const char HexDigit[16] =
@@ -73,12 +87,16 @@ char ToHexDigit(int Value)
return HexDigit[Value];
}
+/****************************************************************************/
+
bool StringEndsWith(const std::string& str, const std::string& suffix)
{
return str.size() >= suffix.size() &&
str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
}
+/****************************************************************************/
+
std::string WStr2Str(const std::wstring& str)
{
std::wstring_convert, wchar_t> Converter;
@@ -86,9 +104,28 @@ std::string WStr2Str(const std::wstring& str)
return Converter.to_bytes(str);
}
+/****************************************************************************/
+
std::wstring Str2WStr(const std::string& str)
{
std::wstring_convert, wchar_t> Converter;
return Converter.from_bytes(str);
}
+
+/****************************************************************************/
+
+int StrCaseCmp(const char *str1, const char *str2)
+{
+ #ifdef WIN32
+
+ return _stricmp(str1, str2);
+
+ #else
+
+ return strcasecmp(str1, str2);
+
+ #endif
+}
+
+/****************************************************************************/
diff --git a/Src/StringUtils.h b/Src/StringUtils.h
index ed49d331..52dc49b3 100644
--- a/Src/StringUtils.h
+++ b/Src/StringUtils.h
@@ -29,5 +29,6 @@ char ToHexDigit(int Value);
bool StringEndsWith(const std::string& str, const std::string& suffix);
std::string WStr2Str(const std::wstring& str);
std::wstring Str2WStr(const std::string& str);
+int StrCaseCmp(const char *str1, const char *str2);
#endif
diff --git a/Src/Tube.cpp b/Src/Tube.cpp
index bc50f74a..a34dd300 100644
--- a/Src/Tube.cpp
+++ b/Src/Tube.cpp
@@ -38,6 +38,7 @@ Boston, MA 02110-1301, USA.
#include "Arm.h"
#include "BeebMem.h"
#include "Debug.h"
+#include "FileUtils.h"
#include "Log.h"
#include "Main.h"
#include "SprowCoPro.h"
@@ -1532,8 +1533,10 @@ static void Reset65C02()
//The fun part, the tube OS is copied from ROM to tube RAM before the processor starts processing
//This makes the OS "ROM" writable in effect, but must be restored on each reset.
char TubeRomName[MAX_PATH];
- strcpy(TubeRomName,RomPath);
- strcat(TubeRomName,"BeebFile/6502Tube.rom");
+ strcpy(TubeRomName, RomPath);
+ AppendPath(TubeRomName, "BeebFile");
+ AppendPath(TubeRomName, "6502Tube.rom");
+
FILE *TubeRom = fopen(TubeRomName,"rb");
if (TubeRom != nullptr)
{
diff --git a/Src/Z80Support.cpp b/Src/Z80Support.cpp
index f06cc253..e7a41625 100644
--- a/Src/Z80Support.cpp
+++ b/Src/Z80Support.cpp
@@ -27,6 +27,7 @@ Boston, MA 02110-1301, USA.
#include "Z80.h"
#include "BeebMem.h"
#include "Debug.h"
+#include "FileUtils.h"
#include "Log.h"
#include "Tube.h"
#include "UefState.h"
@@ -232,16 +233,17 @@ void z80_execute()
void init_z80()
{
- char path[256];
+ char PathName[MAX_PATH];
WriteLog("init_z80()\n");
if (TubeType == TubeDevice::AcornZ80)
{
- strcpy(path, RomPath);
- strcat(path, "BeebFile/Z80.rom");
+ strcpy(PathName, RomPath);
+ AppendPath(PathName, "BeebFile");
+ AppendPath(PathName, "Z80.rom");
- FILE *f = fopen(path, "rb");
+ FILE *f = fopen(PathName, "rb");
if (f != nullptr)
{
fread(z80_rom, 4096, 1, f);
@@ -250,10 +252,11 @@ void init_z80()
}
else // Tube::TorchZ80
{
- strcpy(path, RomPath);
- strcat(path, "BeebFile/CCPN102.rom");
+ strcpy(PathName, RomPath);
+ AppendPath(PathName, "BeebFile");
+ AppendPath(PathName, "CCPN102.rom");
- FILE *f = fopen(path, "rb");
+ FILE *f = fopen(PathName, "rb");
if (f != nullptr)
{
size_t addr = 0;
From 4be6c7fb6b2194355b1e8be0ddce6293cf96cc85 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 24 Aug 2024 20:06:03 +0100
Subject: [PATCH 040/101] Fixed compiler warnings
---
Src/ARMulator.h | 6 ++--
Src/ARMulator/armdefs.h | 2 +-
Src/ARMulator/armemu.cpp | 66 ++++++++++++++++++++++++++------------
Src/ARMulator/thumbemu.cpp | 14 ++++----
Src/SprowCoPro.cpp | 6 ++--
5 files changed, 59 insertions(+), 35 deletions(-)
diff --git a/Src/ARMulator.h b/Src/ARMulator.h
index 33904461..496efb48 100644
--- a/Src/ARMulator.h
+++ b/Src/ARMulator.h
@@ -14,8 +14,8 @@ 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 this program; if not, write to the Free
+You should have received a copy of the GNU General Public
+License along with this program; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
****************************************************************/
@@ -28,8 +28,6 @@ Boston, MA 02110-1301, USA.
#include "ARMulator/armos.h"
#include "ARMulator/ansidecl.h"
-int stop_simulator = 0;
-
#define IFLAG (state->IFFlags >> 1)
#define FFLAG (state->IFFlags & 1)
diff --git a/Src/ARMulator/armdefs.h b/Src/ARMulator/armdefs.h
index 9f79f811..22c0b475 100644
--- a/Src/ARMulator/armdefs.h
+++ b/Src/ARMulator/armdefs.h
@@ -292,7 +292,7 @@ extern void ARMul_Abort (ARMul_State * state, ARMword address);
* Definitons of things in the memory interface *
\***************************************************************************/
-extern unsigned ARMul_MemoryInit (ARMul_State * state, ARMword initmemsize);
+extern unsigned ARMul_MemoryInit (ARMul_State * state, unsigned long initmemsize);
extern void ARMul_MemoryExit (ARMul_State * state);
extern ARMword ARMul_LoadInstrS (ARMul_State * state, ARMword address,
diff --git a/Src/ARMulator/armemu.cpp b/Src/ARMulator/armemu.cpp
index 2e144930..d403658a 100644
--- a/Src/ARMulator/armemu.cpp
+++ b/Src/ARMulator/armemu.cpp
@@ -63,8 +63,6 @@ static long ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
extern int (*deprecated_ui_loop_hook) (int);
#endif /* NEED_UI_LOOP_HOOK */
-extern int stop_simulator;
-
/* Short-hand macros for LDR/STR. */
/* Store post decrement writeback. */
@@ -498,7 +496,7 @@ ARMul_Emulate26 (ARMul_State * state)
ARMword lhs; /* Almost the ABus and BBus. */
ARMword rhs;
ARMword decoded = 0; /* Instruction pipeline. */
- ARMword loaded = 0;
+ ARMword loaded = 0;
/* Execute the next instruction. */
@@ -509,7 +507,7 @@ ARMul_Emulate26 (ARMul_State * state)
pc = state->pc;
}
- do
+ for (;;)
{
/* Just keep going. */
isize = INSN_SIZE;
@@ -794,10 +792,14 @@ ARMul_Emulate26 (ARMul_State * state)
if (cp14r0 & ARMul_CP14_R0_CCD)
{
- if (state->CP14R0_CCD == -1)
+ if (state->CP14R0_CCD == (ARMword)-1)
+ {
state->CP14R0_CCD = (ARMword)newcycles;
+ }
else
+ {
state->CP14R0_CCD += newcycles;
+ }
if (state->CP14R0_CCD >= 64)
{
@@ -963,9 +965,13 @@ ARMul_Emulate26 (ARMul_State * state)
state->Reg[MULDESTReg] = 0;
}
else if (MULDESTReg != 15)
+ {
state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs;
+ }
else
+ {
UNDEF_MULPCDest;
+ }
for (dest = 0, temp = 0; dest < 32; dest ++)
if (rhs & (1L << dest))
@@ -1009,7 +1015,9 @@ ARMul_Emulate26 (ARMul_State * state)
state->Reg[MULDESTReg] = dest;
}
else
+ {
UNDEF_MULPCDest;
+ }
for (dest = 0, temp = 0; dest < 32; dest ++)
if (rhs & (1L << dest))
@@ -1037,7 +1045,8 @@ ARMul_Emulate26 (ARMul_State * state)
}
#endif
if (BITS (4, 7) == 9)
- { /* MLA */
+ {
+ /* MLA */
rhs = state->Reg[MULRHSReg];
if (MULLHSReg == MULDESTReg)
{
@@ -1045,10 +1054,14 @@ ARMul_Emulate26 (ARMul_State * state)
state->Reg[MULDESTReg] = state->Reg[MULACCReg];
}
else if (MULDESTReg != 15)
+ {
state->Reg[MULDESTReg] =
state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
+ }
else
+ {
UNDEF_MULPCDest;
+ }
for (dest = 0, temp = 0; dest < 32; dest ++)
if (rhs & (1L << dest))
@@ -1092,7 +1105,9 @@ ARMul_Emulate26 (ARMul_State * state)
state->Reg[MULDESTReg] = dest;
}
else
+ {
UNDEF_MULPCDest;
+ }
for (dest = 0, temp = 0; dest < 32; dest ++)
if (rhs & (1L << dest))
@@ -1680,8 +1695,10 @@ ARMul_Emulate26 (ARMul_State * state)
Thumb mode it does). So intercept the instruction here
and generate a breakpoint SWI instead. */
#ifndef BEEBEM
- if (! SWI_vector_installed)
+ if (!SWI_vector_installed)
+ {
ARMul_OSHandleSWI (state, SWI_Breakpoint);
+ }
else
{
/* BKPT - normally this will cause an abort, but on the
@@ -1708,8 +1725,9 @@ ARMul_Emulate26 (ARMul_State * state)
ARMul_FixCPSR (state, instr, temp);
}
else
+ {
UNDEF_Test;
-
+ }
break;
case 0x13: /* TEQP reg */
@@ -1838,8 +1856,9 @@ ARMul_Emulate26 (ARMul_State * state)
DEST = GETSPSR (state->Bank);
}
else
+ {
UNDEF_Test;
-
+ }
break;
case 0x15: /* CMPP reg. */
@@ -2353,15 +2372,19 @@ ARMul_Emulate26 (ARMul_State * state)
}
break;
- case 0x32: /* TEQ immed and MSR immed to CPSR */
+ case 0x32: /* TEQ immed and MSR immed to CPSR */
if (DESTReg == 15)
+ {
/* MSR immed to CPSR. */
ARMul_FixCPSR (state, instr, DPImmRHS);
+ }
else
+ {
UNDEF_Test;
+ }
break;
- case 0x33: /* TEQP immed */
+ case 0x33: /* TEQP immed */
if (DESTReg == 15)
{
/* TEQP immed. */
@@ -2421,9 +2444,13 @@ ARMul_Emulate26 (ARMul_State * state)
case 0x36: /* CMN immed and MSR immed to SPSR */
if (DESTReg == 15)
+ {
ARMul_FixSPSR (state, instr, DPImmRHS);
+ }
else
+ {
UNDEF_Test;
+ }
break;
case 0x37: /* CMNP immed. */
@@ -3541,12 +3568,12 @@ ARMul_Emulate26 (ARMul_State * state)
}
else
/* FIXME: Not sure what to do for other v5 processors. */
- ARMul_UndefInstr (state, instr);
+ ARMul_UndefInstr (state, instr);
break;
}
- /* Drop through. */
+ /* Fall through. */
- case 0xc0: /* Store , No WriteBack , Post Dec. */
+ case 0xc0: /* Store , No WriteBack , Post Dec. */
ARMul_STC (state, instr, LHS);
break;
@@ -3589,7 +3616,7 @@ ARMul_Emulate26 (ARMul_State * state)
ARMul_UndefInstr (state, instr);
break;
}
- /* Drop through. */
+ /* Fall through. */
case 0xc1: /* Load , No WriteBack , Post Dec. */
ARMul_LDC (state, instr, LHS);
@@ -3776,7 +3803,7 @@ ARMul_Emulate26 (ARMul_State * state)
default:
break;
}
- /* Drop through. */
+ /* Fall through. */
case 0xe0:
case 0xe4:
@@ -3888,7 +3915,6 @@ ARMul_Emulate26 (ARMul_State * state)
else if (state->Emulate != RUN)
break;
}
- while (!stop_simulator);
state->decoded = decoded;
state->loaded = loaded;
@@ -4386,7 +4412,7 @@ Handle_Load_Double (ARMul_State * state, ARMword instr)
ARMword addr_reg;
ARMword write_back = BIT (21);
ARMword immediate = BIT (22);
- ARMword add_to_base = BIT (23);
+ ARMword add_to_base = BIT (23);
ARMword pre_indexed = BIT (24);
ARMword offset;
ARMword addr;
@@ -4493,7 +4519,7 @@ Handle_Store_Double (ARMul_State * state, ARMword instr)
ARMword addr_reg;
ARMword write_back = BIT (21);
ARMword immediate = BIT (22);
- ARMword add_to_base = BIT (23);
+ ARMword add_to_base = BIT (23);
ARMword pre_indexed = BIT (24);
ARMword offset;
ARMword addr;
@@ -5167,7 +5193,7 @@ Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc)
unsigned multiply, and what bits are clear in the multiplier. */
if (msigned && (Rm & ((unsigned) 1 << 31)))
/* Invert the bits to make the check against zero. */
- Rm = ~Rm;
+ Rm = ~Rm;
if ((Rm & 0xFFFFFF00) == 0)
scount = 1;
diff --git a/Src/ARMulator/thumbemu.cpp b/Src/ARMulator/thumbemu.cpp
index 4bb906bb..69efea8a 100644
--- a/Src/ARMulator/thumbemu.cpp
+++ b/Src/ARMulator/thumbemu.cpp
@@ -5,12 +5,12 @@
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.
-
+
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
@@ -56,7 +56,7 @@ handle_v6_thumb_insn (ARMul_State * state,
case 0xba40: /* rev16 */
case 0xbac0: /* revsh */
case 0xb650: /* setend */
- default:
+ default:
printf ("Unhandled v6 thumb insn: %04x\n", tinstr);
* pvalid = t_undefined;
return;
@@ -270,7 +270,7 @@ ARMul_ThumbDecode (ARMul_State * state,
| ((tinstr & 0x0078) >> 3); /* Rd */
break;
}
- /* Drop through. */
+ /* Fall through. */
case 0x0: /* UNDEFINED */
case 0x4: /* UNDEFINED */
case 0x8: /* UNDEFINED */
@@ -412,14 +412,14 @@ ARMul_ThumbDecode (ARMul_State * state,
case 0x0e00:
if (state->is_v5)
{
- /* This is normally an undefined instruction. The v5t architecture
+ /* This is normally an undefined instruction. The v5t architecture
defines this particular pattern as a BKPT instruction, for
hardware assisted debugging. We map onto the arm BKPT
instruction. */
* ainstr = 0xE1200070 | ((tinstr & 0xf0) << 4) | (tinstr & 0xf);
break;
}
- /* Drop through. */
+ /* Fall through. */
default:
/* Everything else is an undefined instruction. */
handle_v6_thumb_insn (state, tinstr, & valid);
@@ -533,7 +533,7 @@ ARMul_ThumbDecode (ARMul_State * state,
break;
}
/* Drop through. */
-
+
/* Format 19 */
/* There is no single ARM instruction equivalent for this
instruction. Also, it should only ever be matched with the
diff --git a/Src/SprowCoPro.cpp b/Src/SprowCoPro.cpp
index e512e4d6..768287cd 100644
--- a/Src/SprowCoPro.cpp
+++ b/Src/SprowCoPro.cpp
@@ -22,7 +22,6 @@ Boston, MA 02110-1301, USA.
#include
#include
-
#include
#include
@@ -159,9 +158,11 @@ For the new test suite Abort between 8 Mbytes and 26 Mbytes */
int SWI_vector_installed = FALSE;
int tenval = 1;
+
#define PRIMEPIPE 4
#define RESUME 8
#define FLUSHPIPE state->NextInstr |= PRIMEPIPE
+
unsigned
ARMul_OSHandleSWI (ARMul_State * state, ARMword number)
{
@@ -424,7 +425,7 @@ PutWord (ARMul_State * state, ARMword address, ARMword data, int /* check */)
\***************************************************************************/
unsigned
-ARMul_MemoryInit (ARMul_State * state, ARMword initmemsize)
+ARMul_MemoryInit (ARMul_State * state, unsigned long initmemsize)
{
if (initmemsize)
state->MemSize = initmemsize;
@@ -797,7 +798,6 @@ ARMul_Ccycles (ARMul_State * state, unsigned number, ARMword /* address */)
ARMul_CLEARABORT;
}
-
/* Read a byte. Do not check for alignment or access errors. */
ARMword
From 374b3e2c15954c7bbd9d4aa0ca2cfd647a0f4644 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 24 Aug 2024 20:06:25 +0100
Subject: [PATCH 041/101] Added const
---
Src/ARMulator/armdis.cpp | 44 +++++++++++++++++++++-------------------
1 file changed, 23 insertions(+), 21 deletions(-)
diff --git a/Src/ARMulator/armdis.cpp b/Src/ARMulator/armdis.cpp
index 962076f4..a603de72 100644
--- a/Src/ARMulator/armdis.cpp
+++ b/Src/ARMulator/armdis.cpp
@@ -27,31 +27,31 @@
struct Opcodes {
u32 mask;
u32 cval;
- char *mnemonic;
+ const char *mnemonic;
};
-const char hdig[] = "0123456789abcdef";
+static const char hdig[] = "0123456789abcdef";
-const char *decVals[16] = {
+static const char *decVals[16] = {
"0","1","2","3","4","5","6","7","8",
"9","10","11","12","13","14","15"
};
-const char *regs[16] = {
+static const char *regs[16] = {
"r0","r1","r2","r3","r4","r5","r6","r7",
"r8","r9","r10","r11","r12","sp","lr","pc"
};
-const char *conditions[16] = {
+static const char *conditions[16] = {
"eq","ne","cs","cc","mi","pl","vs","vc",
"hi","ls","ge","lt","gt","le","","nv"
};
-const char *shifts[5] = {
+static const char *shifts[5] = {
"lsl","lsr","asr","ror","rrx"
};
-const char *armMultLoadStore[12] = {
+static const char *armMultLoadStore[12] = {
// non-stack
"da","ia","db","ib",
// stack store
@@ -60,7 +60,7 @@ const char *armMultLoadStore[12] = {
"fa","fd","ea","ed"
};
-const Opcodes thumbOpcodes[] = {
+static const Opcodes thumbOpcodes[] = {
// Format 1
{0xf800, 0x0000, "lsl %r0, %r3, %o"},
{0xf800, 0x0800, "lsr %r0, %r3, %o"},
@@ -123,11 +123,11 @@ const Opcodes thumbOpcodes[] = {
// Format 13
{0xff00, 0xb000, "add sp, %s"},
// Format 14
- {0xffff, 0xb500, "push {lr}"},
+ {0xffff, 0xb500, "push {lr}"},
{0xff00, 0xb400, "push {%l}"},
{0xff00, 0xb500, "push {%l,lr}"},
{0xffff, 0xbd00, "pop {pc}"},
- {0xff00, 0xbd00, "pop {%l,pc}"},
+ {0xff00, 0xbd00, "pop {%l,pc}"},
{0xff00, 0xbc00, "pop {%l}"},
// Format 15
{0xf800, 0xc000, "stmia %r8!, {%l}"},
@@ -221,7 +221,7 @@ char* addHex(char *dest, int siz, u32 val){
int disArm(ARMul_State * state, u32 offset, char *dest, int flags)
{
u32 opcode = ARMul_ReadWord(state, offset);
-
+
const Opcodes *sp = armOpcodes;
while( sp->cval != (opcode & sp->mask) )
sp++;
@@ -235,8 +235,9 @@ int disArm(ARMul_State * state, u32 offset, char *dest, int flags)
*dest++ = ' ';
}
- char *src = sp->mnemonic;
- while (*src){
+ const char *src = sp->mnemonic;
+
+ while (*src) {
if (*src!='%')
*dest++ = *src++;
else{
@@ -420,7 +421,7 @@ int disArm(ARMul_State * state, u32 offset, char *dest, int flags)
if(opcode & 0x00100000)
dest = addStr(dest, armMultLoadStore[8+((opcode>>23)&3)]);
else
- dest = addStr(dest, armMultLoadStore[4+((opcode>>23)&3)]);
+ dest = addStr(dest, armMultLoadStore[4+((opcode>>23)&3)]);
} else
dest = addStr(dest, armMultLoadStore[(opcode>>23)&3]);
break;
@@ -529,19 +530,19 @@ int disArm(ARMul_State * state, u32 offset, char *dest, int flags)
}
}
*dest++ = 0;
-
+
return 4;
}
int disThumb(ARMul_State * state, u32 offset, char *dest, int flags)
{
u32 opcode = ARMul_ReadWord(state, offset);
-
+
const Opcodes *sp = thumbOpcodes;
int ret = 2;
while( sp->cval != (opcode & sp->mask) )
sp++;
-
+
if (flags&DIS_VIEW_ADDRESS){
dest = addHex(dest, 32, offset);
*dest++ = ' ';
@@ -550,9 +551,10 @@ int disThumb(ARMul_State * state, u32 offset, char *dest, int flags)
dest = addHex(dest, 16, opcode);
*dest++ = ' ';
}
-
- char *src = sp->mnemonic;
- while (*src){
+
+ const char *src = sp->mnemonic;
+
+ while (*src) {
if (*src!='%')
*dest++ = *src++;
else {
@@ -626,7 +628,7 @@ int disThumb(ARMul_State * state, u32 offset, char *dest, int flags)
if(*s) {
*dest++ = ' ';
dest = addStr(dest, s);
- } */
+ } */
}
break;
case 'b':
From a3da8149d646dd87435aaf9d8b2db6af972bf84d Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 24 Aug 2024 20:13:25 +0100
Subject: [PATCH 042/101] Fixed compiler warnings
---
Src/BeebWinDx.cpp | 2 +-
Src/BeebWinPrefs.cpp | 6 +++---
Src/Csw.cpp | 2 +-
Src/Debug.cpp | 5 +++--
Src/DiscEdit.cpp | 3 ++-
Src/PALRom.cpp | 2 +-
Src/Speech.cpp | 7 +++++--
Src/Uef.cpp | 2 +-
8 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/Src/BeebWinDx.cpp b/Src/BeebWinDx.cpp
index 1cd90b21..e1b235e1 100644
--- a/Src/BeebWinDx.cpp
+++ b/Src/BeebWinDx.cpp
@@ -1169,7 +1169,7 @@ void BeebWin::UpdateMotionBlurMenu()
UINT SelectedMenuItemID = 0;
- for (int i = 0; i < _countof(MenuItems); i++)
+ for (size_t i = 0; i < _countof(MenuItems); i++)
{
if (m_MotionBlur == MenuItems[i].MotionBlur)
{
diff --git a/Src/BeebWinPrefs.cpp b/Src/BeebWinPrefs.cpp
index 0d57f6f4..ba706ac4 100644
--- a/Src/BeebWinPrefs.cpp
+++ b/Src/BeebWinPrefs.cpp
@@ -1175,11 +1175,11 @@ void BeebWin::LoadSerialPortPreferences(int Version)
isxdigit(m_SerialPort[0]) &&
isxdigit(m_SerialPort[1]))
{
- int Port;
+ unsigned int Port;
sscanf(m_SerialPort.c_str(), "%x", &Port);
char PortName[20];
- sprintf(PortName, "COM%d", Port);
+ sprintf(PortName, "COM%u", Port);
m_SerialPort = PortName;
}
}
@@ -1378,7 +1378,7 @@ void BeebWin::LoadTeletextAdapterPreferences(int Version)
m_Preferences.GetDWORDValue(key, Value, TELETEXT_BASE_PORT + ch);
- if (Value >= 0 && Value <= 65535)
+ if (Value <= 65535)
{
TeletextPort[ch] = (u_short)Value;
}
diff --git a/Src/Csw.cpp b/Src/Csw.cpp
index 5e760748..7003a3fc 100644
--- a/Src/Csw.cpp
+++ b/Src/Csw.cpp
@@ -182,7 +182,7 @@ void HexDump(const char *buff, int count)
void CSWCreateTapeMap(std::vector& TapeMap)
{
CSWState last_state = CSWState::Undefined;
- char block[65535];
+ unsigned char block[65535];
int block_ptr = -1;
int n;
diff --git a/Src/Debug.cpp b/Src/Debug.cpp
index 948745cf..a6bfafc5 100644
--- a/Src/Debug.cpp
+++ b/Src/Debug.cpp
@@ -1076,6 +1076,7 @@ void DebugCloseDialog()
}
//*******************************************************************
+
void DebugDisplayInfoF(const char *format, ...)
{
va_list args;
@@ -1979,7 +1980,7 @@ static void DebugExecuteCommand()
void DebugInitMemoryMaps()
{
- for(int i = 0; i < _countof(MemoryMaps); i++)
+ for (size_t i = 0; i < _countof(MemoryMaps); i++)
{
MemoryMaps[i].clear();
}
@@ -2016,7 +2017,7 @@ bool DebugLoadMemoryMap(const char* filename, int bank)
char desc[256];
memset(desc, 0, sizeof(desc));
- int result = sscanf(buf, "%x %x %99c", &entry.start, &entry.end, desc);
+ int result = sscanf(buf, "%x %x %99c", (unsigned int*)&entry.start, (unsigned int*)&entry.end, desc);
if (result >= 2 && strlen(desc) > 0)
{
diff --git a/Src/DiscEdit.cpp b/Src/DiscEdit.cpp
index 1c2d75c1..b3b86fac 100644
--- a/Src/DiscEdit.cpp
+++ b/Src/DiscEdit.cpp
@@ -385,9 +385,10 @@ bool dfs_import_file(const char *szDiscFile,
int fileLen = -1;
FILE* filefd = fopen(infname, "rb");
+
if (filefd != NULL)
{
- if (fscanf(filefd, "%9s %X %X", dfsname, &loadAddr, &execAddr) < 1)
+ if (fscanf(filefd, "%9s %X %X", dfsname, (unsigned int*)&loadAddr, (unsigned int*)&execAddr) < 1)
{
sprintf(szErrStr, "Failed to read file attributes from:\n %s", infname);
success = false;
diff --git a/Src/PALRom.cpp b/Src/PALRom.cpp
index 7f950e62..2ca0d95e 100644
--- a/Src/PALRom.cpp
+++ b/Src/PALRom.cpp
@@ -237,7 +237,7 @@ PALRomType GuessRomType(uint8_t *Rom, uint32_t Size)
char RomName[11];
memcpy(RomName, &Rom[9], 10);
RomName[10] = '\0';
- int Crc = (int)crc32(0, Rom, Size);
+ unsigned int Crc = crc32(0, Rom, Size);
if (strstr(RomName, "ViewSpell") && Size == PALROM_64K && Crc == 0xE56B0E01)
{
diff --git a/Src/Speech.cpp b/Src/Speech.cpp
index 5e8a645e..82c345bb 100644
--- a/Src/Speech.cpp
+++ b/Src/Speech.cpp
@@ -1059,6 +1059,9 @@ bool TMS5220::ParseFrame(bool first_frame)
bits = m_fifo_count * 8 - m_fifo_bits_taken;
}
+ int rep_flag;
+ int indx;
+
// Attempt to extract the energy index
if (m_speak_external)
{
@@ -1067,7 +1070,7 @@ bool TMS5220::ParseFrame(bool first_frame)
goto ranout;
}
- int indx = ExtractBits(4);
+ indx = ExtractBits(4);
m_new_energy = energytable[indx] >> 6;
// If the index is 0 or 15, we're done
@@ -1095,7 +1098,7 @@ bool TMS5220::ParseFrame(bool first_frame)
goto ranout;
}
- int rep_flag = ExtractBits(1);
+ rep_flag = ExtractBits(1);
// Attempt to extract the pitch
if (m_speak_external)
diff --git a/Src/Uef.cpp b/Src/Uef.cpp
index dc8f69da..0d5affcb 100644
--- a/Src/Uef.cpp
+++ b/Src/Uef.cpp
@@ -491,7 +491,7 @@ void UEFFileReader::CreateTapeMap(std::vector& TapeMap)
{
bool done = false;
int blk = 0;
- char block[500];
+ unsigned char block[500];
bool std_last_block = true;
// SetClock(TapeClockSpeed);
From c0e202818ea4e41f6ca950fc7f333259aa2c6162 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 24 Aug 2024 20:13:49 +0100
Subject: [PATCH 043/101] Removed unused code
---
Src/Video.cpp | 47 +++--------------------------------------------
1 file changed, 3 insertions(+), 44 deletions(-)
diff --git a/Src/Video.cpp b/Src/Video.cpp
index 7b6f7a62..36dafb7c 100644
--- a/Src/Video.cpp
+++ b/Src/Video.cpp
@@ -651,56 +651,15 @@ static void DoFastTable() {
}
/*-------------------------------------------------------------------------------------------------------------*/
-#define BEEB_DOTIME_SAMPLESIZE 50
-
-static void VideoStartOfFrame(void) {
-#ifdef BEEB_DOTIME
- static int Have_GotTime=0;
- static struct tms previous,now;
- static int Time_FrameCount=0;
-
- double frametime;
- static CycleCountT OldCycles=0;
-
- if (!Have_GotTime) {
- times(&previous);
- Time_FrameCount=-1;
- Have_GotTime=1;
- }
-
- if (Time_FrameCount==(BEEB_DOTIME_SAMPLESIZE-1)) {
- times(&now);
- frametime=now.tms_utime-previous.tms_utime;
-#ifndef SUNOS
-#ifndef HPUX
- frametime/=(double)CLOCKS_PER_SEC;
-#else
- frametime/=(double)sysconf(_SC_CLK_TCK);
-#endif
-#else
- frametime/=(double)HZ;
-#endif
- frametime/=(double)BEEB_DOTIME_SAMPLESIZE;
- cerr << "Frametime: " << frametime << "s fps=" << (1/frametime) << "Total cycles=" << TotalCycles << "Cycles in last unit=" << (TotalCycles-OldCycles) << "\n";
- OldCycles=TotalCycles;
- previous=now;
- Time_FrameCount=0;
- } else Time_FrameCount++;
-
-#endif
+static void VideoStartOfFrame()
+{
/* FrameNum is determined by the window handler */
if (VideoState.IsNewTVFrame) // RTW - only calibrate timing once per frame
{
VideoState.IsNewTVFrame = false;
-#ifdef WIN32
+
FrameNum = mainWin->StartOfFrame();
-#else
- /* If FrameNum hits 0 we actually refresh */
- if (FrameNum--==0) {
- FrameNum=Video_RefreshFrequency-1;
- }
-#endif
CursorFieldCount--;
Mode7FlashTrigger--;
From 0af9aae5b6b4310aa47a7326a244ffad50cd1199 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 24 Aug 2024 20:15:58 +0100
Subject: [PATCH 044/101] Use StrCaseCmp() function
---
Src/Econet.cpp | 20 ++++++++++----------
Src/FileType.cpp | 25 +++++++++++++++----------
2 files changed, 25 insertions(+), 20 deletions(-)
diff --git a/Src/Econet.cpp b/Src/Econet.cpp
index 37717e39..bbf97ab5 100644
--- a/Src/Econet.cpp
+++ b/Src/Econet.cpp
@@ -819,39 +819,39 @@ static void ReadEconetConfigFile()
try
{
- if (_stricmp(Key.c_str(), "AUNMODE") == 0)
+ if (StrCaseCmp(Key.c_str(), "AUNMODE") == 0)
{
AUNMode = std::stoi(Value) != 0;
}
- else if (_stricmp(Key.c_str(), "LEARN") == 0)
+ else if (StrCaseCmp(Key.c_str(), "LEARN") == 0)
{
LearnMode = std::stoi(Value) != 0;
}
- else if (_stricmp(Key.c_str(), "AUNSTRICT") == 0)
+ else if (StrCaseCmp(Key.c_str(), "AUNSTRICT") == 0)
{
StrictAUNMode = std::stoi(Value) != 0;
}
- else if (_stricmp(Key.c_str(), "SINGLESOCKET") == 0)
+ else if (StrCaseCmp(Key.c_str(), "SINGLESOCKET") == 0)
{
SingleSocket = std::stoi(Value) != 0;
}
- else if (_stricmp(Key.c_str(), "FLAGFILLTIMEOUT") == 0)
+ else if (StrCaseCmp(Key.c_str(), "FLAGFILLTIMEOUT") == 0)
{
EconetFlagFillTimeout = std::stoi(Value);
}
- else if (_stricmp(Key.c_str(), "SCACKTIMEOUT") == 0)
+ else if (StrCaseCmp(Key.c_str(), "SCACKTIMEOUT") == 0)
{
EconetSCACKtimeout = std::stoi(Value);
}
- else if (_stricmp(Key.c_str(), "TIMEBETWEENBYTES") == 0)
+ else if (StrCaseCmp(Key.c_str(), "TIMEBETWEENBYTES") == 0)
{
TimeBetweenBytes = std::stoi(Value);
}
- else if (_stricmp(Key.c_str(), "FOURWAYTIMEOUT") == 0)
+ else if (StrCaseCmp(Key.c_str(), "FOURWAYTIMEOUT") == 0)
{
FourWayStageTimeout = std::stoi(Value);
}
- else if (_stricmp(Key.c_str(), "MASSAGENETS") == 0)
+ else if (StrCaseCmp(Key.c_str(), "MASSAGENETS") == 0)
{
MassageNetworks = std::stoi(Value) != 0;
}
@@ -908,7 +908,7 @@ static void ReadAUNConfigFile()
ParseConfigLine(Line, Tokens);
- if (Tokens.size() == 3 && _stricmp("ADDMAP", Tokens[0].c_str()) == 0)
+ if (Tokens.size() == 3 && StrCaseCmp("ADDMAP", Tokens[0].c_str()) == 0)
{
if (aunnetp < AUN_TABLE_LENGTH)
{
diff --git a/Src/FileType.cpp b/Src/FileType.cpp
index 6fa439cf..e5e4cf33 100644
--- a/Src/FileType.cpp
+++ b/Src/FileType.cpp
@@ -21,6 +21,9 @@ Boston, MA 02110-1301, USA.
#include
#include "FileType.h"
+#include "StringUtils.h"
+
+/****************************************************************************/
FileType GetFileTypeFromExtension(const char* FileName)
{
@@ -30,43 +33,43 @@ FileType GetFileTypeFromExtension(const char* FileName)
if (Ext != nullptr)
{
- if (_stricmp(Ext + 1, "ssd") == 0)
+ if (StrCaseCmp(Ext + 1, "ssd") == 0)
{
Type = FileType::SSD;
}
- else if (_stricmp(Ext + 1, "dsd") == 0)
+ else if (StrCaseCmp(Ext + 1, "dsd") == 0)
{
Type = FileType::DSD;
}
- else if (_stricmp(Ext + 1, "adl") == 0)
+ else if (StrCaseCmp(Ext + 1, "adl") == 0)
{
Type = FileType::ADFS;
}
- else if (_stricmp(Ext + 1, "adf") == 0)
+ else if (StrCaseCmp(Ext + 1, "adf") == 0)
{
Type = FileType::ADFS;
}
- else if (_stricmp(Ext + 1, "uef") == 0)
+ else if (StrCaseCmp(Ext + 1, "uef") == 0)
{
Type = FileType::UEF;
}
- else if (_stricmp(Ext + 1, "uefstate") == 0)
+ else if (StrCaseCmp(Ext + 1, "uefstate") == 0)
{
Type = FileType::UEFState;
}
- else if (_stricmp(Ext + 1, "csw") == 0)
+ else if (StrCaseCmp(Ext + 1, "csw") == 0)
{
Type = FileType::CSW;
}
- else if (_stricmp(Ext + 1, "img") == 0)
+ else if (StrCaseCmp(Ext + 1, "img") == 0)
{
Type = FileType::IMG;
}
- else if (_stricmp(Ext + 1, "dos") == 0)
+ else if (StrCaseCmp(Ext + 1, "dos") == 0)
{
Type = FileType::DOS;
}
- else if (_stricmp(Ext + 1, "fsd") == 0)
+ else if (StrCaseCmp(Ext + 1, "fsd") == 0)
{
Type = FileType::FSD;
}
@@ -74,3 +77,5 @@ FileType GetFileTypeFromExtension(const char* FileName)
return Type;
}
+
+/****************************************************************************/
From a8db1384e59763b89b27219732f4ef4b1868537a Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 24 Aug 2024 20:16:22 +0100
Subject: [PATCH 045/101] Fixed BeebWin::LoadCapturePreferences()
---
Src/BeebWinPrefs.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Src/BeebWinPrefs.cpp b/Src/BeebWinPrefs.cpp
index ba706ac4..0038d901 100644
--- a/Src/BeebWinPrefs.cpp
+++ b/Src/BeebWinPrefs.cpp
@@ -1459,9 +1459,9 @@ void BeebWin::LoadCapturePreferences(int Version)
switch (Value)
{
- case 40185: m_VideoCaptureResolution = VideoCaptureResolution::Display;
- case 40186: default: m_VideoCaptureResolution = VideoCaptureResolution::_640x512;
- case 40187: m_VideoCaptureResolution = VideoCaptureResolution::_320x256;
+ case 40185: m_VideoCaptureResolution = VideoCaptureResolution::Display; break;
+ case 40186: default: m_VideoCaptureResolution = VideoCaptureResolution::_640x512; break;
+ case 40187: m_VideoCaptureResolution = VideoCaptureResolution::_320x256; break;
}
}
From f89d78ad891bfb1fa919c0c33ae47a9361f03884 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 24 Aug 2024 20:16:41 +0100
Subject: [PATCH 046/101] Fixed compiler warnings
---
Src/BeebWinSpeech.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Src/BeebWinSpeech.cpp b/Src/BeebWinSpeech.cpp
index a0086cca..1d503e66 100644
--- a/Src/BeebWinSpeech.cpp
+++ b/Src/BeebWinSpeech.cpp
@@ -1007,8 +1007,8 @@ void BeebWin::TextViewSetCursorPos(int line, int col)
void BeebWin::TextViewSyncWithBeebCursor()
{
// Move speech cursor to Beeb's cursor pos
- int CurAddr = CRTC_CursorPosLow + (((CRTC_CursorPosHigh ^ 0x20) + 0x74 & 0xff) << 8);
- int ScrAddr = CRTC_ScreenStartLow + (((CRTC_ScreenStartHigh ^ 0x20) + 0x74 & 0xff) << 8);
+ int CurAddr = CRTC_CursorPosLow + ((((CRTC_CursorPosHigh ^ 0x20) + 0x74) & 0xff) << 8);
+ int ScrAddr = CRTC_ScreenStartLow + ((((CRTC_ScreenStartHigh ^ 0x20) + 0x74) & 0xff) << 8);
int RelAddr = CurAddr - ScrAddr;
m_SpeechLine = RelAddr / CRTC_HorizontalDisplayed;
From 667b6a9d4c52e8ac64d7eeb596bd6e15f6b59b56 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 24 Aug 2024 20:23:52 +0100
Subject: [PATCH 047/101] Improved socket code portability
---
Src/BeebEm.vcxproj | 2 +
Src/BeebEm.vcxproj.filters | 6 +++
Src/Econet.cpp | 52 ++++++++++---------
Src/IP232.cpp | 17 +++---
Src/Socket.cpp | 103 +++++++++++++++++++++++++++++++++++++
Src/Socket.h | 33 ++++++++++++
Src/Teletext.cpp | 64 ++++++++++++++---------
7 files changed, 220 insertions(+), 57 deletions(-)
create mode 100644 Src/Socket.cpp
create mode 100644 Src/Socket.h
diff --git a/Src/BeebEm.vcxproj b/Src/BeebEm.vcxproj
index c3b4889f..5c1204c2 100644
--- a/Src/BeebEm.vcxproj
+++ b/Src/BeebEm.vcxproj
@@ -225,6 +225,7 @@
+
@@ -396,6 +397,7 @@
+
diff --git a/Src/BeebEm.vcxproj.filters b/Src/BeebEm.vcxproj.filters
index ae1b13c3..8a17d655 100644
--- a/Src/BeebEm.vcxproj.filters
+++ b/Src/BeebEm.vcxproj.filters
@@ -204,6 +204,9 @@
Source Files
+
+ Source Files
+
Source Files
@@ -509,6 +512,9 @@
Header Files
+
+ Header Files
+
Header Files
diff --git a/Src/Econet.cpp b/Src/Econet.cpp
index bbf97ab5..79058529 100644
--- a/Src/Econet.cpp
+++ b/Src/Econet.cpp
@@ -44,6 +44,7 @@ Boston, MA 02110-1301, USA.
#include "DebugTrace.h"
#include "Main.h"
#include "Rtc.h"
+#include "Socket.h"
#include "StringUtils.h"
// Emulated 6854 ADLC control registers.
@@ -381,7 +382,7 @@ static void EconetError(const char *Format, ...);
static const char* IpAddressStr(unsigned long inet_addr)
{
in_addr in;
- in.S_un.S_addr = inet_addr;
+ IN_ADDR(in) = inet_addr;
return inet_ntoa(in);
}
@@ -423,7 +424,7 @@ static ECOLAN* FindHost(sockaddr_in* pAddress)
for (int i = 0; i < networkp; i++)
{
if (pAddress->sin_port == htons(network[i].port) &&
- pAddress->sin_addr.s_addr == network[i].inet_addr)
+ S_ADDR(*pAddress) == network[i].inet_addr)
{
return &network[i];
}
@@ -517,10 +518,10 @@ void EconetReset()
{
if (!SingleSocket)
{
- closesocket(SendSocket);
+ CloseSocket(SendSocket);
}
- closesocket(ListenSocket);
+ CloseSocket(ListenSocket);
ReceiverSocketsOpen = false;
}
@@ -535,7 +536,7 @@ void EconetReset()
// Create a SOCKET for listening for incoming connection requests.
ListenSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (ListenSocket == INVALID_SOCKET) {
- EconetError("Econet: Failed to open listening socket (error %ld)", WSAGetLastError());
+ EconetError("Econet: Failed to open listening socket (error %ld)", GetLastSocketError());
return;
}
@@ -565,12 +566,12 @@ void EconetReset()
}
service.sin_port = htons(EconetListenPort);
- service.sin_addr.s_addr = EconetListenIP;
+ S_ADDR(service) = EconetListenIP;
if (bind(ListenSocket, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR)
{
- EconetError("Econet: Failed to bind to port %d (error %ld)", EconetListenPort, WSAGetLastError());
- closesocket(ListenSocket);
+ EconetError("Econet: Failed to bind to port %d (error %ld)", EconetListenPort, GetLastSocketError());
+ CloseSocket(ListenSocket);
ListenSocket = INVALID_SOCKET;
return;
}
@@ -595,10 +596,10 @@ void EconetReset()
memcpy(&localaddr, host->h_addr_list[a], sizeof(struct in_addr));
if (network[i].inet_addr == inet_addr("127.0.0.1") ||
- network[i].inet_addr == localaddr.S_un.S_addr)
+ network[i].inet_addr == IN_ADDR(localaddr))
{
service.sin_port = htons(network[i].port);
- service.sin_addr.s_addr = network[i].inet_addr;
+ S_ADDR(service) = network[i].inet_addr;
if (bind(ListenSocket, (SOCKADDR*)&service, sizeof(service)) == 0)
{
@@ -626,17 +627,17 @@ void EconetReset()
struct in_addr localaddr;
memcpy(&localaddr, host->h_addr_list[a], sizeof(struct in_addr));
- if (aunnet[j].inet_addr == (localaddr.S_un.S_addr & 0x00FFFFFF))
+ if (aunnet[j].inet_addr == (IN_ADDR(localaddr) & 0x00FFFFFF))
{
service.sin_port = htons(DEFAULT_AUN_PORT);
- service.sin_addr.s_addr = localaddr.S_un.S_addr;
+ S_ADDR(service) = IN_ADDR(localaddr);
if (bind(ListenSocket, (SOCKADDR*)&service, sizeof(service)) == 0)
{
myaunnet = j;
- network[networkp].inet_addr = EconetListenIP = localaddr.S_un.S_addr;
+ network[networkp].inet_addr = EconetListenIP = IN_ADDR(localaddr);
network[networkp].port = EconetListenPort = DEFAULT_AUN_PORT;
- network[networkp].station = EconetStationID = localaddr.S_un.S_addr >> 24;
+ network[networkp].station = EconetStationID = IN_ADDR(localaddr) >> 24;
network[networkp].network = aunnet[j].network;
networkp++;
}
@@ -682,8 +683,8 @@ void EconetReset()
SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (SendSocket == INVALID_SOCKET) {
- EconetError("Econet: Failed to open sending socket (error %ld)", WSAGetLastError());
- closesocket(ListenSocket);
+ EconetError("Econet: Failed to open sending socket (error %ld)", GetLastSocketError());
+ CloseSocket(ListenSocket);
ListenSocket = INVALID_SOCKET;
return;
}
@@ -694,8 +695,8 @@ void EconetReset()
if (setsockopt(SendSocket, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) == -1)
{
- EconetError("Econet: Failed to set socket for broadcasts (error %ld)", WSAGetLastError());
- closesocket(ListenSocket);
+ EconetError("Econet: Failed to set socket for broadcasts (error %ld)", GetLastSocketError());
+ CloseSocket(ListenSocket);
ListenSocket = INVALID_SOCKET;
return;
}
@@ -1368,7 +1369,7 @@ bool EconetPoll_real() // return NMI status
// TODO lookup destnet in aunnet() and use proper ip address!
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(DEFAULT_AUN_PORT);
- RecvAddr.sin_addr.s_addr = INADDR_BROADCAST; // ((EconetListenIP & 0x00FFFFFF) | 0xFF000000);
+ S_ADDR(RecvAddr) = INADDR_BROADCAST; // ((EconetListenIP & 0x00FFFFFF) | 0xFF000000);
SendMe = true;
}
else
@@ -1426,7 +1427,7 @@ bool EconetPoll_real() // return NMI status
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(network[i].port);
- RecvAddr.sin_addr.s_addr = network[i].inet_addr;
+ S_ADDR(RecvAddr) = network[i].inet_addr;
}
//if (DebugEnabled)
@@ -1436,7 +1437,7 @@ bool EconetPoll_real() // return NMI status
BeebTx.Pointer,
(unsigned int)BeebTx.eh.destnet,
(unsigned int)BeebTx.eh.deststn,
- IpAddressStr(RecvAddr.sin_addr.s_addr),
+ IpAddressStr(S_ADDR(RecvAddr)),
(unsigned int)htons(RecvAddr.sin_port));
std::string str = "Econet: Packet data:" + BytesToString(BeebTx.buff, BeebTx.Pointer);
@@ -1711,7 +1712,7 @@ bool EconetPoll_real() // return NMI status
FD_ZERO(&ReadFds);
FD_SET(ListenSocket, &ReadFds);
- static const timeval TimeOut = {0, 0};
+ timeval TimeOut = {0, 0};
int RetVal = select((int)ListenSocket + 1, &ReadFds, NULL, NULL, &TimeOut);
@@ -1738,7 +1739,7 @@ bool EconetPoll_real() // return NMI status
DebugDisplayTraceF(DebugType::Econet, true,
"EconetPoll: Packet received: %u bytes from %s port %u",
(int)RetVal,
- IpAddressStr(RecvAddr.sin_addr.s_addr),
+ IpAddressStr(S_ADDR(RecvAddr)),
htons(RecvAddr.sin_port));
std::string str = "EconetPoll: Packet data:" + BytesToString(AUNMode ? EconetRx.raw : BeebRx.buff, RetVal);
@@ -1878,7 +1879,8 @@ bool EconetPoll_real() // return NMI status
case FourWayStage::DataSent:
// we sent block of data, awaiting final ack..
- if (EconetRx.ah.type == AUNType::Ack || EconetRx.ah.type == AUNType::NAck) {
+ if (EconetRx.ah.type == AUNType::Ack || EconetRx.ah.type == AUNType::NAck)
+ {
// are we expecting a (N)ACK ?
// TODO check it is a (n)ack for packet we just sent!!, deal with naks!
// construct a final ack for the beeb
@@ -1938,7 +1940,7 @@ bool EconetPoll_real() // return NMI status
}
else if (RetVal == SOCKET_ERROR && !SingleSocket)
{
- EconetError("Econet: Failed to receive packet (error %ld)", WSAGetLastError());
+ EconetError("Econet: Failed to receive packet (error %ld)", GetLastSocketError());
}
}
else if (RetVal == SOCKET_ERROR)
diff --git a/Src/IP232.cpp b/Src/IP232.cpp
index a965a59a..6a48831d 100644
--- a/Src/IP232.cpp
+++ b/Src/IP232.cpp
@@ -45,6 +45,7 @@ Boston, MA 02110-1301, USA.
#include "Messages.h"
#include "RingBuffer.h"
#include "Serial.h"
+#include "Socket.h"
#include "StringUtils.h"
#include "Thread.h"
@@ -205,11 +206,11 @@ void IP232Close()
if (DebugEnabled)
DebugDisplayTrace(DebugType::RemoteServer, true, "IP232: Closing socket");
- int Result = closesocket(EthernetSocket);
+ int Result = CloseSocket(EthernetSocket);
if (Result == SOCKET_ERROR)
{
- DebugTrace("closesocket() returned error %d\n", WSAGetLastError());
+ DebugTrace("closesocket() returned error %d\n", GetLastSocketError());
}
EthernetSocket = INVALID_SOCKET;
@@ -307,7 +308,7 @@ unsigned int EthernetPortReadThread::ThreadFunc()
{
fd_set fds;
FD_ZERO(&fds);
- static const timeval TimeOut = {0, 0};
+ timeval TimeOut = {0, 0};
FD_SET(EthernetSocket, &fds);
@@ -315,7 +316,7 @@ unsigned int EthernetPortReadThread::ThreadFunc()
if (NumReady == SOCKET_ERROR)
{
- DebugTrace("Read Select Error %d\n", WSAGetLastError());
+ DebugTrace("Read Select Error %d\n", GetLastSocketError());
if (DebugEnabled)
DebugDisplayTrace(DebugType::RemoteServer, true, "IP232: Select error on read");
@@ -336,7 +337,7 @@ unsigned int EthernetPortReadThread::ThreadFunc()
Close = true;
// Should really check what the error was ...
- int Error = WSAGetLastError();
+ int Error = GetLastSocketError();
DebugTrace("Read error %d, remote session disconnected\n", Error);
@@ -366,7 +367,7 @@ unsigned int EthernetPortReadThread::ThreadFunc()
fd_set fds;
FD_ZERO(&fds);
- static const timeval TimeOut = {0, 0};
+ timeval TimeOut = {0, 0};
FD_SET(EthernetSocket, &fds);
@@ -374,7 +375,7 @@ unsigned int EthernetPortReadThread::ThreadFunc()
if (NumReady == SOCKET_ERROR)
{
- DebugTrace("Write Select Error %d\n", WSAGetLastError());
+ DebugTrace("Write Select Error %d\n", GetLastSocketError());
if (DebugEnabled)
DebugDisplayTrace(DebugType::RemoteServer, true, "IP232: Select error on write");
@@ -388,7 +389,7 @@ unsigned int EthernetPortReadThread::ThreadFunc()
Close = true;
// Should really check what the error was ...
- int Error = WSAGetLastError();
+ int Error = GetLastSocketError();
DebugTrace("Send Error %i, Error %d\n", BytesSent, Error);
diff --git a/Src/Socket.cpp b/Src/Socket.cpp
new file mode 100644
index 00000000..f84097a0
--- /dev/null
+++ b/Src/Socket.cpp
@@ -0,0 +1,103 @@
+/****************************************************************
+BeebEm - BBC Micro and Master 128 Emulator
+Copyright (C) 2024 Chris Needham
+
+This program 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.
+
+This program 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 this program; if not, write to the Free
+Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
+****************************************************************/
+
+#include
+
+#include "Socket.h"
+
+#ifndef WIN32
+#include
+#include
+#endif
+
+/****************************************************************************/
+
+int CloseSocket(SOCKET Socket)
+{
+ #ifdef WIN32
+
+ return closesocket(Socket);
+
+ #else
+
+ return close(Socket);
+
+ #endif
+}
+
+/****************************************************************************/
+
+int GetLastSocketError()
+{
+ #ifdef WIN32
+
+ return WSAGetLastError();
+
+ #else
+
+ return errno;
+
+ #endif
+}
+
+/****************************************************************************/
+
+bool SetSocketBlocking(SOCKET Socket, bool Blocking)
+{
+ #ifdef WIN32
+
+ unsigned long Mode = Blocking ? 0 : 1;
+ return ioctlsocket(Socket, FIONBIO, &Mode) == 0;
+
+ #else
+
+ int Flags = fcntl(Socket, F_GETFL, 0);
+ if (Flags == -1) return false;
+
+ if (Blocking)
+ {
+ Flags &= ~O_NONBLOCK;
+ }
+ else
+ {
+ Flags |= O_NONBLOCK
+ }
+
+ return fcntl(Socket, F_SETFL, Flags) == 0;
+
+ #endif
+}
+
+/****************************************************************************/
+
+bool WouldBlock(int Error)
+{
+#ifdef WIN32
+
+ return Error == WSAEWOULDBLOCK;
+
+#else
+
+ return Error == EWOULDBLOCK; // TODO: EAGAIN?
+
+#endif
+}
+
+/****************************************************************************/
diff --git a/Src/Socket.h b/Src/Socket.h
new file mode 100644
index 00000000..2b056231
--- /dev/null
+++ b/Src/Socket.h
@@ -0,0 +1,33 @@
+/****************************************************************
+BeebEm - BBC Micro and Master 128 Emulator
+Copyright (C) 2024 Chris Needham
+
+This program 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.
+
+This program 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 this program; if not, write to the Free
+Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
+****************************************************************/
+
+#ifndef SOCKET_HEADER
+#define SOCKET_HEADER
+
+int CloseSocket(SOCKET Socket);
+int GetLastSocketError();
+bool SetSocketBlocking(SOCKET Socket, bool Blocking);
+bool WouldBlock(int Error);
+
+#define S_ADDR(s) (s).sin_addr.s_addr
+
+#define IN_ADDR(addr) (addr).s_addr
+
+#endif
diff --git a/Src/Teletext.cpp b/Src/Teletext.cpp
index dcc51885..90ab434e 100644
--- a/Src/Teletext.cpp
+++ b/Src/Teletext.cpp
@@ -60,6 +60,7 @@ Control latch:
#include "Debug.h"
#include "Log.h"
#include "Main.h"
+#include "Socket.h"
#define ENABLE_LOG 0
@@ -100,6 +101,24 @@ static char TeletextSocketBuff[4][672*2] = {0}; // hold one frame of t42 data (2
static bool TeletextConnect(int ch);
static void CloseTeletextSocket(int Index);
+bool ConnectSocket(SOCKET Socket, const sockaddr* Name, int Length)
+{
+ #ifdef WIN32
+
+ if (connect(Socket, Name, Length) == SOCKET_ERROR)
+ {
+ return WSAGetLastError() != WSAEWOULDBLOCK; // WSAEWOULDBLOCK is expected
+ }
+
+ #else
+
+ return connect(Socket, Name, Length) == EAGAIN;
+
+ #endif
+
+ return false;
+}
+
/*--------------------------------------------------------------------------*/
// Initiate connection on socket
@@ -127,29 +146,25 @@ static bool TeletextConnect(int ch)
"Teletext: socket %d created, connecting to server", ch);
}
- u_long iMode = 1;
- ioctlsocket(TeletextSocket[ch], FIONBIO, &iMode); // non blocking
+ SetSocketBlocking(TeletextSocket[ch], false); // non blocking
struct sockaddr_in teletext_serv_addr;
teletext_serv_addr.sin_family = AF_INET; // address family Internet
teletext_serv_addr.sin_port = htons(TeletextPort[ch]); // Port to connect on
teletext_serv_addr.sin_addr.s_addr = inet_addr(TeletextIP[ch].c_str()); // Target IP
- if (connect(TeletextSocket[ch], (SOCKADDR *)&teletext_serv_addr, sizeof(teletext_serv_addr)) == SOCKET_ERROR)
+ if (!ConnectSocket(TeletextSocket[ch], (SOCKADDR *)&teletext_serv_addr, sizeof(teletext_serv_addr)))
{
- if (WSAGetLastError() != WSAEWOULDBLOCK) // WSAEWOULDBLOCK is expected
+ if (DebugEnabled)
{
- if (DebugEnabled)
- {
- DebugDisplayTraceF(DebugType::Teletext, true,
- "Teletext: Socket %d unable to connect to server %s:%d %d",
- ch, TeletextIP[ch].c_str(), TeletextPort[ch],
- WSAGetLastError());
- }
-
- CloseTeletextSocket(ch);
- return false;
+ DebugDisplayTraceF(DebugType::Teletext, true,
+ "Teletext: Socket %d unable to connect to server %s:%d %d",
+ ch, TeletextIP[ch].c_str(), TeletextPort[ch],
+ GetLastSocketError());
}
+
+ CloseTeletextSocket(ch);
+ return false;
}
// How long should we wait (in emulated video fields) for a connection
@@ -163,7 +178,7 @@ static bool TeletextConnect(int ch)
static void CloseTeletextSocket(int Index)
{
- closesocket(TeletextSocket[Index]);
+ CloseSocket(TeletextSocket[Index]);
TeletextSocket[Index] = INVALID_SOCKET;
TeletextConnectTimeout[Index] = 0;
}
@@ -373,7 +388,7 @@ void TeletextAdapterUpdate()
if (TeletextSource == TeletextSourceType::IP)
{
char tmpBuff[672*20]; // big enough to hold 20 fields of data
-
+
if (!(TeletextCurrentField&1)) // an even field
{
for (int i = 0; i < TELETEXT_CHANNEL_COUNT; i++)
@@ -386,13 +401,13 @@ void TeletextAdapterUpdate()
unsigned long n;
if (ioctlsocket(TeletextSocket[i], FIONREAD, &n) == SOCKET_ERROR)
{
- int err = WSAGetLastError();
+ int Error = GetLastSocketError();
if (DebugEnabled)
{
DebugDisplayTraceF(DebugType::Teletext, true,
"Teletext: FIONREAD error %d. Closing socket %d",
- err, i);
+ Error, i);
}
CloseTeletextSocket(i);
@@ -419,13 +434,13 @@ void TeletextAdapterUpdate()
if (result != (672*20))
{
// read failed, probably fatal.
- int err = WSAGetLastError();
+ int Error = GetLastSocketError();
if (DebugEnabled)
{
DebugDisplayTraceF(DebugType::Teletext, true,
"Teletext: discard recv error %d. Closing socket %d",
- err, i);
+ Error, i);
}
CloseTeletextSocket(i);
@@ -442,15 +457,16 @@ void TeletextAdapterUpdate()
if (result == 0 || result == SOCKET_ERROR)
{
- int err = WSAGetLastError();
+ int Error = GetLastSocketError();
- if (err == WSAEWOULDBLOCK)
+ if (WouldBlock(Error))
{
if (DebugEnabled)
{
DebugDisplayTraceF(DebugType::Teletext, true,
"Teletext: WSAEWOULDBLOCK in socket %d. Skipping field",i);
}
+
if (TeletextConnectTimeout[i] > 0)
{
TeletextConnectTimeout[i]--;
@@ -462,7 +478,7 @@ void TeletextAdapterUpdate()
{
DebugDisplayTraceF(DebugType::Teletext, true,
"Teletext: recv error %d. Closing socket %d",
- err, i);
+ Error, i);
}
CloseTeletextSocket(i);
@@ -518,7 +534,7 @@ void TeletextAdapterUpdate()
}
}
}
-
+
TeletextCurrentField ^= 1; // toggle field
}
else
From ce59afd7322682c356f7f49c6e07ddccc855c00d Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 24 Aug 2024 20:26:38 +0100
Subject: [PATCH 048/101] Moved MonitorType and SoundStreamerType to their own
files
---
Src/BeebEm.vcxproj | 2 ++
Src/BeebEm.vcxproj.filters | 6 ++++++
Src/BeebWin.h | 16 ++--------------
Src/MonitorType.h | 32 ++++++++++++++++++++++++++++++++
Src/SoundStreamerType.h | 30 ++++++++++++++++++++++++++++++
5 files changed, 72 insertions(+), 14 deletions(-)
create mode 100644 Src/MonitorType.h
create mode 100644 Src/SoundStreamerType.h
diff --git a/Src/BeebEm.vcxproj b/Src/BeebEm.vcxproj
index 5c1204c2..f70cd265 100644
--- a/Src/BeebEm.vcxproj
+++ b/Src/BeebEm.vcxproj
@@ -380,6 +380,7 @@
+
@@ -400,6 +401,7 @@
+
diff --git a/Src/BeebEm.vcxproj.filters b/Src/BeebEm.vcxproj.filters
index 8a17d655..3598051b 100644
--- a/Src/BeebEm.vcxproj.filters
+++ b/Src/BeebEm.vcxproj.filters
@@ -461,6 +461,9 @@
Header Files
+
+ Header Files
+
Header Files
@@ -518,6 +521,9 @@
Header Files
+
+ Header Files
+
Header Files
diff --git a/Src/BeebWin.h b/Src/BeebWin.h
index 66cb97d5..2c2df788 100644
--- a/Src/BeebWin.h
+++ b/Src/BeebWin.h
@@ -43,8 +43,10 @@ Boston, MA 02110-1301, USA.
#include "DiscType.h"
#include "KeyMap.h"
#include "Model.h"
+#include "MonitorType.h"
#include "Port.h"
#include "Preferences.h"
+#include "SoundStreamerType.h"
#include "Tube.h"
#include "Video.h"
@@ -141,14 +143,6 @@ enum class MessageResult
Cancel
};
-enum class MonitorType
-{
- RGB,
- BW,
- Amber,
- Green
-};
-
enum class DisplayRendererType
{
GDI,
@@ -156,12 +150,6 @@ enum class DisplayRendererType
DirectX9
};
-enum class SoundStreamerType
-{
- XAudio2,
- DirectSound
-};
-
enum class JoystickOption
{
Disabled,
diff --git a/Src/MonitorType.h b/Src/MonitorType.h
new file mode 100644
index 00000000..f7ce3e09
--- /dev/null
+++ b/Src/MonitorType.h
@@ -0,0 +1,32 @@
+/****************************************************************
+BeebEm - BBC Micro and Master 128 Emulator
+Copyright (C) 2024 Chris Needham
+
+This program 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.
+
+This program 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 this program; if not, write to the Free
+Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
+****************************************************************/
+
+#ifndef MONITORTYPE_HEADER
+#define MONITORTYPE_HEADER
+
+enum class MonitorType
+{
+ RGB,
+ BW,
+ Amber,
+ Green
+};
+
+#endif
diff --git a/Src/SoundStreamerType.h b/Src/SoundStreamerType.h
new file mode 100644
index 00000000..3a3e554b
--- /dev/null
+++ b/Src/SoundStreamerType.h
@@ -0,0 +1,30 @@
+/****************************************************************
+BeebEm - BBC Micro and Master 128 Emulator
+Copyright (C) 2024 Chris Needham
+
+This program 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.
+
+This program 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 this program; if not, write to the Free
+Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
+****************************************************************/
+
+#ifndef SOUND_STREAMER_TYPE_HEADER
+#define SOUND_STREAMER_TYPE_HEADER
+
+enum class SoundStreamerType
+{
+ XAudio2,
+ DirectSound
+};
+
+#endif
From 481a6a3f891ea4ec681d19cb2b15c1ad94b2a16f Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 24 Aug 2024 20:47:20 +0100
Subject: [PATCH 049/101] Minor refactoring
---
Src/Disc1770.cpp | 22 ++++++++++++++--------
Src/FileDialog.cpp | 2 +-
Src/RomConfigFile.cpp | 8 ++++----
Src/SelectKeyDialog.h | 4 ++--
Src/Sound.h | 2 +-
Src/UserKeyboardDialog.cpp | 2 +-
6 files changed, 23 insertions(+), 17 deletions(-)
diff --git a/Src/Disc1770.cpp b/Src/Disc1770.cpp
index 28e857fc..26894ddf 100644
--- a/Src/Disc1770.cpp
+++ b/Src/Disc1770.cpp
@@ -882,13 +882,15 @@ void Poll1770(int NCycles) {
NMIStatus |= 1 << nmi_floppy;
}
- if (FDCommand == 10) {
+ if (FDCommand == 10)
+ {
Status &= ~(WD1770_STATUS_WRITE_PROTECT |
WD1770_STATUS_SPIN_UP_COMPLETE |
WD1770_STATUS_RECORD_NOT_FOUND |
WD1770_STATUS_BUSY);
- if (NextFDCommand == 255) {
+ if (NextFDCommand == 255)
+ {
// Error during access
UpdateTR00Status();
@@ -896,6 +898,7 @@ void Poll1770(int NCycles) {
Status &= ~WD1770_STATUS_CRC_ERROR;
}
+
NMIStatus |= 1 << nmi_floppy;
FDCommand = 12;
LoadingCycles = SPIN_DOWN_TIME; // Spin-down delay
@@ -1223,11 +1226,15 @@ void Close1770Disc(int Drive)
}
}
-#define BPUT(a) fputc(a, file); CheckSum = (CheckSum + a) & 0xff
+#define BPUT(a) \
+ do { \
+ fputc(a, file); CheckSum = (CheckSum + (a)) & 0xff; \
+ } while (0)
// This function creates a blank ADFS disc image.
-bool CreateADFSImage(const char *FileName, int Tracks) {
+bool CreateADFSImage(const char *FileName, int Tracks)
+{
int ent;
const int sectors = (Tracks * 16);
FILE *file = fopen(FileName, "wb");
@@ -1357,7 +1364,7 @@ void Load1770UEF(FILE *SUEF, int Version)
DiscInfo[1].Type = static_cast(UEFRead8(SUEF));
char FileName[256];
- memset(FileName, 0, sizeof(FileName));
+ ZeroMemory(FileName, sizeof(FileName));
if (Version >= 14)
{
@@ -1377,7 +1384,7 @@ void Load1770UEF(FILE *SUEF, int Version)
LoadFailed = true;
}
- memset(FileName, 0, sizeof(FileName));
+ ZeroMemory(FileName, sizeof(FileName));
if (Version >= 14)
{
@@ -1445,7 +1452,7 @@ void Load1770UEF(FILE *SUEF, int Version)
SelectedDensity = UEFReadBool(SUEF);
RotSect = UEFRead8(SUEF);
- memset(FDCDLL, 0, sizeof(FDCDLL));
+ ZeroMemory(FDCDLL, sizeof(FDCDLL));
if (Version >= 14)
{
@@ -1462,4 +1469,3 @@ void Load1770UEF(FILE *SUEF, int Version)
}
}
}
-
diff --git a/Src/FileDialog.cpp b/Src/FileDialog.cpp
index 510fd7b6..0d273379 100644
--- a/Src/FileDialog.cpp
+++ b/Src/FileDialog.cpp
@@ -26,7 +26,7 @@ Boston, MA 02110-1301, USA.
FileDialog::FileDialog(HWND hwndOwner, LPTSTR result, DWORD resultLength,
LPCTSTR initialFolder, LPCTSTR filter)
{
- memset(&m_ofn, 0, sizeof(m_ofn));
+ ZeroMemory(&m_ofn, sizeof(m_ofn));
m_ofn.lStructSize = sizeof(OPENFILENAME);
m_ofn.hwndOwner = hwndOwner;
diff --git a/Src/RomConfigFile.cpp b/Src/RomConfigFile.cpp
index d06a51b8..f4ff2a4e 100644
--- a/Src/RomConfigFile.cpp
+++ b/Src/RomConfigFile.cpp
@@ -20,16 +20,16 @@ Boston, MA 02110-1301, USA.
#include
+#include
+#include
+#include
+
#include "RomConfigFile.h"
#include "BeebWin.h"
#include "FileUtils.h"
#include "Main.h"
#include "StringUtils.h"
-#include
-#include
-#include
-
/****************************************************************************/
const char *BANK_EMPTY = "EMPTY";
diff --git a/Src/SelectKeyDialog.h b/Src/SelectKeyDialog.h
index 45782b8e..2420565d 100644
--- a/Src/SelectKeyDialog.h
+++ b/Src/SelectKeyDialog.h
@@ -12,8 +12,8 @@ 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 this program; if not, write to the Free
+You should have received a copy of the GNU General Public
+License along with this program; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
****************************************************************/
diff --git a/Src/Sound.h b/Src/Sound.h
index 70a88ca9..52afaf54 100644
--- a/Src/Sound.h
+++ b/Src/Sound.h
@@ -76,7 +76,7 @@ void SetSound(SoundState state);
struct AudioType {
char Signal; // Signal type: data, gap, or tone.
char BytePos; // Position in data byte
- bool Enabled; // Enable state of audio deooder
+ bool Enabled; // Enable state of audio decoder
int Data; // The actual data itself
int Samples; // Samples counted in current pattern till changepoint
char CurrentBit; // Current bit in data being processed
diff --git a/Src/UserKeyboardDialog.cpp b/Src/UserKeyboardDialog.cpp
index 9c8088c4..e9d09ec8 100644
--- a/Src/UserKeyboardDialog.cpp
+++ b/Src/UserKeyboardDialog.cpp
@@ -392,7 +392,7 @@ static void DrawBorder(HDC hDC, RECT rect, BOOL Depressed)
DrawSides(hDC, rect, 0x00000000, 0x00FFFFFF);
else
DrawSides(hDC, rect, 0x00FFFFFF, 0x00000000);
-
+
// Draw inner border.
rect.top++;
rect.left++;
From 3ecbc09fcd7a628accd7977d13e66d67a2a0059b Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 24 Aug 2024 20:47:59 +0100
Subject: [PATCH 050/101] Fixed compiler warnings
---
Src/Disc8271.cpp | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/Src/Disc8271.cpp b/Src/Disc8271.cpp
index 933c93cf..37ca6c6d 100644
--- a/Src/Disc8271.cpp
+++ b/Src/Disc8271.cpp
@@ -2536,6 +2536,7 @@ Disc8271Result LoadFSDDiscImage(const char *FileName, int DriveNum)
unsigned char Info[5];
Input.read((char *)Info, sizeof(Info));
+ #if DEBUG_8271
const int Day = Info[0] >> 3;
const int Month = Info[2] & 0x0F;
const int Year = ((Info[0] & 0x07) << 8) | Info[1];
@@ -2543,6 +2544,10 @@ Disc8271Result LoadFSDDiscImage(const char *FileName, int DriveNum)
const int CreatorID = Info[2] >> 4;
const int Release = ((Info[4] >> 6) << 8) | Info[3];
+ DebugTrace("8271: FSD File: %s, Day: %d, Month: %d, Year, %d, CreatorID: %d, Release: %d\n",
+ FileName, Day, Month, Year, CreatorID, Release);
+ #endif
+
std::string DiscTitle;
char TitleChar = 1;
@@ -2562,7 +2567,8 @@ Disc8271Result LoadFSDDiscImage(const char *FileName, int DriveNum)
for (int Track = 0; Track < DiscStatus[DriveNum].TotalTracks; Track++)
{
- /* unsigned char TrackNumber = */(unsigned char)Input.get(); // Read current track details
+ // unsigned char TrackNumber = (unsigned char)Input.get();
+ Input.get(); // Read current track details
unsigned char SectorsPerTrack = (unsigned char)Input.get(); // Read number of sectors on track
DiscStatus[DriveNum].Tracks[Head][Track].LogicalSectors = SectorsPerTrack;
From 141add66bcab066faf23fa58d55fd18f3870e99b Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 24 Aug 2024 20:48:25 +0100
Subject: [PATCH 051/101] Fixed 1770 FDC emulation
The intent seemed to be to update both FDCommand
and NextFDCommand?
---
Src/Disc1770.cpp | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/Src/Disc1770.cpp b/Src/Disc1770.cpp
index 26894ddf..5147b129 100644
--- a/Src/Disc1770.cpp
+++ b/Src/Disc1770.cpp
@@ -940,7 +940,13 @@ void Poll1770(int NCycles) {
Status |= WD1770_STATUS_SPIN_UP_COMPLETE;
}
- if (LoadingCycles <= 0) FDCommand = 10; NextFDCommand = 255; // Go to spin down, but report error.
+ if (LoadingCycles <= 0)
+ {
+ // Go to spin down, but report error.
+ FDCommand = 10;
+ NextFDCommand = 255;
+ }
+
SpinDown[CurrentDrive] = SPIN_DOWN_TIME;
LightsOn[CurrentDrive] = true;
return;
From c1f199661bcef3fcc5fbc264478ec79f004f7975 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 24 Aug 2024 20:50:26 +0100
Subject: [PATCH 052/101] Minor tidy up
---
Src/BeebWin.h | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/Src/BeebWin.h b/Src/BeebWin.h
index 2c2df788..4f27236c 100644
--- a/Src/BeebWin.h
+++ b/Src/BeebWin.h
@@ -284,23 +284,23 @@ class BeebWin
}
void doUHorizLine(int Colour, int y, int sx, int width) {
- if (TeletextEnabled) y/=TeletextStyle;
- if (y>500) return;
- memset(m_screen+ (y* 800) + sx, Colour, width);
+ if (TeletextEnabled) y /= TeletextStyle;
+ if (y > 500) return;
+ memset(m_screen + (y * 800) + sx, Colour, width);
}
EightUChars *GetLinePtr(int y) {
- int d = (y*800)+ScreenAdjust;
- if (d > (MAX_VIDEO_SCAN_LINES*800))
- return((EightUChars *)(m_screen+(MAX_VIDEO_SCAN_LINES*800)));
- return((EightUChars *)(m_screen + d));
+ int d = (y * 800) + ScreenAdjust;
+ if (d > MAX_VIDEO_SCAN_LINES * 800)
+ return (EightUChars *)(m_screen + MAX_VIDEO_SCAN_LINES * 800);
+ return (EightUChars *)(m_screen + d);
}
SixteenUChars *GetLinePtr16(int y) {
- int d = (y*800)+ScreenAdjust;
- if (d > (MAX_VIDEO_SCAN_LINES*800))
- return((SixteenUChars *)(m_screen+(MAX_VIDEO_SCAN_LINES*800)));
- return((SixteenUChars *)(m_screen + d));
+ int d = (y * 800) + ScreenAdjust;
+ if (d > MAX_VIDEO_SCAN_LINES * 800)
+ return (SixteenUChars *)(m_screen + MAX_VIDEO_SCAN_LINES * 800);
+ return (SixteenUChars *)(m_screen + d);
}
HWND GethWnd() { return m_hWnd; }
From cca990d7e5f7b476e5347d52f0d9c159b6680fc6 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 24 Aug 2024 20:50:45 +0100
Subject: [PATCH 053/101] Fixed compiler warning on switch fall through
---
Src/Master512CoPro.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Src/Master512CoPro.cpp b/Src/Master512CoPro.cpp
index 10547ca9..497b03ed 100644
--- a/Src/Master512CoPro.cpp
+++ b/Src/Master512CoPro.cpp
@@ -2673,7 +2673,8 @@ void Master512CoPro::Execute(int Cycles)
break;
}
}
- // through to default
+ // Fall through...
+
default:
if (!common_op(op))
{
From 752f8d3540e5d753c2221966b56a4deb49a94087 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 24 Aug 2024 20:51:08 +0100
Subject: [PATCH 054/101] Use KEYMAP_SIZE constant
---
Src/KeyMap.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Src/KeyMap.cpp b/Src/KeyMap.cpp
index 96cee1e2..2e622a00 100644
--- a/Src/KeyMap.cpp
+++ b/Src/KeyMap.cpp
@@ -90,7 +90,7 @@ bool ReadKeyMap(const char *filename, KeyMap *keymap)
{
fgets(buf, 255, infile);
- for (int i = 0; i < 256; ++i)
+ for (int i = 0; i < KEYMAP_SIZE; ++i)
{
if (fgets(buf, 255, infile) == NULL)
{
From 300a86e30bcf53dc45974b64d585bdee57673c28 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 24 Aug 2024 20:51:36 +0100
Subject: [PATCH 055/101] Use built-in data types
---
Src/Music5000.cpp | 76 +++++++++++++++++++++++------------------------
1 file changed, 38 insertions(+), 38 deletions(-)
diff --git a/Src/Music5000.cpp b/Src/Music5000.cpp
index 81e2e516..768040f2 100644
--- a/Src/Music5000.cpp
+++ b/Src/Music5000.cpp
@@ -33,7 +33,7 @@ Boston, MA 02110-1301, USA.
#include "UefState.h"
bool Music5000Enabled = false;
-UINT8 JimPageSelectRegister;
+unsigned char JimPageSelectRegister;
extern int SoundVolume;
#define RAM_SIZE 2048
@@ -58,44 +58,44 @@ extern int SoundVolume;
struct CHANNELREGS
{
- UINT8 FreqLo[NUM_CHANNELS];
- UINT8 FreqMed[NUM_CHANNELS];
- UINT8 FreqHi[NUM_CHANNELS];
- UINT8 Unused1[NUM_CHANNELS];
- UINT8 Unused2[NUM_CHANNELS];
- UINT8 WaveformReg[NUM_CHANNELS];
- UINT8 AmplitudeReg[NUM_CHANNELS];
- UINT8 ControlReg[NUM_CHANNELS];
+ unsigned char FreqLo[NUM_CHANNELS];
+ unsigned char FreqMed[NUM_CHANNELS];
+ unsigned char FreqHi[NUM_CHANNELS];
+ unsigned char Unused1[NUM_CHANNELS];
+ unsigned char Unused2[NUM_CHANNELS];
+ unsigned char WaveformReg[NUM_CHANNELS];
+ unsigned char AmplitudeReg[NUM_CHANNELS];
+ unsigned char ControlReg[NUM_CHANNELS];
};
struct WAVERAM
{
- UINT8 WaveTable[WAVE_TABLES][WAVE_TABLE_SIZE];
+ unsigned char WaveTable[WAVE_TABLES][WAVE_TABLE_SIZE];
CHANNELREGS ChannelRegs[NUM_REG_SETS]; // Normal & Alt
};
-static UINT8 WaveRam[RAM_SIZE];
+static unsigned char WaveRam[RAM_SIZE];
static WAVERAM* pWaveRam = (WAVERAM*)WaveRam;
-static UINT32 PhaseRam[NUM_CHANNELS];
+static unsigned int PhaseRam[NUM_CHANNELS];
static const double ChordBase[8] = { 0, 8.25, 24.75, 57.75, 123.75, 255.75, 519.75, 1047.75 };
static const double StepInc[8] = { 0.5, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0 };
-static INT D2ATable[128];
+static int D2ATable[128];
-static const INT StereoLeft[16] = { 0, 0, 0, 0, 0, 0, 0, 0,100,100,100, 83, 67, 50, 33, 17 };
-static const INT StereoRight[16] = { 100,100,100,100,100,100,100,100, 0, 0, 0, 17, 33, 50, 67, 83 };
+static const int StereoLeft[16] = { 0, 0, 0, 0, 0, 0, 0, 0,100,100,100, 83, 67, 50, 33, 17 };
+static const int StereoRight[16] = { 100,100,100,100,100,100,100,100, 0, 0, 0, 17, 33, 50, 67, 83 };
// 6MHz clock, 128 cycles to update all channels
-static UINT CycleCount = 0;
+static unsigned int CycleCount = 0;
-static INT16 *SampleBuf = nullptr;
-static UINT32 SampleBufSize = 0;
-static UINT32 SampleWritePtr = 0;
+static short *SampleBuf = nullptr;
+static unsigned int SampleBufSize = 0;
+static unsigned int SampleWritePtr = 0;
-static UINT CurCh;
-static UINT ActiveRegSet;
-static INT SampleLeft;
-static INT SampleRight;
+static unsigned int CurCh;
+static unsigned int ActiveRegSet;
+static int SampleLeft;
+static int SampleRight;
static SoundStreamer *pSoundStreamer = nullptr;
@@ -103,8 +103,8 @@ void Music5000Init()
{
static_assert(sizeof(WAVERAM) == RAM_SIZE, "WAVERAM size");
- memset(WaveRam, 0, sizeof(WaveRam));
- memset(PhaseRam, 0, sizeof(PhaseRam));
+ ZeroMemory(WaveRam, sizeof(WaveRam));
+ ZeroMemory(PhaseRam, sizeof(PhaseRam));
CycleCount = 0;
CurCh = 0;
ActiveRegSet = REG_SET_NORMAL;
@@ -138,10 +138,10 @@ void Music5000Init()
else
{
pSoundStreamer->Play();
- SampleBufSize = (UINT32)pSoundStreamer->BufferSize();
+ SampleBufSize = (unsigned int)pSoundStreamer->BufferSize();
if (SampleBuf)
free(SampleBuf);
- SampleBuf = (INT16*)malloc(SampleBufSize * 4);
+ SampleBuf = (short*)malloc(SampleBufSize * 4);
if (SampleBuf == nullptr)
{
Music5000Enabled = false;
@@ -213,15 +213,15 @@ bool Music5000Read(int address, unsigned char *value)
void Music5000Update(UINT cycles)
{
CHANNELREGS *pChRegs;
- UINT32 freq;
- UINT c4d;
- UINT wavetable, offset;
- UINT amplitude;
- UINT control;
- UINT data;
- UINT sign;
- UINT pos;
- INT sample;
+ unsigned int freq;
+ unsigned int c4d;
+ unsigned int wavetable, offset;
+ unsigned int amplitude;
+ unsigned int control;
+ unsigned int data;
+ unsigned int sign;
+ unsigned int pos;
+ int sample;
// Convert 2MHz 6502 cycles to 6MHz Music5000 cycles
CycleCount += cycles * 3;
@@ -303,8 +303,8 @@ void Music5000Update(UINT cycles)
else if (SampleRight > 32767)
SampleRight = 32767;
- SampleBuf[SampleWritePtr++] = (INT16)SampleLeft;
- SampleBuf[SampleWritePtr++] = (INT16)SampleRight;
+ SampleBuf[SampleWritePtr++] = (short)SampleLeft;
+ SampleBuf[SampleWritePtr++] = (short)SampleRight;
if (SampleWritePtr/2 >= SampleBufSize)
{
From 9863a66578e92398dbcd6e6f05353e9874518326 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sun, 25 Aug 2024 13:10:34 +0100
Subject: [PATCH 056/101] Added command line parameter length check
---
Src/BeebWin.cpp | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index 4f9f3be1..326e91a3 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -5131,7 +5131,8 @@ void BeebWin::ParseCommandLine()
}
}
- if (CustomData) {
+ if (CustomData)
+ {
m_CustomData = true;
}
}
@@ -5210,11 +5211,25 @@ void BeebWin::ParseCommandLine()
// Assume it's a file name
if (m_CommandLineFileName1[0] == '\0')
{
- strncpy(m_CommandLineFileName1, __argv[i], MAX_PATH);
+ if (strlen(__argv[i]) < MAX_PATH)
+ {
+ strcpy(m_CommandLineFileName1, __argv[i]);
+ }
+ else
+ {
+ invalid = true;
+ }
}
else if (m_CommandLineFileName2[0] == '\0')
{
- strncpy(m_CommandLineFileName2, __argv[i], MAX_PATH);
+ if (strlen(__argv[i]) < MAX_PATH)
+ {
+ strcpy(m_CommandLineFileName2, __argv[i]);
+ }
+ else
+ {
+ invalid = true;
+ }
}
}
From 06307ded6c6730acf520153e4b193b695515fe82 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sun, 25 Aug 2024 13:11:08 +0100
Subject: [PATCH 057/101] Added check for OS ROM file size
---
Src/BeebMem.cpp | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/Src/BeebMem.cpp b/Src/BeebMem.cpp
index a2d23a99..f81278ac 100644
--- a/Src/BeebMem.cpp
+++ b/Src/BeebMem.cpp
@@ -1280,15 +1280,25 @@ void BeebReadRoms()
if (InFile != nullptr)
{
- fread(WholeRam + 0xc000, 1, MAX_ROM_SIZE, InFile);
+ size_t BytesRead = fread(WholeRam + 0xc000, 1, MAX_ROM_SIZE, InFile);
+
fclose(InFile);
+ if (BytesRead != MAX_ROM_SIZE)
+ {
+ mainWin->Report(MessageType::Error,
+ "OS ROM has wrong file size (expected %d bytes):\n %s",
+ OSRomFileName.c_str(),
+ MAX_ROM_SIZE);
+ }
+
// Try to read OS ROM memory map:
std::string MapFileName = ReplaceFileExt(OSRomFileName, ".map");
DebugLoadMemoryMap(MapFileName.c_str(), 16);
}
- else {
+ else
+ {
mainWin->Report(MessageType::Error,
"Cannot open specified OS ROM:\n %s", OSRomFileName.c_str());
}
From 23afc0eeefca6ad8972a91fee3aadafa86275d27 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sun, 25 Aug 2024 15:35:22 +0100
Subject: [PATCH 058/101] Added check for ARM7TDMI co-processor ROM size
---
Src/Arm.cpp | 10 ++++++++++
Src/BeebWin.cpp | 28 ++++++++++++++++++----------
Src/SprowCoPro.cpp | 27 ++++++++++++++++++++-------
Src/SprowCoPro.h | 10 +++++++---
4 files changed, 55 insertions(+), 20 deletions(-)
diff --git a/Src/Arm.cpp b/Src/Arm.cpp
index 224b64e5..e6969933 100644
--- a/Src/Arm.cpp
+++ b/Src/Arm.cpp
@@ -102,6 +102,16 @@ CArm::InitResult CArm::init(const char *ROMPath)
if (ROMFile != nullptr)
{
+ fseek(ROMFile, 0, SEEK_END);
+ long Length = ftell(ROMFile);
+ fseek(ROMFile, 0, SEEK_SET);
+
+ if (Length != ROM_SIZE)
+ {
+ fclose(ROMFile);
+ return InitResult::InvalidROM;
+ }
+
size_t BytesRead = fread(romMemory, 1, ROM_SIZE, ROMFile);
fclose(ROMFile);
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index 326e91a3..29da2d18 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -1057,21 +1057,29 @@ void BeebWin::CreateSprowCoPro()
AppendPath(SprowROMPath, "Sprow.rom");
sprow = new CSprowCoPro();
+
CSprowCoPro::InitResult Result = sprow->Init(SprowROMPath);
- switch (Result) {
- case CSprowCoPro::InitResult::FileNotFound:
- Report(MessageType::Error, "ARM7TDMI co-processor ROM file not found:\n %s",
- SprowROMPath);
+ if (Result != CSprowCoPro::InitResult::Success)
+ {
+ DestroySprowCoPro();
- DestroySprowCoPro();
+ TubeType = TubeDevice::None;
+ UpdateTubeMenu();
- TubeType = TubeDevice::None;
- UpdateTubeMenu();
- break;
+ switch (Result)
+ {
+ case CSprowCoPro::InitResult::FileNotFound:
+ Report(MessageType::Error, "ARM7TDMI co-processor ROM file not found:\n %s",
+ SprowROMPath);
- case CSprowCoPro::InitResult::Success:
- break;
+ break;
+
+ case CSprowCoPro::InitResult::InvalidROM:
+ Report(MessageType::Error, "Invalid ARM7TDMI co-processor ROM file (expected 524,288 bytes):\n %s",
+ SprowROMPath);
+ break;
+ }
}
}
diff --git a/Src/SprowCoPro.cpp b/Src/SprowCoPro.cpp
index 768287cd..aa3e6e77 100644
--- a/Src/SprowCoPro.cpp
+++ b/Src/SprowCoPro.cpp
@@ -50,15 +50,28 @@ CSprowCoPro::CSprowCoPro()
CSprowCoPro::InitResult CSprowCoPro::Init(const char* ROMPath)
{
- FILE *testFile = fopen(ROMPath, "rb");
+ FILE * ROMFile = fopen(ROMPath, "rb");
- if (testFile != nullptr)
+ if (ROMFile != nullptr)
{
- fseek(testFile, 0, SEEK_END);
- long length = ftell(testFile);
- fseek(testFile, 0, SEEK_SET);
- fread(m_ROMMemory, length, 1, testFile);
- fclose(testFile);
+ fseek(ROMFile, 0, SEEK_END);
+ long Length = ftell(ROMFile);
+ fseek(ROMFile, 0, SEEK_SET);
+
+ if (Length != ROM_SIZE)
+ {
+ fclose(ROMFile);
+ return InitResult::InvalidROM;
+ }
+
+ size_t BytesRead = fread(m_ROMMemory, 1, ROM_SIZE, ROMFile);
+
+ fclose(ROMFile);
+
+ if (BytesRead != ROM_SIZE)
+ {
+ return InitResult::InvalidROM;
+ }
}
else
{
diff --git a/Src/SprowCoPro.h b/Src/SprowCoPro.h
index f41eabe6..5b2fc2ff 100644
--- a/Src/SprowCoPro.h
+++ b/Src/SprowCoPro.h
@@ -25,9 +25,11 @@ Boston, MA 02110-1301, USA.
class CSprowCoPro
{
public:
- enum class InitResult {
+ enum class InitResult
+ {
Success,
- FileNotFound
+ FileNotFound,
+ InvalidROM
};
public:
@@ -44,7 +46,9 @@ class CSprowCoPro
void LoadState(FILE* SUEF);
private:
- unsigned char m_ROMMemory[0x80000]; // 512 KBytes of rom memory
+ static constexpr int ROM_SIZE = 0x80000; // 512 KBytes of rom memory
+
+ unsigned char m_ROMMemory[ROM_SIZE];
ARMul_State *m_State;
// bool keepRunning; // keep calling run()
int m_CycleCount;
From 5fd68dc730aefbeec5ff7dbbd963586416120e1e Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Wed, 18 Dec 2024 18:35:30 +0000
Subject: [PATCH 059/101] Fixed ConnectSocket()
---
Src/Teletext.cpp | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/Src/Teletext.cpp b/Src/Teletext.cpp
index 90ab434e..65912dba 100644
--- a/Src/Teletext.cpp
+++ b/Src/Teletext.cpp
@@ -105,9 +105,13 @@ bool ConnectSocket(SOCKET Socket, const sockaddr* Name, int Length)
{
#ifdef WIN32
- if (connect(Socket, Name, Length) == SOCKET_ERROR)
+ if (connect(Socket, Name, Length) == 0)
{
- return WSAGetLastError() != WSAEWOULDBLOCK; // WSAEWOULDBLOCK is expected
+ return true;
+ }
+ else
+ {
+ return WSAGetLastError() == WSAEWOULDBLOCK; // WSAEWOULDBLOCK is expected
}
#else
@@ -115,8 +119,6 @@ bool ConnectSocket(SOCKET Socket, const sockaddr* Name, int Length)
return connect(Socket, Name, Length) == EAGAIN;
#endif
-
- return false;
}
/*--------------------------------------------------------------------------*/
From d5e7a949158c8a2f3cd8a02aa1a15d716dba9de1 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Thu, 19 Dec 2024 10:47:44 +0000
Subject: [PATCH 060/101] Fixed econet CTS status bit
See https://www.stardot.org.uk/forums/viewtopic.php?p=430048#p430048
---
CHANGES.md | 4 +++-
Src/Econet.cpp | 2 +-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/CHANGES.md b/CHANGES.md
index 199a4e1c..26a3e6a3 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -5,7 +5,8 @@ Unreleased changes
------------
Contributors: Chris Needham, Mauro Varischetti, Bill Carr, Daniel Beardsmore,
-Steve Inglis, Alistair Cree, Ken Lowe, Mark Usher, Martin Mather, Tom Seddon
+Steve Inglis, Alistair Cree, Ken Lowe, Mark Usher, Martin Mather, Tom Seddon,
+Andrew Hague
* Added support for FSD format disk images. This currently only works
with the 8271 and not the 1770 disk controller.
@@ -25,6 +26,7 @@ Steve Inglis, Alistair Cree, Ken Lowe, Mark Usher, Martin Mather, Tom Seddon
- Fixed potential buffer overflow bug.
- Added support for immediate operations, used by the *VIEW and *NOTIFY
commands. These currently only work under Master series emulation.
+ - Fixed CTS status bit.
* Added Master ET support.
* ROM config files (e.g., Roms.cfg) can now include comments. Note that
files with comments are not backwards compatible with older BeebEm
diff --git a/Src/Econet.cpp b/Src/Econet.cpp
index 79058529..9204c50c 100644
--- a/Src/Econet.cpp
+++ b/Src/Econet.cpp
@@ -2135,7 +2135,7 @@ bool EconetPoll_real() // return NMI status
// and then set the status bit if the line is high! (status bit stays
// up until cpu tries to clear it) (& still stays up if cts line still high)
- if (!(ADLC.control1 && CONTROL_REG1_TX_RESET) && ADLC.cts) // TODO: is && right here?
+ if (!(ADLC.control1 & CONTROL_REG1_RX_RESET) && ADLC.cts)
{
ADLC.status1 |= STATUS_REG1_CTS; // set CTS now
}
From 686466c9b6b7d466b5655176eee7ea014a0cedc2 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Thu, 19 Dec 2024 11:04:39 +0000
Subject: [PATCH 061/101] Updated Master MOS ROM image
The new file includes the comments from FC00 to FF00
---
UserData/BeebFile/M128/MOS.rom | Bin 16384 -> 16384 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
diff --git a/UserData/BeebFile/M128/MOS.rom b/UserData/BeebFile/M128/MOS.rom
index 6430173a8e5806e4fa5d864ee83a70d9d63ba0cf..bf5692717384ba64617f7b51575eed8b244d2731 100644
GIT binary patch
delta 791
zcmYjPL2er{3`8z{2YX8ZHAsOT+M+;UJB?i@4h-8s&ay;%h1HS>{`t%2e}9Q+W#8$VXS3sb;Q~t2oBC
z$g3ZC;u^IW9<{W49PBTx=%ZTm)5Ed~heLbzw6fmCu-jqb)UdMpP3QE_g8y4w<+d&P
zPg#zh3D!k@gPJ_79Ve&DG9<7@JN)}v7tR;bTnW0Dt`^&wS>7{jx*|UE{a-&@A*Ii;
mZQ)rXDu(tb6y+fR}0|NoEL4-CKr1qc*oFlG<}!UQO&KK9|mZy;8H
z0tN=A{~#t05C{MPOx(Khd_AiqpZXS^{|+n+mm5L+R0%$H5iJP+KQNJ$D&K!yqRGI(
z$I!q4;$Ky~|N4qLLp@kP0qg*vaUgeKC16&ON4qf8JN##;cLdS(C^Q>HV6vjU!DIvb
F3jpC+M9=^L
From dc2da72e5fcc330368f5ed538dc9b706b3a59c22 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Mon, 23 Dec 2024 15:46:33 +0000
Subject: [PATCH 062/101] Fixed Master 512 80186 co-pro timing table
---
Src/Master512CoPro.cpp | 126 ++++++++++++++++++++++-------------------
1 file changed, 68 insertions(+), 58 deletions(-)
diff --git a/Src/Master512CoPro.cpp b/Src/Master512CoPro.cpp
index 497b03ed..d2198185 100644
--- a/Src/Master512CoPro.cpp
+++ b/Src/Master512CoPro.cpp
@@ -164,64 +164,74 @@ enum
static const uint8_t Timing[] =
{
- 51,32, // exception, IRET
- 2, 0, 4, 2, // INTs
- 2, // segment overrides
- 2, 4, 4, // flag operations
- 4, 4,83,60, // arithmetic adjusts
- 4, 4, // decimal adjusts
- 2, 5, // sign extension
- 2,24, 2, 2, 3,11, // misc
-
- 15,15,15, // direct JMPs
- 11,18,24, // indirect JMPs
- 19,28, // direct CALLs
- 16,21,37, // indirect CALLs
- 20,32,24,31, // returns
- 4,16, 6,18, // conditional JMPs
- 5,17, 6,18, // loops
-
- 10,14, 8,12, // port reads
- 10,14, 8,12, // port writes
-
- 2, 8, 9, // move, 8-bit
- 4,10, // move, 8-bit immediate
- 2, 8, 9, // move, 16-bit
- 4,10, // move, 16-bit immediate
- 10,10,10,10, // move, AL/AX memory
- 2, 8, 2, 9, // move, segment registers
- 4,17, // exchange, 8-bit
- 4,17, 3, // exchange, 16-bit
-
- 15,24,14,14, // pushes
- 12,25,12,12, // pops
-
- 3, 9,16, // ALU ops, 8-bit
- 4,17,10, // ALU ops, 8-bit immediate
- 3, 9,16, // ALU ops, 16-bit
- 4,17,10, // ALU ops, 16-bit immediate
- 4,17,10, // ALU ops, 16-bit w/8-bit immediate
- 70,118,76,128, // MUL
- 80,128,86,138, // IMUL
- 80,144,86,154, // DIV
- 101,165,107,175, // IDIV
- 3, 2,15,15, // INC/DEC
- 3, 3,16,16, // NEG/NOT
-
- 2, 8, 4, // reg shift/rotate
- 15,20, 4, // m8 shift/rotate
- 15,20, 4, // m16 shift/rotate
-
- 22, 9,21, // CMPS 8-bit
- 22, 9,21, // CMPS 16-bit
- 15, 9,14, // SCAS 8-bit
- 15, 9,14, // SCAS 16-bit
- 12, 9,11, // LODS 8-bit
- 12, 9,11, // LODS 16-bit
- 11, 9,10, // STOS 8-bit
- 11, 9,10, // STOS 16-bit
- 18, 9,17, // MOVS 8-bit
- 18, 9,17, // MOVS 16-bit
+ 45, 28, // exception, IRET
+ 0, 2, 4, 3, // INTs
+ 2, // segment overrides
+ 2, 2, 3, // flag operations
+ 8, 7, 19, 15, // arithmetic adjusts
+ 4, 4, // decimal adjusts
+ 2, 4, // sign extension
+ 2,18, 6, 2, 6,11, // misc
+
+ 14,14,14, // direct JMPs
+ 11,17,26, // indirect JMPs
+ 15,23, // direct CALLs
+ 13,19,38, // indirect CALLs
+ 16,22,18,25, // returns
+ 4,13, 5,15, // conditional JMPs
+ 6,16, 6,16, // loops
+
+ 10,10, 8, 8, // port reads
+ 9, 9, 7, 7, // port writes
+
+ 2, 9,12, // move, 8-bit
+ 3,12, // move, 8-bit immediate
+ 2, 9,12, // move, 16-bit
+ 4,13, // move, 16-bit immediate
+ 8, 8, 9, 9, // move, AL/AX memory
+ 2,11, 2,11, // move, segment registers
+ 4,17, // exchange, 8-bit
+ 4,17, 3, // exchange, 16-bit
+
+ 10,16, 9, 9, // pushes
+ 10,20, 8, 8, // pops
+
+ 3,10,10, // ALU ops, 8-bit
+ 4,16,10, // ALU ops, 8-bit immediate
+ 3,10,10, // ALU ops, 16-bit
+ 4,16,10, // ALU ops, 16-bit immediate
+ 4,16,10, // ALU ops, 16-bit w/8-bit immediate
+ 26,35,32,41, // MUL
+ 25,34,31,40, // IMUL
+ 29,38,35,44, // DIV
+ 44,53,50,59, // IDIV
+ 3, 3,15,15, // INC/DEC
+ 3, 3,10,10, // NEG/NOT
+
+ 2, 5, 1, // reg shift/rotate
+ 15,17, 1, // m8 shift/rotate
+ 15,17, 1, // m16 shift/rotate
+
+ 22, 5,22, // CMPS 8-bit
+ 22, 5,22, // CMPS 16-bit
+ 15, 5,15, // SCAS 8-bit
+ 15, 5,15, // SCAS 16-bit
+ 12, 6,11, // LODS 8-bit
+ 12, 6,11, // LODS 16-bit
+ 10, 6, 9, // STOS 8-bit
+ 10, 6, 9, // STOS 16-bit
+ 14, 8, 8, // MOVS 8-bit
+ 14, 8, 8, // MOVS 16-bit
+
+ 14, 8, 8, // (80186) INS 8-bit
+ 14, 8, 8, // (80186) INS 16-bit
+ 14, 8, 8, // (80186) OUTS 8-bit
+ 14, 8, 8, // (80186) OUTS 16-bit
+ 14,68,83, // (80186) PUSH immediate, PUSHA/POPA
+ 22,29, // (80186) IMUL immediate 8-bit
+ 25,32, // (80186) IMUL immediate 16-bit
+ 15,25,4,16, 8, // (80186) ENTER/LEAVE
+ 33, // (80186) BOUND
};
// DMA control register
From 8a75b5a4c61b7e7fca417ff014b480d29d5789e1 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Mon, 23 Dec 2024 15:55:51 +0000
Subject: [PATCH 063/101] Added error checking reading ROM files
---
Src/BeebMem.cpp | 21 +++++++++--
Src/BeebWin.cpp | 42 +++++++++-------------
Src/Master512CoPro.cpp | 11 ++++--
Src/Speech.cpp | 82 +++++++++++++++++++++++++++++-------------
Src/Tube.cpp | 23 ++++++++----
5 files changed, 118 insertions(+), 61 deletions(-)
diff --git a/Src/BeebMem.cpp b/Src/BeebMem.cpp
index f81278ac..a27e15f4 100644
--- a/Src/BeebMem.cpp
+++ b/Src/BeebMem.cpp
@@ -1215,16 +1215,31 @@ static bool ReadRom(const std::string& RomFileName, int Bank)
long Size = ftell(File);
fseek(File, 0, SEEK_SET);
- if (Size <= MAX_PALROM_SIZE)
+ if (Size == -1)
+ {
+ mainWin->Report(MessageType::Error,
+ "Failed to read ROM file:\n %s", RomFileName.c_str());
+
+ return false;
+ }
+ else if (Size <= MAX_PALROM_SIZE)
{
// Read ROM:
- fread(Roms[Bank], 1, MAX_ROM_SIZE, File);
+ size_t BytesRead = fread(Roms[Bank], 1, MAX_ROM_SIZE, File);
// Read PAL ROM:
fseek(File, 0L, SEEK_SET);
- fread(PALRom[Bank].Rom, 1, Size, File);
+ BytesRead = fread(PALRom[Bank].Rom, 1, Size, File);
fclose(File);
+ if (BytesRead != (size_t)Size)
+ {
+ mainWin->Report(MessageType::Error,
+ "Failed to read ROM file:\n %s", RomFileName.c_str());
+
+ return false;
+ }
+
PALRom[Bank].Type = GuessRomType(PALRom[Bank].Rom, Size);
if (PALRom[Bank].Type != PALRomType::none)
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index 29da2d18..ffde12be 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -1024,17 +1024,15 @@ void BeebWin::CreateArmCoPro()
TubeType = TubeDevice::None;
UpdateTubeMenu();
- switch (Result)
+ if (Result == CArm::InitResult::FileNotFound)
{
- case CArm::InitResult::FileNotFound:
- Report(MessageType::Error, "ARM co-processor ROM file not found:\n %s",
- ArmROMPath);
- break;
-
- case CArm::InitResult::InvalidROM:
- Report(MessageType::Error, "Invalid ARM co-processor ROM file (expected 4096 bytes):\n %s",
- ArmROMPath);
- break;
+ Report(MessageType::Error, "ARM co-processor ROM file not found:\n %s",
+ ArmROMPath);
+ }
+ else if (Result == CArm::InitResult::InvalidROM)
+ {
+ Report(MessageType::Error, "Invalid ARM co-processor ROM file (expected 4096 bytes):\n %s",
+ ArmROMPath);
}
}
}
@@ -1067,18 +1065,15 @@ void BeebWin::CreateSprowCoPro()
TubeType = TubeDevice::None;
UpdateTubeMenu();
- switch (Result)
+ if (Result == CSprowCoPro::InitResult::FileNotFound)
{
- case CSprowCoPro::InitResult::FileNotFound:
- Report(MessageType::Error, "ARM7TDMI co-processor ROM file not found:\n %s",
- SprowROMPath);
-
- break;
-
- case CSprowCoPro::InitResult::InvalidROM:
- Report(MessageType::Error, "Invalid ARM7TDMI co-processor ROM file (expected 524,288 bytes):\n %s",
- SprowROMPath);
- break;
+ Report(MessageType::Error, "ARM7TDMI co-processor ROM file not found:\n %s",
+ SprowROMPath);
+ }
+ else if (Result == CSprowCoPro::InitResult::InvalidROM)
+ {
+ Report(MessageType::Error, "Invalid ARM7TDMI co-processor ROM file (expected 524,288 bytes):\n %s",
+ SprowROMPath);
}
}
}
@@ -3129,11 +3124,8 @@ void BeebWin::AdjustSpeed(bool Up)
10
};
- int Index = 0;
-
if (m_TimingType == TimingType::FixedFPS)
{
- Index = 8;
m_TimingType = TimingType::FixedSpeed;
}
else
@@ -5329,7 +5321,7 @@ bool BeebWin::FindCommandLineFile(char *FileName)
}
char TmpPath[MAX_PATH];
- strncpy(TmpPath, FileName, MAX_PATH);
+ strcpy(TmpPath, FileName);
bool Found = false;
diff --git a/Src/Master512CoPro.cpp b/Src/Master512CoPro.cpp
index d2198185..e112ab2a 100644
--- a/Src/Master512CoPro.cpp
+++ b/Src/Master512CoPro.cpp
@@ -3778,11 +3778,18 @@ void Master512CoPro::LoadBIOS()
if (f != nullptr)
{
- fread(m_Memory + 0xf0000, 0x4000, 1, f);
+ size_t BytesRead = fread(m_Memory + 0xf0000, 1, 0x4000, f);
+
+ fclose(f);
+
+ if (BytesRead != 0x4000)
+ {
+ mainWin->Report(MessageType::Error, "Failed to read BIOS image file:\n %s", PathName);
+ }
+
memcpy(m_Memory + 0xf4000, m_Memory + 0xf0000, 0x4000);
memcpy(m_Memory + 0xf8000, m_Memory + 0xf0000, 0x4000);
memcpy(m_Memory + 0xfc000, m_Memory + 0xf0000, 0x4000);
- fclose(f);
}
else
{
diff --git a/Src/Speech.cpp b/Src/Speech.cpp
index 82c345bb..7319535b 100644
--- a/Src/Speech.cpp
+++ b/Src/Speech.cpp
@@ -43,6 +43,8 @@ POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
+#include
+
#include "Speech.h"
#include "6502core.h"
#include "BeebWin.h"
@@ -50,6 +52,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "Log.h"
#include "Main.h"
#include "Sound.h"
+#include "StringUtils.h"
#if ENABLE_SPEECH
@@ -1394,15 +1397,16 @@ void TMS5220StreamState::Update(unsigned char *buff, int length)
bool SpeechInit()
{
- // Read all ROM files in the BeebFile directory
- // This section rewritten for V.1.32 to take account of roms.cfg file.
+ memset(phrom_rom, 0, sizeof(phrom_rom));
+
+ // Read the PHROM files listed in Phroms.cfg.
char Path[MAX_PATH];
strcpy(Path, mainWin->GetUserDataPath());
AppendPath(Path, "Phroms.cfg");
- FILE *RomCfg = fopen(Path, "rt");
+ std::ifstream RomCfg(Path);
- if (RomCfg == nullptr)
+ if (!RomCfg)
{
mainWin->Report(MessageType::Error, "Cannot open PHROM configuration file:\n %s", Path);
return false;
@@ -1411,42 +1415,72 @@ bool SpeechInit()
bool Success = true;
// Read phroms
- for (int romslot = 15; romslot >= 0; romslot--)
+ int RomSlot = 15;
+
+ std::string Line;
+
+ while (std::getline(RomCfg, Line))
{
- char RomName[80];
- fgets(RomName, 80, RomCfg);
+ trim(Line);
+
+ // Skip blank lines and comments
+ if (Line.empty() || Line[0] == '#')
+ {
+ continue;
+ }
- if (strchr(RomName, 13)) *strchr(RomName, 13) = 0;
- if (strchr(RomName, 10)) *strchr(RomName, 10) = 0;
+ if (Line == "EMPTY")
+ {
+ continue;
+ }
+
+ if (Line.size() >= MAX_PATH)
+ {
+ mainWin->Report(MessageType::Error, "Invalid PHROM configuration file:\n %s", Path);
+ Success = false;
+ break;
+ }
char PhromPath[MAX_PATH];
- strcpy(PhromPath, RomName);
+ strcpy(PhromPath, Line.c_str());
- if (IsRelativePath(RomName))
+ if (IsRelativePath(Line.c_str()))
{
strcpy(PhromPath, mainWin->GetUserDataPath());
AppendPath(PhromPath, "Phroms");
- AppendPath(PhromPath, RomName);
+ AppendPath(PhromPath, Line.c_str());
}
- if (strncmp(RomName, "EMPTY", 5) != 0)
+ FILE *InFile = fopen(PhromPath, "rb");
+
+ if (InFile != nullptr)
{
- FILE *InFile = fopen(PhromPath, "rb");
+ size_t BytesRead = fread(phrom_rom[RomSlot], 1, 16384, InFile);
- if (InFile != nullptr)
- {
- fread(phrom_rom[romslot], 1, 16384, InFile);
- fclose(InFile);
- }
- else
+ fclose(InFile);
+
+ if (BytesRead == 0 || BytesRead % 1024 != 0)
{
- mainWin->Report(MessageType::Error, "Cannot open specified PHROM:\n\n%s", PhromPath);
- Success = false;
+ mainWin->Report(MessageType::Error,
+ "Invalid PHROM file size:\n %s",
+ PhromPath);
}
}
- }
+ else
+ {
+ mainWin->Report(MessageType::Error, "Cannot open specified PHROM:\n\n%s", PhromPath);
+ Success = false;
+ }
- fclose(RomCfg);
+ if (RomSlot == 0)
+ {
+ break;
+ }
+ else
+ {
+ RomSlot--;
+ }
+ }
return Success;
}
diff --git a/Src/Tube.cpp b/Src/Tube.cpp
index a34dd300..6a98c897 100644
--- a/Src/Tube.cpp
+++ b/Src/Tube.cpp
@@ -1532,21 +1532,30 @@ static void Reset65C02()
//The fun part, the tube OS is copied from ROM to tube RAM before the processor starts processing
//This makes the OS "ROM" writable in effect, but must be restored on each reset.
- char TubeRomName[MAX_PATH];
- strcpy(TubeRomName, RomPath);
- AppendPath(TubeRomName, "BeebFile");
- AppendPath(TubeRomName, "6502Tube.rom");
+ char TubeRomPath[MAX_PATH];
+ strcpy(TubeRomPath, RomPath);
+ AppendPath(TubeRomPath, "BeebFile");
+ AppendPath(TubeRomPath, "6502Tube.rom");
+
+ FILE *TubeRom = fopen(TubeRomPath, "rb");
- FILE *TubeRom = fopen(TubeRomName,"rb");
if (TubeRom != nullptr)
{
- fread(TubeRam+0xf800,1,2048,TubeRom);
+ size_t BytesRead = fread(TubeRam + 0xf800, 1, 2048, TubeRom);
+
fclose(TubeRom);
+
+ if (BytesRead != 2048)
+ {
+ mainWin->Report(MessageType::Error,
+ "Invalid Tube ROM file (expected 2,048 bytes):\n %s",
+ TubeRomPath);
+ }
}
else
{
mainWin->Report(MessageType::Error,
- "Cannot open ROM:\n %s", TubeRomName);
+ "Cannot open ROM:\n %s", TubeRomPath);
}
TubeProgramCounter = TubeReadMem(0xfffc);
From 3d549090d36cc469180ef9aff5907f1153881aa5 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Mon, 23 Dec 2024 15:56:27 +0000
Subject: [PATCH 064/101] Fixed compiler warning
---
Src/BeebWin.h | 6 +++---
Src/DiscEdit.cpp | 3 +--
Src/SerialPort.cpp | 4 ++--
Src/UserPortBreakoutBox.cpp | 2 +-
4 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/Src/BeebWin.h b/Src/BeebWin.h
index 4f27236c..dfb30c88 100644
--- a/Src/BeebWin.h
+++ b/Src/BeebWin.h
@@ -598,9 +598,9 @@ class BeebWin
int FindEnum(const std::string& Value, const char* const* Names, int Default);
// Timers
- const int TIMER_KEYBOARD = 1;
- const int TIMER_AUTOBOOT_DELAY = 2;
- const int TIMER_PRINTER = 3;
+ const UINT TIMER_KEYBOARD = 1;
+ const UINT TIMER_AUTOBOOT_DELAY = 2;
+ const UINT TIMER_PRINTER = 3;
// Main window
HWND m_hWnd;
diff --git a/Src/DiscEdit.cpp b/Src/DiscEdit.cpp
index b3b86fac..8d37b13b 100644
--- a/Src/DiscEdit.cpp
+++ b/Src/DiscEdit.cpp
@@ -35,7 +35,6 @@ Boston, MA 02110-1301, USA.
#include "DiscEdit.h"
#include "DiscInfo.h"
-#include "FileDialog.h"
#include "FileUtils.h"
static int DFS_LENGTH_TO_SECTORS(int Length)
@@ -641,7 +640,7 @@ bool dfs_import_file(const char *szDiscFile,
success = false;
}
else if (fwrite(buffer, 1, DFS_SECTOR_SIZE * numSectors, discfd) !=
- (DFS_SECTOR_SIZE * numSectors))
+ (size_t)(DFS_SECTOR_SIZE * numSectors))
{
sprintf(szErrStr, "Failed to write catalogue to:\n %s", szDiscFile);
success = false;
diff --git a/Src/SerialPort.cpp b/Src/SerialPort.cpp
index dfb01682..6cc9855f 100644
--- a/Src/SerialPort.cpp
+++ b/Src/SerialPort.cpp
@@ -281,8 +281,8 @@ bool SerialPort::SetBaudRate(int BaudRate)
/*--------------------------------------------------------------------------*/
bool SerialPort::Configure(unsigned char DataBits,
- unsigned char StopBits,
- unsigned char Parity)
+ unsigned char StopBits,
+ unsigned char Parity)
{
DebugTrace("SerialPort::Configure DataBits=%d StopBits=%d Parity=%d\n", DataBits, StopBits, Parity);
diff --git a/Src/UserPortBreakoutBox.cpp b/Src/UserPortBreakoutBox.cpp
index 3650c3b8..806b03b0 100644
--- a/Src/UserPortBreakoutBox.cpp
+++ b/Src/UserPortBreakoutBox.cpp
@@ -198,7 +198,7 @@ INT_PTR UserPortBreakoutDialog::DlgProc(
switch (nMessage)
{
case WM_INITDIALOG:
- for (int i = 0; i < _countof(BitKeyButtonIDs); i++)
+ for (size_t i = 0; i < _countof(BitKeyButtonIDs); i++)
{
ShowBitKey(i, BitKeyButtonIDs[i]);
}
From 811f209ecbb08673d4bb26a4c24c24b89c5c87b1 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Fri, 27 Dec 2024 15:59:46 +0000
Subject: [PATCH 065/101] A few minor changes
---
Src/Preferences.cpp | 2 ++
Src/Socket.cpp | 9 +++++----
Src/Teletext.cpp | 2 +-
3 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/Src/Preferences.cpp b/Src/Preferences.cpp
index 8a83b7a8..ef9de869 100644
--- a/Src/Preferences.cpp
+++ b/Src/Preferences.cpp
@@ -22,7 +22,9 @@ Boston, MA 02110-1301, USA.
#include
#include
+#include
#include
+#include
#include "Preferences.h"
#include "StringUtils.h"
diff --git a/Src/Socket.cpp b/Src/Socket.cpp
index f84097a0..73a3e49c 100644
--- a/Src/Socket.cpp
+++ b/Src/Socket.cpp
@@ -77,7 +77,7 @@ bool SetSocketBlocking(SOCKET Socket, bool Blocking)
}
else
{
- Flags |= O_NONBLOCK
+ Flags |= O_NONBLOCK;
}
return fcntl(Socket, F_SETFL, Flags) == 0;
@@ -89,15 +89,16 @@ bool SetSocketBlocking(SOCKET Socket, bool Blocking)
bool WouldBlock(int Error)
{
-#ifdef WIN32
+
+ #ifdef WIN32
return Error == WSAEWOULDBLOCK;
-#else
+ #else
return Error == EWOULDBLOCK; // TODO: EAGAIN?
-#endif
+ #endif
}
/****************************************************************************/
diff --git a/Src/Teletext.cpp b/Src/Teletext.cpp
index 65912dba..f899f5fa 100644
--- a/Src/Teletext.cpp
+++ b/Src/Teletext.cpp
@@ -80,7 +80,6 @@ static unsigned char TeletextStatus = 0x0f;
static bool TeletextInts = false;
static bool TeletextEnable = false;
static int TeletextChannel = 0;
-static int rowPtrOffset = 0x00;
static int rowPtr = 0x00;
static int colPtr = 0x00;
@@ -551,6 +550,7 @@ void TeletextAdapterUpdate()
}
fseek(TeletextFile[TeletextChannel], TeletextCurrentField * TELETEXT_FIELD_SIZE + 3L * 43L, SEEK_SET);
+
fread(buff, 16 * 43, 1, TeletextFile[TeletextChannel]);
}
From 6443aa9cfdb8e1258d8e17de5fd208cdf203d939 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Fri, 27 Dec 2024 16:03:41 +0000
Subject: [PATCH 066/101] Fixed printer enable at startup
See #144
---
Src/BeebWin.cpp | 12 +++---------
Src/BeebWin.h | 2 +-
Src/BeebWinIo.cpp | 23 ++++++++++++-----------
3 files changed, 16 insertions(+), 21 deletions(-)
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index ffde12be..0eca4c80 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -586,14 +586,7 @@ void BeebWin::ApplyPrefs()
InitTextView();
// Initialise printer
- if (PrinterEnabled)
- {
- PrinterEnable(m_PrinterDevice.c_str());
- }
- else
- {
- PrinterDisable();
- }
+ EnablePrinter(PrinterEnabled);
// Joysticks can only be initialised after the window is created (needs hwnd)
if (m_JoystickOption == JoystickOption::Joystick)
@@ -1284,6 +1277,7 @@ void BeebWin::FlashWindow()
}
/****************************************************************************/
+
void BeebWin::ShowMenu(bool on)
{
if (m_DisableMenu)
@@ -3807,7 +3801,7 @@ void BeebWin::HandleCommand(UINT MenuID)
break;
case IDM_PRINTERONOFF:
- TogglePrinter();
+ EnablePrinter(!PrinterEnabled);
break;
case IDM_SERIAL:
diff --git a/Src/BeebWin.h b/Src/BeebWin.h
index dfb30c88..8b3c0de1 100644
--- a/Src/BeebWin.h
+++ b/Src/BeebWin.h
@@ -502,7 +502,7 @@ class BeebWin
void SetPrinterPort(PrinterPortType PrinterPort);
void UpdatePrinterPortMenu();
bool GetPrinterFileName();
- bool TogglePrinter();
+ bool EnablePrinter(bool Enable);
void TranslatePrinterPort();
// AVI recording
diff --git a/Src/BeebWinIo.cpp b/Src/BeebWinIo.cpp
index 0b51ea8b..30b46950 100644
--- a/Src/BeebWinIo.cpp
+++ b/Src/BeebWinIo.cpp
@@ -739,7 +739,7 @@ void BeebWin::SetPrinterPort(PrinterPortType PrinterPort)
// disable it before changing file
if (PrinterEnabled)
{
- TogglePrinter();
+ EnablePrinter(false);
}
// Add file name to menu
@@ -759,7 +759,7 @@ void BeebWin::SetPrinterPort(PrinterPortType PrinterPort)
{
if (PrinterEnabled)
{
- TogglePrinter();
+ EnablePrinter(false);
}
m_PrinterPort = PrinterPort;
@@ -774,7 +774,7 @@ void BeebWin::SetPrinterPort(PrinterPortType PrinterPort)
// disable it before changing file
if (PrinterEnabled)
{
- TogglePrinter();
+ EnablePrinter(false);
}
m_PrinterPort = PrinterPort;
@@ -861,15 +861,11 @@ bool BeebWin::GetPrinterFileName()
/****************************************************************************/
-bool BeebWin::TogglePrinter()
+bool BeebWin::EnablePrinter(bool Enable)
{
bool Success = true;
- if (PrinterEnabled)
- {
- PrinterDisable();
- }
- else
+ if (Enable)
{
m_PrinterBuffer.clear();
KillTimer(m_hWnd, TIMER_PRINTER);
@@ -895,9 +891,14 @@ bool BeebWin::TogglePrinter()
Success = PrinterEnable(m_PrinterDevice.c_str());
}
}
+ else
+ {
+ PrinterDisable();
+ }
if (Success)
{
+ PrinterEnabled = Enable;
CheckMenuItem(IDM_PRINTERONOFF, PrinterEnabled);
}
@@ -1581,13 +1582,13 @@ void BeebWin::OnCopy()
{
if (PrinterEnabled)
{
- TogglePrinter();
+ EnablePrinter(false);
}
m_PrinterPort = PrinterPortType::Clipboard;
TranslatePrinterPort();
- TogglePrinter(); // Turn printer back on
+ EnablePrinter(true); // Turn printer back on
UpdatePrinterPortMenu();
m_PrinterBuffer.clear();
From 97b6056a323b2bb187b7981cec163f40d5964cc0 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Fri, 27 Dec 2024 16:05:43 +0000
Subject: [PATCH 067/101] Added error handling reading CSW files
---
Src/BeebWinIo.cpp | 8 +++++++-
Src/Csw.cpp | 46 +++++++++++++++++++++++++++++++++++++++-------
Src/Csw.h | 1 +
3 files changed, 47 insertions(+), 8 deletions(-)
diff --git a/Src/BeebWinIo.cpp b/Src/BeebWinIo.cpp
index 30b46950..67eef119 100644
--- a/Src/BeebWinIo.cpp
+++ b/Src/BeebWinIo.cpp
@@ -1304,6 +1304,11 @@ bool BeebWin::LoadCSWTape(const char *FileName)
case CSWResult::Success:
return true;
+ case CSWResult::ReadFailed:
+ Report(MessageType::Error, "Failed to read CSW file:\n %s",
+ FileName);
+ return false;
+
case CSWResult::InvalidCSWFile:
Report(MessageType::Error, "The file selected is not a CSW file:\n %s",
FileName);
@@ -1332,6 +1337,7 @@ bool BeebWin::LoadFDC(char *DLLName, bool Save)
Ext1770Result Result = Ext1770Result::Success;
Ext1770Reset();
+
NativeFDC = true;
char CfgName[20];
@@ -1365,7 +1371,7 @@ bool BeebWin::LoadFDC(char *DLLName, bool Save)
{
Report(MessageType::Error, "Unable to load FDD Extension Board DLL\nReverting to native 8271");
}
- else // if (Result == InvalidDLL)
+ else // if (Result == Ext1770Result::InvalidDLL)
{
Report(MessageType::Error, "Invalid FDD Extension Board DLL\nReverting to native 8271");
}
diff --git a/Src/Csw.cpp b/Src/Csw.cpp
index 7003a3fc..0424f140 100644
--- a/Src/Csw.cpp
+++ b/Src/Csw.cpp
@@ -113,17 +113,49 @@ CSWResult CSWOpen(const char *FileName)
return CSWResult::InvalidHeaderExtension;
}
- int end = ftell(csw_file);
- fseek(csw_file, 0, SEEK_END);
- int sourcesize = ftell(csw_file) - end + 1;
- fseek(csw_file, end, SEEK_SET);
+ long end = ftell(csw_file);
+
+ if (end == -1)
+ {
+ fclose(csw_file);
+ return CSWResult::ReadFailed;
+ }
+
+ if (fseek(csw_file, 0, SEEK_END) == -1)
+ {
+ fclose(csw_file);
+ return CSWResult::ReadFailed;
+ }
+
+ long pos = ftell(csw_file);
+
+ if (pos == -1)
+ {
+ fclose(csw_file);
+ return CSWResult::ReadFailed;
+ }
+
+ long sourcesize = pos - end + 1;
+
+ if (fseek(csw_file, end, SEEK_SET) == -1)
+ {
+ fclose(csw_file);
+ return CSWResult::ReadFailed;
+ }
csw_bufflen = 8 * 1024 * 1024;
- csw_buff = (unsigned char *) malloc(csw_bufflen);
- unsigned char *sourcebuff = (unsigned char *) malloc(sourcesize);
+ csw_buff = (unsigned char *)malloc(csw_bufflen);
+ unsigned char *sourcebuff = (unsigned char *)malloc(sourcesize);
+
+ size_t BytesRead = fread(sourcebuff, 1, sourcesize, csw_file);
- fread(sourcebuff, 1, sourcesize, csw_file);
fclose(csw_file);
+
+ if (BytesRead != (size_t)sourcesize)
+ {
+ return CSWResult::ReadFailed;
+ }
+
csw_file = nullptr;
uncompress(csw_buff, &csw_bufflen, sourcebuff, sourcesize);
diff --git a/Src/Csw.h b/Src/Csw.h
index 5dcf4f57..80f40b45 100644
--- a/Src/Csw.h
+++ b/Src/Csw.h
@@ -30,6 +30,7 @@ Boston, MA 02110-1301, USA.
enum class CSWResult {
Success,
OpenFailed,
+ ReadFailed,
InvalidCSWFile,
InvalidHeaderExtension
};
From 9d35b0f5a97b6bf5b2bcbea9e9388758d88c7875 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Fri, 27 Dec 2024 16:46:04 +0000
Subject: [PATCH 068/101] Added error handling reading UEF savetate files
---
Src/UefState.cpp | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)
diff --git a/Src/UefState.cpp b/Src/UefState.cpp
index 47b7f0ee..e271e441 100644
--- a/Src/UefState.cpp
+++ b/Src/UefState.cpp
@@ -47,6 +47,10 @@ Boston, MA 02110-1301, USA.
/*-------------------------------------------------------------------------*/
+const unsigned char UEFSTATE_VERSION = 15;
+
+/*-------------------------------------------------------------------------*/
+
void UEFWrite64(uint64_t Value, FILE *pFile)
{
for (int Shift = 0; Shift < 64; Shift += 8)
@@ -286,7 +290,7 @@ UEFStateResult SaveUEFState(const char *FileName)
fprintf(UEFState,"UEF File!");
fputc(0, UEFState); // UEF Header
- const unsigned char UEFMinorVersion = 15;
+ const unsigned char UEFMinorVersion = UEFSTATE_VERSION;
const unsigned char UEFMajorVersion = 0;
fputc(UEFMinorVersion, UEFState);
@@ -389,9 +393,9 @@ UEFStateResult LoadUEFState(const char *FileName)
char UEFId[10];
UEFId[0] = '\0';
- fread(UEFId, sizeof(UEFId), 1, UEFState);
+ size_t BytesRead = fread(UEFId, 1, sizeof(UEFId), UEFState);
- if (strcmp(UEFId, "UEF File!") != 0)
+ if (BytesRead != sizeof(UEFId) || strcmp(UEFId, "UEF File!") != 0)
{
fclose(UEFState);
return UEFStateResult::InvalidUEFFile;
@@ -399,7 +403,7 @@ UEFStateResult LoadUEFState(const char *FileName)
const int Version = UEFRead16(UEFState);
- if (Version > 14)
+ if (Version > UEFSTATE_VERSION)
{
fclose(UEFState);
return UEFStateResult::InvalidUEFVersion;
@@ -411,6 +415,12 @@ UEFStateResult LoadUEFState(const char *FileName)
unsigned int Length = UEFRead32(UEFState);
long CPos = ftell(UEFState);
+ if (CPos == -1)
+ {
+ fclose(UEFState);
+ return UEFStateResult::ReadFailed;
+ }
+
switch (Block)
{
case 0x046A:
@@ -535,6 +545,8 @@ UEFStateResult LoadUEFState(const char *FileName)
}
catch (UEFStateResult Result)
{
+ fclose(UEFState);
+
return Result;
}
}
@@ -550,9 +562,10 @@ bool IsUEFSaveState(const char* FileName)
if (file != nullptr)
{
char buf[14];
- fread(buf, sizeof(buf), 1, file);
+ size_t BytesRead = fread(buf, 1, sizeof(buf), file);
- if (strcmp(buf, "UEF File!") == 0 && buf[12] == 0x6c && buf[13] == 0x04)
+ if (BytesRead == sizeof(buf) && strcmp(buf, "UEF File!") == 0 &&
+ buf[12] == 0x6c && buf[13] == 0x04)
{
IsSaveState = true;
}
From 536a8fc9dfe43f8076aacb51b98e01dfccfc5817 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Fri, 27 Dec 2024 16:46:51 +0000
Subject: [PATCH 069/101] Report error if failed to load Z80 copro ROM file
---
Src/Z80Support.cpp | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/Src/Z80Support.cpp b/Src/Z80Support.cpp
index e7a41625..9b5e551a 100644
--- a/Src/Z80Support.cpp
+++ b/Src/Z80Support.cpp
@@ -29,6 +29,7 @@ Boston, MA 02110-1301, USA.
#include "Debug.h"
#include "FileUtils.h"
#include "Log.h"
+#include "Main.h"
#include "Tube.h"
#include "UefState.h"
@@ -244,10 +245,24 @@ void init_z80()
AppendPath(PathName, "Z80.rom");
FILE *f = fopen(PathName, "rb");
+
if (f != nullptr)
{
- fread(z80_rom, 4096, 1, f);
+ size_t BytesRead = fread(z80_rom, 1, 4096, f);
+
fclose(f);
+
+ if (BytesRead != 4096)
+ {
+ mainWin->Report(MessageType::Error,
+ "Failed to read ROM file:\n %s",
+ PathName);
+ }
+ }
+ else
+ {
+ mainWin->Report(MessageType::Error,
+ "Cannot open ROM:\n %s", PathName);
}
}
else // Tube::TorchZ80
From dff8f374fd6936d278b237b975f161669e08ab62 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Fri, 27 Dec 2024 16:47:15 +0000
Subject: [PATCH 070/101] Simplified code that reads Torch Z80 ROM file
Not sure why this checks for the file size. Were different
sized ROMs available?
---
Src/Z80Support.cpp | 40 ++++++++++++++++++----------------------
1 file changed, 18 insertions(+), 22 deletions(-)
diff --git a/Src/Z80Support.cpp b/Src/Z80Support.cpp
index 9b5e551a..dcd727f0 100644
--- a/Src/Z80Support.cpp
+++ b/Src/Z80Support.cpp
@@ -272,33 +272,29 @@ void init_z80()
AppendPath(PathName, "CCPN102.rom");
FILE *f = fopen(PathName, "rb");
+
if (f != nullptr)
{
- size_t addr = 0;
- fseek(f, 0, SEEK_END);
- long count = ftell(f);
- if (count > 4096) {
- fseek(f, 0, SEEK_SET);
- addr=addr+fread(z80_rom+0, 8192, 1, f);
- } else {
- if (count > 2048) {
- fseek(f, 0, SEEK_SET);
- addr=addr+fread(z80_rom+0, 4096, 1, f);
- fseek(f, 0, SEEK_SET);
- addr=addr+fread(z80_rom+4096, 4096, 1, f);
- } else {
- fseek(f, 0, SEEK_SET);
- addr=addr+fread(z80_rom+0, 2048, 1, f);
- fseek(f, 0, SEEK_SET);
- addr=addr+fread(z80_rom+2048, 2048, 1, f);
- fseek(f, 0, SEEK_SET);
- addr=addr+fread(z80_rom+4096, 2048, 1, f);
- fseek(f, 0, SEEK_SET);
- addr=addr+fread(z80_rom+6144, 2048, 1, f);
- }
+ size_t BytesRead = fread(z80_rom, 1, 8192, f);
+
+ if (BytesRead <= 2048)
+ {
+ memcpy(z80_rom + 2048, z80_rom, 2048);
+ memcpy(z80_rom + 4096, z80_rom, 2048);
+ memcpy(z80_rom + 6144, z80_rom, 2048);
}
+ else if (BytesRead <= 4096)
+ {
+ memcpy(z80_rom + 4096, z80_rom, 4096);
+ }
+
fclose(f);
}
+ else
+ {
+ mainWin->Report(MessageType::Error,
+ "Cannot open ROM:\n %s", PathName);
+ }
}
inROM = true;
From bf5e4e04cb1ca3e85c3ea7617fccb022dca88c51 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 28 Dec 2024 10:59:35 +0000
Subject: [PATCH 071/101] Renamed Z80 functions
---
Src/6502core.cpp | 2 +-
Src/BeebWin.cpp | 4 ++--
Src/Tube.cpp | 2 +-
Src/Z80.h | 4 ++--
Src/Z80Support.cpp | 6 +++---
5 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/Src/6502core.cpp b/Src/6502core.cpp
index 5848350e..52f90495 100644
--- a/Src/6502core.cpp
+++ b/Src/6502core.cpp
@@ -3249,7 +3249,7 @@ void Exec6502Instruction()
case TubeDevice::AcornZ80: // TODO: 6MHz
case TubeDevice::TorchZ80: // TODO: 4MHz
- z80_execute();
+ Z80Execute();
break;
case TubeDevice::AcornArm: // TODO: 8MHz
diff --git a/Src/BeebWin.cpp b/Src/BeebWin.cpp
index 0eca4c80..509490ce 100644
--- a/Src/BeebWin.cpp
+++ b/Src/BeebWin.cpp
@@ -793,7 +793,7 @@ void BeebWin::ResetBeebSystem(Model NewModelType, bool LoadRoms)
{
R1Status = 0;
ResetTube();
- init_z80();
+ Z80Init();
}
else if (TubeType == TubeDevice::AcornArm)
{
@@ -939,7 +939,7 @@ void BeebWin::Break()
{
R1Status = 0;
ResetTube();
- init_z80();
+ Z80Init();
}
else if (TubeType == TubeDevice::AcornArm)
{
diff --git a/Src/Tube.cpp b/Src/Tube.cpp
index 6a98c897..08dd26e6 100644
--- a/Src/Tube.cpp
+++ b/Src/Tube.cpp
@@ -308,7 +308,7 @@ void WriteTorchTubeFromHostSide(int IOAddr,unsigned char IOData)
case 0x0c :
if (IOData == 0xaa)
{
- init_z80();
+ Z80Init();
}
break;
diff --git a/Src/Z80.h b/Src/Z80.h
index 274b79f6..85f5835b 100644
--- a/Src/Z80.h
+++ b/Src/Z80.h
@@ -84,8 +84,8 @@ extern void out(unsigned int, unsigned char);
#endif
-void z80_execute();
-void init_z80();
+void Z80Execute();
+void Z80Init();
void Debug_Z80();
int Z80_Disassemble(int adr, char *s);
void PrintHex(int PC);
diff --git a/Src/Z80Support.cpp b/Src/Z80Support.cpp
index dcd727f0..a379a9b2 100644
--- a/Src/Z80Support.cpp
+++ b/Src/Z80Support.cpp
@@ -199,7 +199,7 @@ void out(unsigned int addr, unsigned char value)
}
}
-void z80_execute()
+void Z80Execute()
{
if (trace_z80)
{
@@ -232,11 +232,11 @@ void z80_execute()
}
}
-void init_z80()
+void Z80Init()
{
char PathName[MAX_PATH];
- WriteLog("init_z80()\n");
+ WriteLog("Z80Init()\n");
if (TubeType == TubeDevice::AcornZ80)
{
From 8f70e13289f048800b45b40a559a9f32f0932190 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 28 Dec 2024 11:00:16 +0000
Subject: [PATCH 072/101] Set parent window for tape control dialog box
---
Src/TapeControlDialog.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Src/TapeControlDialog.cpp b/Src/TapeControlDialog.cpp
index 4e695e47..ef68799a 100644
--- a/Src/TapeControlDialog.cpp
+++ b/Src/TapeControlDialog.cpp
@@ -40,14 +40,14 @@ static void UpdateState(HWND hwndDlg);
static INT_PTR CALLBACK TapeControlDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam);
-void TapeControlOpenDialog(HINSTANCE hinst, HWND /* hwndMain */)
+void TapeControlOpenDialog(HINSTANCE hinst, HWND hwndMain)
{
TapeControlEnabled = true;
if (!IsWindow(hwndTapeControl))
{
hwndTapeControl = CreateDialog(hinst, MAKEINTRESOURCE(IDD_TAPECONTROL),
- NULL, TapeControlDlgProc);
+ hwndMain, TapeControlDlgProc);
hCurrentDialog = hwndTapeControl;
DisableRoundedCorners(hwndTapeControl);
From 1f5b904b837b51c432862f7225b41e12f21b5ef8 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 28 Dec 2024 12:47:47 +0000
Subject: [PATCH 073/101] Fixed resource ids
---
Src/Resource.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Src/Resource.h b/Src/Resource.h
index 9abc854c..c2178221 100644
--- a/Src/Resource.h
+++ b/Src/Resource.h
@@ -313,8 +313,8 @@
#define IDM_MODELBINT 40105
#define IDM_MODELBPLUS 40106
#define IDM_MASTER128 40107
-#define IDM_MASTER_ET 40327
-#define IDM_LOADTAPE 40108
+#define IDM_MASTER_ET 40108
+#define IDM_LOADTAPE 40109
#define IDM_REWINDTAPE 40116
#define IDM_SFX_RELAY 40117
#define IDM_TUBE_NONE 40118
From b0acffecbfcd282c44ffe091a4d601b30381d4f1 Mon Sep 17 00:00:00 2001
From: Chris Needham
Date: Sat, 28 Dec 2024 12:44:40 +0000
Subject: [PATCH 074/101] Fixed recording to an existing tape image
Saving to tape is only enabled for UEF format tape images.
This commit adds a New Tape button to the Tape Control window,
and tape data is held in memory instead of being written
directly to file, which ensures the UEF data is gzip compressed
in one block.
See #142
---
Help/emulation.html | 1 +
Help/tape.png | Bin 13875 -> 11766 bytes
Help/tapes.html | 20 +-
Src/BeebEm.rc | 15 +-
Src/BeebWin.cpp | 1 -
Src/BeebWin.h | 4 +-
Src/BeebWinIo.cpp | 30 +--
Src/Csw.cpp | 3 +-
Src/Resource.h | 5 +-
Src/Serial.cpp | 109 +++++----
Src/Serial.h | 11 +-
Src/TapeControlDialog.cpp | 109 ++++++---
Src/Uef.cpp | 466 +++++++++++++++++++++++++-------------
Src/Uef.h | 46 ++--
14 files changed, 536 insertions(+), 284 deletions(-)
diff --git a/Help/emulation.html b/Help/emulation.html
index a9452165..dc58c20f 100644
--- a/Help/emulation.html
+++ b/Help/emulation.html
@@ -59,6 +59,7 @@ Hardware common to all models
"IC32" Addressable latch
Full BBC Micro keyboard
ROMSELect Register
+ 6850 Serial ACIA and Serial ULA
6854 Advanced Data-Link Controller (Econet)
SCSI and SASI Hard Drives
AMX Mouse
diff --git a/Help/tape.png b/Help/tape.png
index 01eb6802ae65dbc00cf171195e2624cdf9a1d95f..50f91a868986f3fdaa5eca53fcd8f2004c426082 100644
GIT binary patch
literal 11766
zcmb_?2|QG7|NdxGdhnE@$S8`EY$ZD>C5cjG-?9|SzRVa5Nh&0%$o`}vvS*($N=Orm
zn1oSTCI-ho7-RnT%+Nz`@B4q=-|y%18FS9eIdkswy}#esNzMjFi<>!5f?BIjy6xoW>mkU}w!G4P6ZwEI(@FyvL@DfSb-zlE?>}4Icjj3&iE^K
z0O!JB4#ji_n9|)2#y;bX-f>q6#@c%S{ylRK96|@5-7TiCWna%Y&Y>8bcenU1IP~sa
z2L}fwC76uU@@6Iy#z~n%dLT149t3t*sjx8n(+D
ziJr3GE_y1WOZGDu#|F2PCY~@DS2g3sR_B^w2R`KWI&SQB-qpd&*T%yhcGkwx#Yo*z4uT5qB&ONZr
z_*(^jWfk+tbBYRJYw;`@X=%o{wogRgoYSMdhr#yuXlrU1AS{QIHiYahaer!$gq$;;
z?Zy|E7U=qM=Te$;>ighyy6XYq@7S9sVJ0T*;`(xtQIR(z*mno{hc<4PyOd!S(Q_tn
z7OzgzqR*VsZy=@2x1euiWzCT2->n|b6TchhF;>a6DX+*XU5J3lst!sF<95>?diwZ8Oe
zZqe>)diKYzTf2r9is88F_-b00oNFjrXvJJAH7)$)$W!IixX8
z5fVbX9$uI>t9a@)+UZyorpjhuUN}u7?Mw9DyYT9-@rzFz?DJiXnxcn+gfJfP(
zCr!h&5oN82Xrt>Gd12n%_hRu{gi{Of+}#3COV)SeT~Feu&H)vlyPl4Kq?GhIVP
z8^5$FR31_$jEPOQzu6Io(B}TZTe$+~WP{W%o;Zu5*EKbs$)>1teyubf($B&zC;Lh`dw1*;aNl+EzYM+mWq5=$>EuV}h+FPN$a|eprDt!-
z=Nz?k-rMA&o9>wfcn(AP@|}b-xws$skE}w-cg!jLw%7FN5%a5v>27gZW?uTZL;^;TXt#AAQ(he7o24qrS#h4IigH6+0Kv8_9n!Coj`OJHcixqRB0sq9`6eSoy|~
zv>=$Fg5jI6Ora?f)6UF@V_c)4u0wi42v^rls0TB0^F>eOG@)}`SOSDUvj*N-Hbg73
z!zc9xtc7=)5L4LUo!ff?VwZO7=)?ky`X+?lLyFj{ChaEFyv}5u3DGr}^rT01Vb9!p
zX%Si~j&=pn_7c})HIg63C6@Js7e#PC#}V3HjYEj*g|etMy&C(Y$vGAw=g40^a=
zcqcAORib0ytKy@;5&JOjLg|MNk@0DAAFa51{O8wy7kQyonM2vLQzjymoF}&<`__V=
z@%y@DCHB!o321{Rl5!v4JOp#jUgh*dlY?ikNDoqWG|>xFSH)&NaWK>mLVWt>CRn_V
zM>VrML!@-%ZBeU1G&BK6dw;XZnKOxpXmX9%z{yFzeQOCx8P87~53TZSo`Um5jXxwh
zOIRniZ8G&07ujxChy75Zw*#526X2H9^RaChkDyqG!@5Vn-$?YNoiX
zLMh{MrT*IxdR$mOG!-tSK;N1~)vxko1^iC8V$H=VE48)s0?Eis=a=NK{1EQEde9Y_(!owV7umr^LXDnWqviY<2Y=>ysv0AM
zRvk~aa&GX@kZQ0c-@9DS)k6L%3h5lVxGg-lP=5Af{Eyr)?W_E#!5vke9-)+)^YZ-k
z)FW=t@spUR6u+R|^?c4-&mI#y7k6a)_NJI%QZFwgvM*lutxRbH>V#Ua^`JMu$E90?
z@`IofJg&+a_R0_wp3f=OPn+^)Nw`H!+#y*eKl$2Y82PoFXEAbjFt|IBeT`;*x%ok3
zrdn=Yx8lXcsq5vdJjZ2;B*raJh`ooa!i-J$Ro};d+Ub<3ufJL!qnFy&g?pv63##ME`0
zBNF>)ya+udVh?m60(S6PGG$(FpPcrYpqA-$oKL&Y-R?U0!(lH*LZSJ)Jf)OhB!uQ4
za{k0j!)>G@z=d17smt|&mJ+-Bg*4X>wkUu7qnR@(Nx2|fcCrt#p
zy0l>VdW!Ba0%vG2y~!nr)N7AvYItpYc!H9rN0yAX?W%sE&H4Bl>l81j@7tdrcdN3U
zt~iK$*SzVL@BP=0pG4-Qir-qjTSs~qTT{J1)E)Hhbp^AA*Kt|XB(82$5mSZ6>PSKk
zG?jD^y&Os@;y%Ct6|q7rDOdYB2z6qyI;{v_95Syqop&WYgk(2Y7Ax2Wh7m94#Jv58
zi7}CzQF-v$a$;=I8);rEu|7^_28tFr4n6mTHPuHF$+*q?HuTvOn^C_n;Lbtp=`maF
z3@MKUN`(L0S5Lg>TGC?lX(t3!5nc#D$fnTKdsNZ7r*xZn
zZaSh`tSYW3zlE}%L8n1&A0x&VMukff5V^|PAO~kURnK2%f@F-Tz_UmYZN<-2d}nXK
zhLeBTj(I2d226fZ1PO8)qC+}}C~yAMcNOX84;@mX+r(3E=sl4Rmi4$Kh|sgFV^*zy
z5}t@M!0ChHi+0X>F5FGR&QH6q&qa*rkeggG0Y1js0`Sz-l@k|VlN@u0GE+DqQWcR(
zMV;>MF(D=t9T4^7t91sGBj%Kup+p84I=0|AkJDMI-=V`*bEjSw9P*0;RQJgs?eS57
zha*^(9m4TX#J;xpkO=lqMb4F1|B|4Oh`A|GubL2rtm_beFaZAyxOyM$R+Xo02Wlby
zJ~%nZ(YL=lTHuRDpb*NqxaF0nENv0_5@u10b=te4PR%d*4l+X*uGqd2LH02TfPf
z&smb^eBmDV&wdFYlJyuY66PtyVBWY-U#yERz5GK(tfUf}Iw+ksMyk?zxltglw4S>8
z?zY<3-ahGSraZK%yto)uCQ5hCHRj_G7f&SgiC?UGSTb3eXr@^9w4JTZbnT}Px3-9$
zy>pubu!s+&^UghvS?X>{T?6?lX>*ZE*MLwnTTHo%!0ZDqTGwatC}PRfkx9`(tuyH8
za}2Isi1j?1^plymy{I)EzR%V2kNDg;(EmPdlHkDgX$1#meMhqGOk>^O9CokBt0DM
zYO^M86WC)g2A+Cgnethdz00K3a+xFu$+*GDXo3qsWRmK_%zX8W6q3QBASuA)0`4lN
zj8~6op^sKB$?dvH!q8(ugC_FC%cbP+u<$9BzMQ+CY#x^V*M89t3?-#Y_P-Cr7p3w_
zewTgN#*pdq0!biju76P^3-Z4
z&F%5aULEB0T<*x5fW%rSrUsbgw*^$@jHTq&brH$x`4$0s2euHLH}x3U$8ODZ@zP+*
zV%vkbbp*k(5xH8BHd0>${C1dUJo^#qV{_d*^}b8%y*us$%^zf*%f)51xE(vWuXH3Y
zM}YCWW>_g|^F~@TI`vd0;tlmQ;ryYtCEzI9&5C*{n6@YDOz@F1Kn+BaEPWrlOr)@53G6L2
zjtk^}qOezi#P^F5U&z0$Dv+Z@fsPD+!vZ`HqbRnoeHWkmn%X#q6#%R-SM<=Kf?V**
z!*HyX1^G`YzWK}vWQyS5rvgJ&56u3ps)y$P3sr3ysAMUp-Bum(uF$)4Jv7)IF#Lk4
zt>e8b{iIdITAHv|a$PoiUR~OM
ziK9THJ6lsFllQrf)b8pKv*-j5&=!dt{>ys}NPyya@ytfGZ;AuRC|vodv=L3BfwI6)
zvXnSakk)Gja#8>M)a`4lo3sfibCq|67~IA(sgiX(*o{3enVP5d>H`22K=J4vZS*d5
z6KL2W*Jfj}$74q&XE9S1K7YLCC#mc{AE%Ejz9aC>f>z;uVc^yl5oFqpC;Kx_eTUV@
zAMW8`l)?gMh6D!8mJ3Mx`=#aA!1PT|61l+?Bb(H3IJ9oEYA6!|%BKV+G;outfhb6+
zOG4jXliVUH_Lp#azUB9R{@~*LZy7qFvk=Z82e4FR$=dfP&0Qcu)~#HNG~i)gyl@KOpm
ze5%rDqHf+)0ELe9lsaQDI+l5Yfu)&7TXuj^p-Fa<+pG|E6s+&XMdB*Y25l9CwzS`t
zx$wGFLtPc^>t_DkuT$t6k}WECGu|n4FB?J+KCvKcgk*L?^;;YalCyhGxDgtM#dWlH
z6ZJX5?;S3`mbshj?hD6*IY1Zv)SsX=Jc9Cr*cZvY8T4nK-`qhb$xJR>iS(-X>-~s$
zU$55PCfoXZ;$Ef{Wo1
zR!6V!5&S~m>iKlu?yN&qc<#`RU~rmuOlld>y1tXdmjclV2wUG(HxY*S9bErliFSSY
z4bw$ynVNl5ROa!)=8g5EUoZ5Ec7Dcn8$^A+&XAbB#J8rAe*E%3*ox&9oAXeoCO!;
zH?o0}#m0sm(~Pm>VBK-4Gs$OJk7HwB_U3JZ`&xuvKZ?H2fS1UrBE}++OOA}VA*0mQ
z=+b18;#SbUVC!nqm|F8+`ti>uhkxD1=@!O2&HWmC_(R`)QxYye81!@!z}>yf`eL7-@*e0jE7j~<@oB2
zndNyP(Q+X3$N{%ZO@|5@SlHW7!OjoP9Y;Tyx=FmjJXap+s&3g9BiWudUBntd1Im_u
zpsI>_MTDa~HO=mY6&Slj{4dk{TSI$T#kQ_l10>&hKh^wnZEnfAQ?|V^WAeH1+?tnE;a|Q|8R-H<`~?M*S17
z3Gf*JRCQ%_kn=8MYAsV+B7f4@5*k*QGYOlK@~Y6&Ss#5K!pC&EcjilGR2~;uJi2G}
zYF_J4zPkeTP&<2!>^{iGgW`f^GCX|;$C5`7xpNb`U%&ZBxdXy;K&k>eYsr}
z=xbUhZgo)@1@xZd3qdSe`%kvc?-^~mxcR*j8h0W_QEiZ%Xs&KL5;GsS5dXB}r<5P}
zAXRpaZL=eG^55Y-fmU7WERji+84>uqs;K^~X*EBFRnbg=qu-=Sk9RyKVG}ny&vplN
zTnH2P><9iJne2o4sp|1ZDgfQJkHJH5{x&5Gd^nmq6-$HARtveo>|LHsScc!wz%M82
zx2zk&MN>TTj7us4cjQ#JSwG(4+O?tfIX|=4VQO3n=+-S_=%U(DD+@D;;a_U060k;Tvvk?&3~ZPemX9=rPk16$
zNJ>xTE9d#Hj}{tt
z+T?UfLgJAoj4ldzV8=KwuLcBGq6`mtpLG>*SLh;l5#w-hFa>A6@4<9ie7kJ3NLAik
zfPRM=;h&+oZ3y%@A?*1Dqg;5bcCK77cggM|WL#
zc!Il-$wGS-0qNva%N`2h|0H5JtN`
zqQl;1_5G9lEW_}XJMTEaB$sFT>5Tx(3$d~1FLL69Bww9rJZY!b*pVb8+(sBi{PZnj
zgMBtJ%gz%59%DGTnTqG|R@YAqa{1zv`PQ`;yF;RFI7g_C(4Md(=|+^1+%>Y^Vke0~rx0#D9^Xwi${2}Y=!l|_}
zjRCMTo8D*{N0}2hcF8e|`KL?PPQ>raztPPd`&I1HZdozXa3lBciWb=+-p;at>fZfTZfxYofnB)|ogcce
z&jz$kCIOp!DKfbY*q*VEuNi)8HfKvMGdAJM@lL-6Cwx=eDD~TBpZCZ=9-Sv0AfI#!
zx;^EsY`G-C-zIs3x?2p+o`$ZJE`z9L{;T}BB^NK*hY(fmeTw1b0QAy^3;YdU{%TOe
z7hVRjELn?;-$Sm2yrar&sK-EoI+U=r89jdR^y5l*u?9&S2X^<&%dS~(lYyJ}NAmVM
zrm+jkbE
z+tel!OR1O;Vic9}`+BDT|9;w1@0Q$rVCfolMUiO5_VU!#zXAKD(A1E^!Z@G(g6kJK
z7@_GQKf%1xoW1NNw(S?RS#E2sgqu_UZWW-B94r4@8-ZcE2DAGj*FHbh)oc?uVvN0uc@!ElG>N>=Icw^0LYmYT^Yz3aL545tq)=M
zeMpJT2T;tok~;U&|A~u0E&MKP5N@Q_#(;_*nYWlSIVSQhx$_=KDKCP8Dd=XUpX=J5
zNm>o=x*esshgnqfy%C!IZ!olhcE^9o955k6i-G_wKn(qwIg5(G>XNI67r&Y%tAUNY
z&G9Nk8IL;ay#k5B=+Hx%=E)1gx=pOqZ`^Alxn$Q@Ykzh?n;VRn0tYq@|
zxblx@%gp+JoHsY1I}6I1mInwDU0mbT&(#G
z8=3dnZ2wA9jEN*AqZkVh7e}&v@BG42s;al7d4H#qz+ED_my8=gT>9-=rEFkqL5my(
zmQ`53+=vZuY4p#tVp+IE-~UDofmCn7qF0M=gw}D7NI+7yz$j*12@PNRPpZKPQ8+ED
zeYNO9dC2tbUs##E@wgfd-ShU4E!Ju!jPCc|j*ZfvjE=w30`O`0C
zKK|`tZk>(9@SR~wNXBZ2=sU5r6%@r7dN9zC%a^}EocTsADRBbD>RVD!u08_R0sk>=
ze9TI`{#R+kG4536FtCKf%PQ(HrICY4;-W=|5rSaF%L9q4c+H|N=29UTYW)flPj579
zi~a=Lx}vC*$;(owxs%qe`wQSKk~nZJUuh~5%XuQs|CBf&w&@eZ7gv|_c&iEfKTjX)
zmQzCqc4lS5_tly-JN?a5U`YQAbMk$|Fh~8Ihu(57i5xJdtR$*Wo$Xy@dwKYx-23v?
z+yDC1+dgb#w^{EpX$%gwgZl0pS3_YsqcI0JKZ?n=4R-2j><|38ok@tOk*ZkwR
z)n(l>(%|YhaPzwIla}RcF#i?q=xBao37uc63*Tn37>c%axjkS(KhO`Nq^tiYOuj#m
zJs1Rkk=rr0v`%nBa`mt%#E^k;Sxj|-yQR>M1yY>P5SF|k`IJ6&_XPTJoB89cl)ZJ9`ra%DcN&?J@VqxnBY
z&{b
z$g6az`?(fh_Q%U`81reHPLvC8t%m~6@t4eDH4kCrp+?tuW(S-3vx8+J^8`Gi6_|wo
zJu-vb(akNN)O;=2?5N*-;%A@w@1c48lRCN3%$%4KrZUxZvEoMTL|~^pA`+|IyY-@x
z*_@LOSogH$#``EC2UEhK=Ichvl;JydJ0}Xf`4m}MQ}l|=2o<86ug8W)nyjp2hN~tK
ztS?(P4YxI|RE8htT8`EHtNc;OPWjnW{HhHh6ok1=VadZqY{
zY4Y?&oqPg6TSHP8dWLI`qzdfb@VbZ
zg==WC!COy-PRP8CEiP@88RfsYT|cKd&G5s1?m5^_4(-{t!cw=90Oig-eg(a~ndVf)
zRi*d`Cn|y*inK9DiaQWVM{wS6CT|*CTra$P7e~c-f}U+1>PlVOMLyxuUc0B}&h^#-
zg4!{S4t%^G{pWm=j;I$#;y+fziEP*ZY-pZR^MF`!`I?R%zxA<0?Xg? 5-_A3tf
zsB*abvW#e^_`9`(A2hb?ajA4~{64O%b
zuwt@)xATOe&g+Ie7}aSe^Z~Zyi
z^19)Q@_AsyN6|2q#}2l7b9>d?9s5MYi=LXmnq&9PH*`uZ`0k!+w1_%9)K$^sV&$9J
zEU9}z;YT2sDkNfo+ZW(KLsk1bVJF0)0V7XH4Hck#-Xi&h+Xvc?X^d36<@P`uLDbu0
z`0&RhRVeoHyojKz!Q6w5#E!fz*$)sc27y9hJ)%+f^e&MCqOfmQ4^Dj}DiJqgcz7OJ
zm|i}pbfX=+&FHwLxxAsu-KSWE;9Ba@_M0PGJ_iVX?m=o^)W-aJh3Ey_cIrmuFvF3r
z*&n1MElN`xeju#!62=jlDVARbhEP$%78O!z-ih+h4(W@(3|_$cg&Fb7Fb?EAbbf=+
zdALyY+!{ZK+B}qX2&eG9E+w$}5^xOOh-*`WUefRQ%5>e5s
z!|+^FJy*$i3fv8EaM2y-s;cVj?Cjv+uzUAz85tQZEiH3%a{&PX6BCour%#_cb;{J#l$V$Hz<~p@va-8&
z?Xt78J96ZRprD|Ig@vZ3rkI$Ryu7@Wl+@O(TUAt4E?v5`ckf;bg`%LKK%rz>L0?2i
zXO&5@qEo!xPJK>&ptRpsq+9x}rlyAW3_64Yy>>g3!pOXadYn}z^ts!ax1mFC-?p-{
zQdFcI>uJ<4>MEv9-1B?d_%WXr=`2mXnh+Gc$vZ6BZV(t*zD2(6F?$
zEIIwo6}pJE&PVlK=;+u=s6X@-PA@I#=nk|TJEC&d!({Yv;5)u!SEBWv>;|#BRgm%}
z!U)kQ10U~)}7MdY3|nOfpTHXBH|}%9G74Q*nCz+%i
zu=)$RKK>%HfD}ICKR>3;b4P!Ea!ex9l>G1!j{Z5(!oOT;UoNp)`GL23^hARx*VugN
zd=HtZ++s-T#!Iu0(l$Ou{E@3rm5M019Lpu64w|_0kM4
zAW6)=rp$;adxLqX6nN&ssCFCs-Phpa(Cnuet;FO`B5J|~xleh)7hs())9wy`RAJRJ
zOAcg5t>r~c=s4K2c!J)gV@>jBr$sHxNHe;u_Ojt=^T3&~@44h{pPg6z**
z1C!fHWgwq)dBOG(q%f&}i`QMmmBd?}1kttn1!c2_A=mU_bJN>$B`o|0mUgy@@ue=H5zmmvrKvEu`=H*UG1F=p!J+T3Sja&h_=wNR%
zOxeYb`5?Go_BjJ)wXsIYAY-!=#^?9j4TWbF5Cs#jqaDrikAq~&mzr)Qh_cM_(PodX
z$8RSXecHH6PbBvOp-oXpz4I|>Jm6QWq2;X-M}9wX0mL30@`im10!jI7B1sBL6FaTU
z{GRU1J9oAJ{+{vZ4~jzbl6!+x2M@Dv#yy%p0+P|nRROWUaGrJFa6EC*UEXC1$Rb5t
zal9tP?O7FfUN}#YQ8qb|!CXud*E_QGsa4UJnyMFsJBf<`0s5S9J(3b8Z9Pef-W{2`
z=CQqi^qW+5H`jFzCWg$MDIY!iCM@=U65FMlpyhpy2!uw?F&BUx&ZKR#BuWr*lV4#W
zwJc2LF>8jDbUw>^I0ct&eQJ2m^NG#tb-2v?d{R2RSkc^A8`;bYcblFNhuFOFE%hdg
z{R^=GMWQYmhetKn!C-4Tk%gr8e5Xw=1?2TcJW$aK6)
zo5(!lM