commit
9982ceb36a
18 changed files with 720 additions and 199 deletions
|
@ -14,13 +14,25 @@ MESSAGE("CMAKE_CXX_FLAGS_RELWITHDEBINFO: ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
|
|||
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
include(CheckIPOSupported)
|
||||
check_ipo_supported()
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
execute_process(COMMAND uname -n
|
||||
OUTPUT_VARIABLE UNAME
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
if(${UNAME} STREQUAL raspberrypi)
|
||||
# it is too slow and might cause out of memory issues
|
||||
# more forensic is required
|
||||
MESSAGE("Raspberry Pi detected: IPO disabled")
|
||||
else()
|
||||
include(CheckIPOSupported)
|
||||
check_ipo_supported()
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION FALSE)
|
||||
endif()
|
||||
|
||||
include_directories(source)
|
||||
|
||||
add_subdirectory(source)
|
||||
add_subdirectory(source/frontends/common2)
|
||||
add_subdirectory(source/frontends/ncurses)
|
||||
add_subdirectory(source/frontends/qapple)
|
||||
add_subdirectory(source/frontends/sa2)
|
||||
add_subdirectory(test/TestCPU6502)
|
||||
|
|
|
@ -5,7 +5,6 @@ add_library(appleii SHARED
|
|||
SoundCore.cpp
|
||||
AY8910.cpp
|
||||
Mockingboard.cpp
|
||||
|
||||
Pravets.cpp
|
||||
Tape.cpp
|
||||
YamlHelper.cpp
|
||||
|
@ -29,7 +28,6 @@ add_library(appleii SHARED
|
|||
NTSC_CharSet.cpp
|
||||
CardManager.cpp
|
||||
Disk2CardManager.cpp
|
||||
SaveState.cpp # uses g_CardMgr in m_ConfigNew (reverse order)
|
||||
Riff.cpp
|
||||
|
||||
Configuration/PropertySheetHelper.cpp
|
||||
|
@ -64,6 +62,7 @@ add_library(appleii SHARED
|
|||
linux/duplicates/SerialComms.cpp
|
||||
linux/duplicates/IPropertySheet.cpp
|
||||
linux/duplicates/Applewin.cpp # defines g_CardMgr (reverse order)
|
||||
SaveState.cpp # uses g_CardMgr in m_ConfigNew (reverse order)
|
||||
|
||||
Z80VICE/z80.cpp
|
||||
Z80VICE/z80mem.cpp
|
||||
|
|
29
source/frontends/common2/CMakeLists.txt
Normal file
29
source/frontends/common2/CMakeLists.txt
Normal file
|
@ -0,0 +1,29 @@
|
|||
include(GNUInstallDirs)
|
||||
|
||||
add_library(common2 STATIC
|
||||
resources.cpp
|
||||
configuration.cpp
|
||||
programoptions.cpp
|
||||
utils.cpp
|
||||
)
|
||||
|
||||
find_package(Boost REQUIRED
|
||||
COMPONENTS program_options
|
||||
)
|
||||
|
||||
target_include_directories(common2 PRIVATE
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${Boost_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(common2 PRIVATE
|
||||
Boost::program_options
|
||||
)
|
||||
|
||||
file(RELATIVE_PATH ROOT_PATH ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR})
|
||||
file(RELATIVE_PATH SHARE_PATH ${CMAKE_INSTALL_FULL_BINDIR} ${CMAKE_INSTALL_FULL_DATADIR}/applewin)
|
||||
|
||||
configure_file(config.h.in config.h)
|
||||
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/resource
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/applewin)
|
|
@ -1,4 +1,4 @@
|
|||
#include "frontends/ncurses/configuration.h"
|
||||
#include "frontends/common2/configuration.h"
|
||||
|
||||
#include "Log.h"
|
||||
#include "linux/windows/files.h"
|
96
source/frontends/common2/programoptions.cpp
Normal file
96
source/frontends/common2/programoptions.cpp
Normal file
|
@ -0,0 +1,96 @@
|
|||
#include <frontends/common2/programoptions.h>
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "Memory.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
||||
bool getEmulatorOptions(int argc, const char * argv [], const std::string & version, EmulatorOptions & options)
|
||||
{
|
||||
po::options_description desc("AppleWin " + version);
|
||||
desc.add_options()
|
||||
("help,h", "Print this help message")
|
||||
("conf", "Save configuration on exit");
|
||||
|
||||
po::options_description diskDesc("Disk");
|
||||
diskDesc.add_options()
|
||||
("d1,1", po::value<std::string>(), "Mount disk image in first drive")
|
||||
("d2,2", po::value<std::string>(), "Mount disk image in second drive")
|
||||
("create,c", "Create missing disks");
|
||||
desc.add(diskDesc);
|
||||
|
||||
po::options_description snapshotDesc("Snapshot");
|
||||
snapshotDesc.add_options()
|
||||
("load-state,ls", po::value<std::string>(), "Load snapshot from file");
|
||||
desc.add(snapshotDesc);
|
||||
|
||||
po::options_description memoryDesc("Memory");
|
||||
memoryDesc.add_options()
|
||||
("memclear,m", po::value<int>(), "Memory initialization pattern [0..7]");
|
||||
desc.add(memoryDesc);
|
||||
|
||||
po::options_description emulatorDesc("Emulator");
|
||||
emulatorDesc.add_options()
|
||||
("log", "Log to AppleWin.log")
|
||||
("headless,hl", "Headless: disable video")
|
||||
("ntsc,nt", "NTSC: execute NTSC code")
|
||||
("benchmark,b", "Benchmark emulator");
|
||||
desc.add(emulatorDesc);
|
||||
|
||||
po::variables_map vm;
|
||||
try
|
||||
{
|
||||
po::store(po::parse_command_line(argc, argv, desc), vm);
|
||||
|
||||
if (vm.count("help"))
|
||||
{
|
||||
std::cout << "AppleWin " << version << " edition" << std::endl << std::endl << desc << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
options.saveConfigurationOnExit = vm.count("conf");
|
||||
|
||||
if (vm.count("d1"))
|
||||
{
|
||||
options.disk1 = vm["d1"].as<std::string>();
|
||||
}
|
||||
|
||||
if (vm.count("d2"))
|
||||
{
|
||||
options.disk2 = vm["d2"].as<std::string>();
|
||||
}
|
||||
|
||||
options.createMissingDisks = vm.count("create") > 0;
|
||||
|
||||
if (vm.count("load-state"))
|
||||
{
|
||||
options.snapshot = vm["load-state"].as<std::string>();
|
||||
}
|
||||
|
||||
if (vm.count("memclear"))
|
||||
{
|
||||
const int memclear = vm["memclear"].as<int>();
|
||||
if (memclear >=0 && memclear < NUM_MIP)
|
||||
options.memclear = memclear;
|
||||
}
|
||||
|
||||
options.benchmark = vm.count("benchmark") > 0;
|
||||
options.headless = vm.count("headless") > 0;
|
||||
options.log = vm.count("log") > 0;
|
||||
options.ntsc = vm.count("ntsc") > 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (const po::error& e)
|
||||
{
|
||||
std::cerr << "ERROR: " << e.what() << std::endl << desc << std::endl;
|
||||
return false;
|
||||
}
|
||||
catch (const std::exception & e)
|
||||
{
|
||||
std::cerr << "ERROR: " << e.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
20
source/frontends/common2/programoptions.h
Normal file
20
source/frontends/common2/programoptions.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#include <string>
|
||||
|
||||
|
||||
struct EmulatorOptions
|
||||
{
|
||||
std::string disk1;
|
||||
std::string disk2;
|
||||
bool createMissingDisks;
|
||||
std::string snapshot;
|
||||
int memclear;
|
||||
bool log;
|
||||
bool benchmark;
|
||||
bool headless;
|
||||
bool ntsc;
|
||||
bool saveConfigurationOnExit;
|
||||
|
||||
bool run; // false if options include "-h"
|
||||
};
|
||||
|
||||
bool getEmulatorOptions(int argc, const char * argv [], const std::string & version, EmulatorOptions & options);
|
|
@ -25,7 +25,7 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
std::string getResourcePath()
|
||||
std::string getResourcePathImpl()
|
||||
{
|
||||
char self[1024] = {0};
|
||||
const int ch = readlink("/proc/self/exe", self, sizeof(self));
|
||||
|
@ -51,7 +51,12 @@ namespace
|
|||
return std::string();
|
||||
}
|
||||
|
||||
const std::string resourcePath = getResourcePath();
|
||||
}
|
||||
|
||||
const std::string & getResourcePath()
|
||||
{
|
||||
static const std::string path = getResourcePathImpl();
|
||||
return path;
|
||||
}
|
||||
|
||||
HRSRC FindResource(void *, const char * filename, const char *)
|
||||
|
@ -60,7 +65,7 @@ HRSRC FindResource(void *, const char * filename, const char *)
|
|||
|
||||
if (filename)
|
||||
{
|
||||
const std::string path = resourcePath + filename;
|
||||
const std::string path = getResourcePath() + filename;
|
||||
|
||||
int fd = open(path.c_str(), O_RDONLY);
|
||||
|
||||
|
@ -84,15 +89,3 @@ HRSRC FindResource(void *, const char * filename, const char *)
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
HBITMAP LoadBitmap(HINSTANCE hInstance, const char * filename)
|
||||
{
|
||||
LogFileOutput("LoadBitmap: not loading resource %s\n", filename);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LONG GetBitmapBits(HBITMAP hbit, LONG cb, LPVOID lpvBits)
|
||||
{
|
||||
memset(lpvBits, 0, cb);
|
||||
return cb;
|
||||
}
|
3
source/frontends/common2/resources.h
Normal file
3
source/frontends/common2/resources.h
Normal file
|
@ -0,0 +1,3 @@
|
|||
#include <string>
|
||||
|
||||
const std::string & getResourcePath();
|
63
source/frontends/common2/utils.cpp
Normal file
63
source/frontends/common2/utils.cpp
Normal file
|
@ -0,0 +1,63 @@
|
|||
#include <frontends/common2/utils.h>
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "Common.h"
|
||||
#include "Applewin.h"
|
||||
#include "CardManager.h"
|
||||
#include "Disk.h"
|
||||
#include "SaveState.h"
|
||||
|
||||
#include <libgen.h>
|
||||
#include <unistd.h>
|
||||
|
||||
bool DoDiskInsert(const UINT slot, const int nDrive, const std::string & fileName, const bool createMissingDisk)
|
||||
{
|
||||
std::string strPathName;
|
||||
|
||||
if (fileName.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fileName[0] == '/')
|
||||
{
|
||||
// Abs pathname
|
||||
strPathName = fileName;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rel pathname
|
||||
char szCWD[MAX_PATH] = {0};
|
||||
if (!GetCurrentDirectory(sizeof(szCWD), szCWD))
|
||||
return false;
|
||||
|
||||
strPathName = szCWD;
|
||||
strPathName.append("/");
|
||||
strPathName.append(fileName);
|
||||
}
|
||||
|
||||
Disk2InterfaceCard* pDisk2Card = dynamic_cast<Disk2InterfaceCard*> (g_CardMgr.GetObj(slot));
|
||||
ImageError_e Error = pDisk2Card->InsertDisk(nDrive, strPathName.c_str(), IMAGE_USE_FILES_WRITE_PROTECT_STATUS, createMissingDisk);
|
||||
return Error == eIMAGE_ERROR_NONE;
|
||||
}
|
||||
|
||||
void setSnapshotFilename(const std::string & filename)
|
||||
{
|
||||
// same logic as qapple
|
||||
// setting chdir allows to load relative disks from the snapshot file (tests?)
|
||||
// but if the snapshot file itself is relative, it wont work after a chdir
|
||||
// so we convert to absolute first
|
||||
char * absPath = realpath(filename.c_str(), nullptr);
|
||||
if (absPath)
|
||||
{
|
||||
char * temp = strdup(absPath);
|
||||
const char * dir = dirname(temp);
|
||||
// dir points inside temp!
|
||||
chdir(dir);
|
||||
Snapshot_SetFilename(absPath);
|
||||
|
||||
free(temp);
|
||||
free(absPath);
|
||||
Snapshot_LoadState();
|
||||
}
|
||||
}
|
6
source/frontends/common2/utils.h
Normal file
6
source/frontends/common2/utils.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include <string>
|
||||
#include <linux/windows/wincompat.h>
|
||||
|
||||
bool DoDiskInsert(const UINT slot, const int nDrive, const std::string & fileName, const bool createMissingDisk);
|
||||
|
||||
void setSnapshotFilename(const std::string & filename);
|
|
@ -1,5 +1,4 @@
|
|||
include(FindPkgConfig)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
add_executable(applen
|
||||
main.cpp
|
||||
|
@ -8,18 +7,13 @@ add_executable(applen
|
|||
evdevpaddle.cpp
|
||||
nframe.cpp
|
||||
asciiart.cpp
|
||||
resources.cpp
|
||||
configuration.cpp
|
||||
bitmaps.cpp
|
||||
)
|
||||
|
||||
pkg_search_module(NCURSESW REQUIRED ncursesw)
|
||||
pkg_search_module(LIBEVDEV REQUIRED libevdev)
|
||||
find_package(Boost REQUIRED
|
||||
COMPONENTS program_options
|
||||
)
|
||||
|
||||
target_include_directories(applen PRIVATE
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${NCURSESW_INCLUDE_DIRS}
|
||||
${LIBEVDEV_INCLUDE_DIRS}
|
||||
${Boost_INCLUDE_DIRS}
|
||||
|
@ -33,17 +27,9 @@ target_compile_options(applen PRIVATE
|
|||
target_link_libraries(applen PRIVATE
|
||||
${NCURSESW_LIBRARIES}
|
||||
${LIBEVDEV_LIBRARIES}
|
||||
Boost::program_options
|
||||
appleii
|
||||
common2
|
||||
)
|
||||
|
||||
file(RELATIVE_PATH ROOT_PATH ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR})
|
||||
file(RELATIVE_PATH SHARE_PATH ${CMAKE_INSTALL_FULL_BINDIR} ${CMAKE_INSTALL_FULL_DATADIR}/applewin)
|
||||
|
||||
configure_file(config.h.in config.h)
|
||||
|
||||
install(TARGETS applen
|
||||
DESTINATION bin)
|
||||
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/resource
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/applewin)
|
||||
|
|
14
source/frontends/ncurses/bitmaps.cpp
Normal file
14
source/frontends/ncurses/bitmaps.cpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include "StdAfx.h"
|
||||
#include "Log.h"
|
||||
|
||||
HBITMAP LoadBitmap(HINSTANCE hInstance, const char * filename)
|
||||
{
|
||||
LogFileOutput("LoadBitmap: not loading resource %s\n", filename);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LONG GetBitmapBits(HBITMAP hbit, LONG cb, LPVOID lpvBits)
|
||||
{
|
||||
memset(lpvBits, 0, cb);
|
||||
return cb;
|
||||
}
|
|
@ -4,9 +4,6 @@
|
|||
#include <thread>
|
||||
#include <iostream>
|
||||
#include <ncurses.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include "Common.h"
|
||||
#include "CardManager.h"
|
||||
|
@ -27,116 +24,13 @@
|
|||
|
||||
#include "linux/data.h"
|
||||
#include "linux/benchmark.h"
|
||||
#include "frontends/ncurses/configuration.h"
|
||||
#include "frontends/common2/configuration.h"
|
||||
#include "frontends/common2/programoptions.h"
|
||||
#include "frontends/common2/utils.h"
|
||||
#include "frontends/ncurses/world.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace po = boost::program_options;
|
||||
|
||||
struct EmulatorOptions
|
||||
{
|
||||
std::string disk1;
|
||||
std::string disk2;
|
||||
bool createMissingDisks;
|
||||
std::string snapshot;
|
||||
int memclear;
|
||||
bool log;
|
||||
bool benchmark;
|
||||
bool headless;
|
||||
bool ntsc;
|
||||
bool saveConfigurationOnExit;
|
||||
|
||||
bool run; // false if options include "-h"
|
||||
};
|
||||
|
||||
bool getEmulatorOptions(int argc, const char * argv [], EmulatorOptions & options)
|
||||
{
|
||||
po::options_description desc("AppleWin ncurses");
|
||||
desc.add_options()
|
||||
("help,h", "Print this help message")
|
||||
("conf", "Save configuration on exit");
|
||||
|
||||
po::options_description diskDesc("Disk");
|
||||
diskDesc.add_options()
|
||||
("d1,1", po::value<std::string>(), "Mount disk image in first drive")
|
||||
("d2,2", po::value<std::string>(), "Mount disk image in second drive")
|
||||
("create,c", "Create missing disks");
|
||||
desc.add(diskDesc);
|
||||
|
||||
po::options_description snapshotDesc("Snapshot");
|
||||
snapshotDesc.add_options()
|
||||
("load-state,ls", po::value<std::string>(), "Load snapshot from file");
|
||||
desc.add(snapshotDesc);
|
||||
|
||||
po::options_description memoryDesc("Memory");
|
||||
memoryDesc.add_options()
|
||||
("memclear,m", po::value<int>(), "Memory initialization pattern [0..7]");
|
||||
desc.add(memoryDesc);
|
||||
|
||||
po::options_description emulatorDesc("Emulator");
|
||||
emulatorDesc.add_options()
|
||||
("log", "Log to AppleWin.log")
|
||||
("headless,hl", "Headless: disable video")
|
||||
("ntsc,nt", "NTSC: execute NTSC code")
|
||||
("benchmark,b", "Benchmark emulator");
|
||||
desc.add(emulatorDesc);
|
||||
|
||||
po::variables_map vm;
|
||||
try
|
||||
{
|
||||
po::store(po::parse_command_line(argc, argv, desc), vm);
|
||||
|
||||
if (vm.count("help"))
|
||||
{
|
||||
std::cout << "AppleWin ncurses edition" << std::endl << std::endl << desc << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
options.saveConfigurationOnExit = vm.count("conf");
|
||||
|
||||
if (vm.count("d1"))
|
||||
{
|
||||
options.disk1 = vm["d1"].as<std::string>();
|
||||
}
|
||||
|
||||
if (vm.count("d2"))
|
||||
{
|
||||
options.disk2 = vm["d2"].as<std::string>();
|
||||
}
|
||||
|
||||
options.createMissingDisks = vm.count("create") > 0;
|
||||
|
||||
if (vm.count("load-state"))
|
||||
{
|
||||
options.snapshot = vm["load-state"].as<std::string>();
|
||||
}
|
||||
|
||||
if (vm.count("memclear"))
|
||||
{
|
||||
const int memclear = vm["memclear"].as<int>();
|
||||
if (memclear >=0 && memclear < NUM_MIP)
|
||||
options.memclear = memclear;
|
||||
}
|
||||
|
||||
options.benchmark = vm.count("benchmark") > 0;
|
||||
options.headless = vm.count("headless") > 0;
|
||||
options.log = vm.count("log") > 0;
|
||||
options.ntsc = vm.count("ntsc") > 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (const po::error& e)
|
||||
{
|
||||
std::cerr << "ERROR: " << e.what() << std::endl << desc << std::endl;
|
||||
return false;
|
||||
}
|
||||
catch (const std::exception & e)
|
||||
{
|
||||
std::cerr << "ERROR: " << e.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ContinueExecution(const EmulatorOptions & options)
|
||||
{
|
||||
|
@ -229,63 +123,11 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
bool DoDiskInsert(const UINT slot, const int nDrive, const std::string & fileName, const bool createMissingDisk)
|
||||
{
|
||||
std::string strPathName;
|
||||
|
||||
if (fileName.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fileName[0] == '/')
|
||||
{
|
||||
// Abs pathname
|
||||
strPathName = fileName;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rel pathname
|
||||
char szCWD[MAX_PATH] = {0};
|
||||
if (!GetCurrentDirectory(sizeof(szCWD), szCWD))
|
||||
return false;
|
||||
|
||||
strPathName = szCWD;
|
||||
strPathName.append("/");
|
||||
strPathName.append(fileName);
|
||||
}
|
||||
|
||||
Disk2InterfaceCard* pDisk2Card = dynamic_cast<Disk2InterfaceCard*> (g_CardMgr.GetObj(slot));
|
||||
ImageError_e Error = pDisk2Card->InsertDisk(nDrive, strPathName.c_str(), IMAGE_USE_FILES_WRITE_PROTECT_STATUS, createMissingDisk);
|
||||
return Error == eIMAGE_ERROR_NONE;
|
||||
}
|
||||
|
||||
void setSnapshotFilename(const std::string & filename)
|
||||
{
|
||||
// same logic as qapple
|
||||
// setting chdir allows to load relative disks from the snapshot file (tests?)
|
||||
// but if the snapshot file itself is relative, it wont work after a chdir
|
||||
// so we convert to absolute first
|
||||
char * absPath = realpath(filename.c_str(), nullptr);
|
||||
if (absPath)
|
||||
{
|
||||
char * temp = strdup(absPath);
|
||||
const char * dir = dirname(temp);
|
||||
// dir points inside temp!
|
||||
chdir(dir);
|
||||
Snapshot_SetFilename(absPath);
|
||||
|
||||
free(temp);
|
||||
free(absPath);
|
||||
Snapshot_LoadState();
|
||||
}
|
||||
}
|
||||
|
||||
int foo(int argc, const char * argv [])
|
||||
{
|
||||
EmulatorOptions options;
|
||||
options.memclear = g_nMemoryClearType;
|
||||
const bool run = getEmulatorOptions(argc, argv, options);
|
||||
const bool run = getEmulatorOptions(argc, argv, "ncurses", options);
|
||||
|
||||
if (!run)
|
||||
return 1;
|
||||
|
|
29
source/frontends/sa2/CMakeLists.txt
Normal file
29
source/frontends/sa2/CMakeLists.txt
Normal file
|
@ -0,0 +1,29 @@
|
|||
include(FindPkgConfig)
|
||||
|
||||
add_executable(sa2
|
||||
main.cpp
|
||||
bitmaps.cpp
|
||||
)
|
||||
|
||||
find_package(Boost REQUIRED
|
||||
COMPONENTS program_options
|
||||
)
|
||||
|
||||
find_package(SDL2 REQUIRED)
|
||||
|
||||
target_compile_features(sa2 PUBLIC cxx_std_17)
|
||||
|
||||
target_include_directories(sa2 PRIVATE
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${SDL2_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(sa2 PRIVATE
|
||||
Boost::program_options
|
||||
${SDL2_LIBRARIES}
|
||||
appleii
|
||||
common2
|
||||
)
|
||||
|
||||
install(TARGETS sa2
|
||||
DESTINATION bin)
|
82
source/frontends/sa2/bitmaps.cpp
Normal file
82
source/frontends/sa2/bitmaps.cpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
#include <SDL.h>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
|
||||
#include <linux/interface.h>
|
||||
#include <linux/windows/misc.h>
|
||||
#include <frontends/common2/resources.h>
|
||||
|
||||
struct CBITMAP : public CHANDLE
|
||||
{
|
||||
std::shared_ptr<SDL_Surface> surface;
|
||||
};
|
||||
|
||||
std::string getFilename(const std::string & resource)
|
||||
{
|
||||
if (resource == "CHARSET40") return "CHARSET4.BMP";
|
||||
if (resource == "CHARSET82") return "CHARSET82.bmp";
|
||||
if (resource == "CHARSET8M") return "CHARSET8M.bmp";
|
||||
if (resource == "CHARSET8C") return "CHARSET8C.bmp";
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
HBITMAP LoadBitmap(HINSTANCE hInstance, const char * resource)
|
||||
{
|
||||
if (resource)
|
||||
{
|
||||
const std::string filename = getFilename(resource);
|
||||
const std::string path = getResourcePath() + filename;
|
||||
|
||||
std::shared_ptr<SDL_Surface> surface(SDL_LoadBMP(path.c_str()), SDL_FreeSurface);
|
||||
if (surface)
|
||||
{
|
||||
CBITMAP * bitmap = new CBITMAP;
|
||||
bitmap->surface = surface;
|
||||
return bitmap;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Cannot load: " << resource << " with path: " << path << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Cannot load invalid resource." << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
LONG GetBitmapBits(HBITMAP hbit, LONG cb, LPVOID lpvBits)
|
||||
{
|
||||
const CBITMAP & bitmap = dynamic_cast<CBITMAP&>(*hbit);
|
||||
|
||||
SDL_LockSurface(bitmap.surface.get());
|
||||
|
||||
const SDL_Surface * surface = bitmap.surface.get();
|
||||
|
||||
const char * source = static_cast<char *>(surface->pixels);
|
||||
const size_t size = surface->h * surface->w / 8;
|
||||
const size_t requested = cb;
|
||||
|
||||
const size_t copied = std::min(requested, size);
|
||||
|
||||
char * dest = static_cast<char *>(lpvBits);
|
||||
|
||||
for (size_t i = 0; i < copied; ++i)
|
||||
{
|
||||
const size_t offset = i * 8;
|
||||
char val = 0;
|
||||
for (size_t j = 0; j < 8; ++j)
|
||||
{
|
||||
const char pixel = *(source + offset + j);
|
||||
val = (val << 1) | pixel;
|
||||
}
|
||||
dest[i] = val;
|
||||
}
|
||||
|
||||
SDL_UnlockSurface(bitmap.surface.get());
|
||||
|
||||
return copied;
|
||||
}
|
347
source/frontends/sa2/main.cpp
Normal file
347
source/frontends/sa2/main.cpp
Normal file
|
@ -0,0 +1,347 @@
|
|||
#include <iostream>
|
||||
#include <SDL.h>
|
||||
#include <memory>
|
||||
|
||||
#include "linux/interface.h"
|
||||
#include "linux/windows/misc.h"
|
||||
#include "linux/data.h"
|
||||
#include "frontends/common2/configuration.h"
|
||||
#include "frontends/common2/utils.h"
|
||||
#include "frontends/common2/programoptions.h"
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "Common.h"
|
||||
#include "CardManager.h"
|
||||
#include "Applewin.h"
|
||||
#include "Disk.h"
|
||||
#include "Harddisk.h"
|
||||
#include "Log.h"
|
||||
#include "CPU.h"
|
||||
#include "Frame.h"
|
||||
#include "Memory.h"
|
||||
#include "LanguageCard.h"
|
||||
#include "MouseInterface.h"
|
||||
#include "ParallelPrinter.h"
|
||||
#include "Video.h"
|
||||
#include "NTSC.h"
|
||||
#include "SaveState.h"
|
||||
#include "RGBMonitor.h"
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
void initialiseEmulator()
|
||||
{
|
||||
InitializeRegistry("applen.conf");
|
||||
|
||||
g_fh = fopen("/tmp/applewin.txt", "w");
|
||||
setbuf(g_fh, nullptr);
|
||||
|
||||
LogFileOutput("Initialisation\n");
|
||||
|
||||
ImageInitialize();
|
||||
g_bFullSpeed = false;
|
||||
}
|
||||
|
||||
void loadEmulator()
|
||||
{
|
||||
LoadConfiguration();
|
||||
CheckCpu();
|
||||
SetWindowTitle();
|
||||
FrameRefreshStatus(DRAW_LEDS | DRAW_BUTTON_DRIVES);
|
||||
ResetDefaultMachineMemTypes();
|
||||
|
||||
MemInitialize();
|
||||
VideoInitialize();
|
||||
VideoSwitchVideocardPalette(RGB_GetVideocard(), GetVideoType());
|
||||
|
||||
g_CardMgr.GetDisk2CardMgr().Reset();
|
||||
HD_Reset();
|
||||
}
|
||||
|
||||
void applyOptions(const EmulatorOptions & options)
|
||||
{
|
||||
if (options.log)
|
||||
{
|
||||
LogInit();
|
||||
}
|
||||
|
||||
bool disksOk = true;
|
||||
if (!options.disk1.empty())
|
||||
{
|
||||
const bool ok = DoDiskInsert(SLOT6, DRIVE_1, options.disk1, options.createMissingDisks);
|
||||
disksOk = disksOk && ok;
|
||||
LogFileOutput("Init: DoDiskInsert(D1), res=%d\n", ok);
|
||||
}
|
||||
|
||||
if (!options.disk2.empty())
|
||||
{
|
||||
const bool ok = DoDiskInsert(SLOT6, DRIVE_2, options.disk2, options.createMissingDisks);
|
||||
disksOk = disksOk && ok;
|
||||
LogFileOutput("Init: DoDiskInsert(D2), res=%d\n", ok);
|
||||
}
|
||||
|
||||
if (!options.snapshot.empty())
|
||||
{
|
||||
setSnapshotFilename(options.snapshot);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void stopEmulator()
|
||||
{
|
||||
CMouseInterface* pMouseCard = g_CardMgr.GetMouseCard();
|
||||
if (pMouseCard)
|
||||
{
|
||||
pMouseCard->Reset();
|
||||
}
|
||||
MemDestroy();
|
||||
}
|
||||
|
||||
void uninitialiseEmulator()
|
||||
{
|
||||
HD_Destroy();
|
||||
PrintDestroy();
|
||||
CpuDestroy();
|
||||
|
||||
g_CardMgr.GetDisk2CardMgr().Destroy();
|
||||
ImageDestroy();
|
||||
fclose(g_fh);
|
||||
g_fh = nullptr;
|
||||
}
|
||||
|
||||
SDL_Rect refreshTexture(const std::shared_ptr<SDL_Texture> & tex)
|
||||
{
|
||||
uint8_t * data;
|
||||
int width;
|
||||
int height;
|
||||
int sx, sy;
|
||||
int sw, sh;
|
||||
|
||||
getScreenData(data, width, height, sx, sy, sw, sh);
|
||||
|
||||
void * pixels;
|
||||
int pitch;
|
||||
SDL_LockTexture(tex.get(), nullptr, &pixels, &pitch);
|
||||
|
||||
memcpy(pixels, data, width * height * 4);
|
||||
|
||||
SDL_UnlockTexture(tex.get());
|
||||
|
||||
SDL_Rect srect;
|
||||
srect.x = sx;
|
||||
srect.y = sy;
|
||||
srect.w = sw;
|
||||
srect.h = sh;
|
||||
|
||||
return srect;
|
||||
}
|
||||
|
||||
void renderScreen(const std::shared_ptr<SDL_Renderer> & ren, const std::shared_ptr<SDL_Texture> & tex, const SDL_Rect & srect)
|
||||
{
|
||||
SDL_RenderCopyEx(ren.get(), tex.get(), &srect, nullptr, 0.0, nullptr, SDL_FLIP_VERTICAL);
|
||||
SDL_RenderPresent(ren.get());
|
||||
}
|
||||
|
||||
void cycleVideoType(const std::shared_ptr<SDL_Window> & win)
|
||||
{
|
||||
g_eVideoType++;
|
||||
if (g_eVideoType >= NUM_VIDEO_MODES)
|
||||
g_eVideoType = 0;
|
||||
|
||||
SetWindowTitle();
|
||||
SDL_SetWindowTitle(win.get(), g_pAppTitle.c_str());
|
||||
|
||||
Config_Save_Video();
|
||||
VideoReinitialize();
|
||||
VideoRedrawScreen();
|
||||
}
|
||||
|
||||
void cycle50ScanLines(const std::shared_ptr<SDL_Window> & win)
|
||||
{
|
||||
VideoStyle_e videoStyle = GetVideoStyle();
|
||||
videoStyle = VideoStyle_e(videoStyle ^ VS_HALF_SCANLINES);
|
||||
|
||||
SetVideoStyle(videoStyle);
|
||||
|
||||
SetWindowTitle();
|
||||
SDL_SetWindowTitle(win.get(), g_pAppTitle.c_str());
|
||||
|
||||
Config_Save_Video();
|
||||
VideoReinitialize();
|
||||
VideoRedrawScreen();
|
||||
}
|
||||
|
||||
int getFPS()
|
||||
{
|
||||
SDL_DisplayMode current;
|
||||
|
||||
int should_be_zero = SDL_GetCurrentDisplayMode(0, ¤t);
|
||||
|
||||
if (should_be_zero)
|
||||
{
|
||||
throw std::string(SDL_GetError());
|
||||
}
|
||||
|
||||
return current.refresh_rate;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int MessageBox(HWND, const char * text, const char * caption, UINT type)
|
||||
{
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, caption, text, nullptr);
|
||||
return IDOK;
|
||||
}
|
||||
|
||||
void FrameDrawDiskLEDS(HDC x)
|
||||
{
|
||||
}
|
||||
|
||||
void FrameDrawDiskStatus(HDC x)
|
||||
{
|
||||
}
|
||||
|
||||
void FrameRefreshStatus(int x, bool)
|
||||
{
|
||||
}
|
||||
|
||||
BYTE SpkrToggle (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG uExecutedCycles)
|
||||
{
|
||||
return MemReadFloatingBus(uExecutedCycles);
|
||||
}
|
||||
|
||||
|
||||
// Mockingboard
|
||||
void registerSoundBuffer(IDirectSoundBuffer * buffer)
|
||||
{
|
||||
}
|
||||
|
||||
void unregisterSoundBuffer(IDirectSoundBuffer * buffer)
|
||||
{
|
||||
}
|
||||
|
||||
void run_sdl(int argc, const char * argv [])
|
||||
{
|
||||
EmulatorOptions options;
|
||||
options.memclear = g_nMemoryClearType;
|
||||
const bool run = getEmulatorOptions(argc, argv, "SDL2", options);
|
||||
|
||||
if (!run)
|
||||
return;
|
||||
|
||||
initialiseEmulator();
|
||||
loadEmulator();
|
||||
|
||||
const int width = GetFrameBufferWidth();
|
||||
const int height = GetFrameBufferHeight();
|
||||
const int sx = GetFrameBufferBorderWidth();
|
||||
const int sy = GetFrameBufferBorderHeight();
|
||||
const int sw = GetFrameBufferBorderlessWidth();
|
||||
const int sh = GetFrameBufferBorderlessHeight();
|
||||
|
||||
int multiplier = 1;
|
||||
|
||||
std::shared_ptr<SDL_Window> win(SDL_CreateWindow(g_pAppTitle.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, sw, sh, SDL_WINDOW_SHOWN), SDL_DestroyWindow);
|
||||
if (!win)
|
||||
{
|
||||
std::cerr << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<SDL_Renderer> ren(SDL_CreateRenderer(win.get(), -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC), SDL_DestroyRenderer);
|
||||
if (!ren)
|
||||
{
|
||||
std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
const Uint32 format = SDL_PIXELFORMAT_BGRA32;
|
||||
std::shared_ptr<SDL_Texture> tex(SDL_CreateTexture(ren.get(), format, SDL_TEXTUREACCESS_STREAMING, width, height), SDL_DestroyTexture);
|
||||
|
||||
const int fps = getFPS();
|
||||
const DWORD uCyclesToExecute = int(g_fCurrentCLK6502 / fps);
|
||||
const UINT dwClksPerFrame = NTSC_GetCyclesPerFrame();
|
||||
|
||||
bool quit = false;
|
||||
do
|
||||
{
|
||||
SDL_Event e;
|
||||
while (SDL_PollEvent(&e) != 0)
|
||||
{
|
||||
if (e.type == SDL_QUIT)
|
||||
{
|
||||
quit = true;
|
||||
}
|
||||
else if (e.type == SDL_KEYDOWN)
|
||||
{
|
||||
if (!e.key.repeat)
|
||||
{
|
||||
switch (e.key.keysym.scancode)
|
||||
{
|
||||
case SDL_SCANCODE_F9:
|
||||
{
|
||||
cycleVideoType(win);
|
||||
break;
|
||||
}
|
||||
case SDL_SCANCODE_F6:
|
||||
{
|
||||
if ((e.key.keysym.mod & KMOD_CTRL) && (e.key.keysym.mod & KMOD_SHIFT))
|
||||
{
|
||||
cycle50ScanLines(win);
|
||||
}
|
||||
else if (e.key.keysym.mod & KMOD_CTRL)
|
||||
{
|
||||
multiplier = multiplier == 1 ? 2 : 1;
|
||||
SDL_SetWindowSize(win.get(), sw * multiplier, sh * multiplier);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cerr << e.key.keysym.scancode << "," << e.key.keysym.sym << "," << e.key.keysym.mod << "," << bool(e.key.repeat) << ",AAA" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
const bool bVideoUpdate = true;
|
||||
const DWORD uActualCyclesExecuted = CpuExecute(uCyclesToExecute, bVideoUpdate);
|
||||
g_dwCyclesThisFrame += uActualCyclesExecuted;
|
||||
|
||||
g_CardMgr.GetDisk2CardMgr().UpdateDriveState(uActualCyclesExecuted);
|
||||
|
||||
// SDL2 seems to synch with screen refresh rate so we do not need to worry about timers
|
||||
const SDL_Rect srect = refreshTexture(tex);
|
||||
renderScreen(ren, tex, srect);
|
||||
|
||||
g_dwCyclesThisFrame = (g_dwCyclesThisFrame + g_dwCyclesThisFrame) % dwClksPerFrame;
|
||||
} while (!quit);
|
||||
|
||||
stopEmulator();
|
||||
uninitialiseEmulator();
|
||||
}
|
||||
|
||||
int main(int argc, const char * argv [])
|
||||
{
|
||||
//First we need to start up SDL, and make sure it went ok
|
||||
if (SDL_Init(SDL_INIT_VIDEO) != 0)
|
||||
{
|
||||
std::cerr << "SDL_Init Error: " << SDL_GetError() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int exit = 0;
|
||||
|
||||
try
|
||||
{
|
||||
run_sdl(argc, argv);
|
||||
}
|
||||
catch (const std::exception & e)
|
||||
{
|
||||
exit = 2;
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
|
||||
SDL_Quit();
|
||||
|
||||
return exit;
|
||||
}
|
Loading…
Add table
Reference in a new issue