Fix code formatting again, add debuging tools

This commit is contained in:
meepingsnesroms
2018-04-15 19:44:13 -07:00
parent 1e4c74d2ac
commit 3b4c0d8786
10 changed files with 280 additions and 201 deletions

View File

@@ -18,7 +18,7 @@ TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS
CONFIG(debug, debug|release){
DEFINES += EMU_DEBUG
DEFINES += EMU_DEBUG EMU_OPCODE_LEVEL_DEBUG
}
# You can also make your code fail to compile if you use deprecated APIs.

View File

@@ -3,12 +3,12 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
QApplication a(argc, argv);
MainWindow w;
a.setOrganizationDomain("meepingsnesroms.github.com");
a.setApplicationName("Mu");
w.show();
a.setOrganizationDomain("meepingsnesroms.github.com");
a.setApplicationName("Mu");
w.show();
return a.exec();
return a.exec();
}

View File

@@ -31,244 +31,252 @@ static uint8_t romBuffer[ROM_SIZE];
void popupErrorDialog(std::string error){
//add error dialog code
//add error dialog code
}
uint8_t* getFileBuffer(std::string filePath, size_t& size, uint32_t& error){
uint8_t* rawData = NULL;
if(filePath != ""){
struct stat st;
int doesntExist = stat(filePath.c_str(), &st);
if(doesntExist == 0 && st.st_size){
FILE* dataFile = fopen(filePath.c_str(), "rb");
if(dataFile != NULL){
rawData = new (std::nothrow) uint8_t[st.st_size];
if(rawData){
size_t bytesRead = fread(rawData, 1, st.st_size, dataFile);
if(bytesRead == (size_t)st.st_size){
size = bytesRead;
error = FRONTEND_ERR_NONE;
}
else{
error = FRONTEND_FILE_UNFINISHED;
}
}
else{
error = FRONTEND_OUT_OF_MEMORY;
}
fclose(dataFile);
uint8_t* rawData = NULL;
if(filePath != ""){
struct stat st;
int doesntExist = stat(filePath.c_str(), &st);
if(doesntExist == 0 && st.st_size){
FILE* dataFile = fopen(filePath.c_str(), "rb");
if(dataFile != NULL){
rawData = new (std::nothrow) uint8_t[st.st_size];
if(rawData){
size_t bytesRead = fread(rawData, 1, st.st_size, dataFile);
if(bytesRead == (size_t)st.st_size){
size = bytesRead;
error = FRONTEND_ERR_NONE;
}
else{
error = FRONTEND_FILE_UNFINISHED;
}
}
else{
error = FRONTEND_FILE_PROTECTED;
error = FRONTEND_OUT_OF_MEMORY;
}
}
else{
error = FRONTEND_FILE_DOESNT_EXIST;
}
}
else{
error = FRONTEND_FILE_EMPTY_PATH;
}
fclose(dataFile);
}
else{
error = FRONTEND_FILE_PROTECTED;
}
}
else{
error = FRONTEND_FILE_DOESNT_EXIST;
}
}
else{
error = FRONTEND_FILE_EMPTY_PATH;
}
if(error != FRONTEND_ERR_NONE){
if(rawData)
delete[] rawData;
rawData = NULL;
size = 0;
}
if(error != FRONTEND_ERR_NONE){
if(rawData)
delete[] rawData;
rawData = NULL;
size = 0;
}
return rawData;
return rawData;
}
MainWindow::MainWindow(QWidget* parent) :
QMainWindow(parent),
ui(new Ui::MainWindow){
ui->setupUi(this);
emuOn = false;
emuInited = false;
screenWidth = 160;
screenHeight = 160 + 60;
QMainWindow(parent),
ui(new Ui::MainWindow){
ui->setupUi(this);
emuOn = false;
emuInited = false;
screenWidth = 160;
screenHeight = 160 + 60;
loadRom();
loadRom();
ui->ctrlBtn->setText("Start");
ui->ctrlBtn->setText("Start");
refreshDisplay = new QTimer(this);
connect(refreshDisplay, SIGNAL(timeout()), this, SLOT(updateDisplay()));
//update display every 16.67 miliseconds = 60*second
refreshDisplay->start(16);
refreshDisplay = new QTimer(this);
connect(refreshDisplay, SIGNAL(timeout()), this, SLOT(updateDisplay()));
//update display every 16.67 miliseconds = 60*second
refreshDisplay->start(16);
}
MainWindow::~MainWindow(){
emuMutex.lock();
emulatorExit();
emuMutex.unlock();
delete ui;
emuMutex.lock();
emulatorExit();
emuMutex.unlock();
delete ui;
}
void MainWindow::loadRom(){
std::string rom = settings.value("romPath", "").toString().toStdString();
if(rom == ""){
//keep the selector open until a valid file is picked
while(settings.value("romPath", "").toString().toStdString() == "")
selectRom();
}
std::string rom = settings.value("romPath", "").toString().toStdString();
if(rom == ""){
//keep the selector open until a valid file is picked
while(settings.value("romPath", "").toString().toStdString() == "")
selectRom();
}
uint32_t error;
size_t size;
uint8_t* romData = getFileBuffer(rom, size, error);
if(romData){
size_t romSize = size < ROM_SIZE ? size : ROM_SIZE;
memcpy(romBuffer, romData, romSize);
if(romSize < ROM_SIZE)
memset(romBuffer + romSize, 0x00, ROM_SIZE - romSize);
delete[] romData;
}
uint32_t error;
size_t size;
uint8_t* romData = getFileBuffer(rom, size, error);
if(romData){
size_t romSize = size < ROM_SIZE ? size : ROM_SIZE;
memcpy(romBuffer, romData, romSize);
if(romSize < ROM_SIZE)
memset(romBuffer + romSize, 0x00, ROM_SIZE - romSize);
delete[] romData;
}
if(error != FRONTEND_ERR_NONE){
popupErrorDialog("Could not open ROM file");
}
if(error != FRONTEND_ERR_NONE){
popupErrorDialog("Could not open ROM file");
}
}
void MainWindow::selectRom(){
std::string rom = QFileDialog::getOpenFileName(this, "Palm OS ROM (palmos41-en-m515.rom)", QDir::root().path(), 0).toStdString();
uint32_t error;
size_t size;
uint8_t* romData = getFileBuffer(rom, size, error);
if(romData){
//valid file
settings.setValue("romPath", QString::fromStdString(rom));
delete[] romData;
}
std::string rom = QFileDialog::getOpenFileName(this, "Palm OS ROM (palmos41-en-m515.rom)", QDir::root().path(), 0).toStdString();
uint32_t error;
size_t size;
uint8_t* romData = getFileBuffer(rom, size, error);
if(romData){
//valid file
settings.setValue("romPath", QString::fromStdString(rom));
delete[] romData;
}
if(error != FRONTEND_ERR_NONE){
popupErrorDialog("Could not open ROM file");
}
if(error != FRONTEND_ERR_NONE){
popupErrorDialog("Could not open ROM file");
}
}
void MainWindow::on_install_pressed(){
std::string app = QFileDialog::getOpenFileName(this, "Open Prc/Pdb/Pqa", QDir::root().path(), 0).toStdString();
uint32_t error;
size_t size;
uint8_t* appData = getFileBuffer(app, size, error);
if(appData){
error = emulatorInstallPrcPdb(appData, size);
delete[] appData;
}
std::string app = QFileDialog::getOpenFileName(this, "Open Prc/Pdb/Pqa", QDir::root().path(), 0).toStdString();
uint32_t error;
size_t size;
uint8_t* appData = getFileBuffer(app, size, error);
if(appData){
error = emulatorInstallPrcPdb(appData, size);
delete[] appData;
}
if(error != FRONTEND_ERR_NONE){
popupErrorDialog("Could not install app");
}
if(error != FRONTEND_ERR_NONE)
popupErrorDialog("Could not install app");
}
//display
void MainWindow::updateDisplay(){
if(emuOn){
if(emuMutex.try_lock()){
emulateFrame();
video = QImage((unsigned char*)palmFramebuffer, screenWidth, screenHeight, QImage::Format_RGB16);//16 bit
ui->display->setPixmap(QPixmap::fromImage(video).scaled(ui->display->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
ui->display->update();
emuMutex.unlock();
}
}
if(emuOn){
if(emuMutex.try_lock()){
#ifdef EMU_DEBUG
if(emulateUntilDebugEventOrFrameEnd()){
//debug event occured
emuOn = false;
ui->ctrlBtn->setText("Resume");
}
#else
emulateFrame();
#endif
video = QImage((unsigned char*)palmFramebuffer, screenWidth, screenHeight, QImage::Format_RGB16);//16 bit
ui->display->setPixmap(QPixmap::fromImage(video).scaled(ui->display->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
ui->display->update();
emuMutex.unlock();
}
}
}
void MainWindow::on_display_destroyed(){
//do nothing
//do nothing
}
//palm buttons
void MainWindow::on_power_pressed(){
palmInput.buttonPower = true;
palmInput.buttonPower = true;
}
void MainWindow::on_power_released(){
palmInput.buttonPower = false;
palmInput.buttonPower = false;
}
void MainWindow::on_calender_pressed(){
palmInput.buttonCalender = true;
palmInput.buttonCalender = true;
}
void MainWindow::on_calender_released(){
palmInput.buttonCalender = false;
palmInput.buttonCalender = false;
}
void MainWindow::on_addressBook_pressed(){
palmInput.buttonAddress = true;
palmInput.buttonAddress = true;
}
void MainWindow::on_addressBook_released(){
palmInput.buttonAddress = false;
palmInput.buttonAddress = false;
}
void MainWindow::on_todo_pressed(){
palmInput.buttonTodo = true;
palmInput.buttonTodo = true;
}
void MainWindow::on_todo_released(){
palmInput.buttonTodo = false;
palmInput.buttonTodo = false;
}
void MainWindow::on_notes_pressed(){
palmInput.buttonNotes = true;
palmInput.buttonNotes = true;
}
void MainWindow::on_notes_released(){
palmInput.buttonNotes = false;
palmInput.buttonNotes = false;
}
//ui buttons
void MainWindow::on_mainLeft_clicked(){
ui->controlPanel->setCurrentWidget(ui->controlPanel->widget(2));
ui->controlPanel->setCurrentWidget(ui->controlPanel->widget(2));
}
void MainWindow::on_mainRight_clicked(){
ui->controlPanel->setCurrentWidget(ui->controlPanel->widget(1));
ui->controlPanel->setCurrentWidget(ui->controlPanel->widget(1));
}
void MainWindow::on_settingsLeft_clicked(){
ui->controlPanel->setCurrentWidget(ui->controlPanel->widget(0));
ui->controlPanel->setCurrentWidget(ui->controlPanel->widget(0));
}
void MainWindow::on_settingsRight_clicked(){
ui->controlPanel->setCurrentWidget(ui->controlPanel->widget(2));
ui->controlPanel->setCurrentWidget(ui->controlPanel->widget(2));
}
void MainWindow::on_joyLeft_clicked(){
ui->controlPanel->setCurrentWidget(ui->controlPanel->widget(1));
ui->controlPanel->setCurrentWidget(ui->controlPanel->widget(1));
}
void MainWindow::on_joyRight_clicked(){
ui->controlPanel->setCurrentWidget(ui->controlPanel->widget(0));
ui->controlPanel->setCurrentWidget(ui->controlPanel->widget(0));
}
void MainWindow::on_settings_clicked(){
//setprocess(SETUP);
//setprocess(SETUP);
}
//emu control
void MainWindow::on_ctrlBtn_clicked()
{
emuMutex.lock();
if(!emuOn && !emuInited){
//start emu
emulatorInit(romBuffer, NULL/*bootloader*/, ACCURATE);
emuInited = true;
emuOn = true;
ui->ctrlBtn->setText("Pause");
}
else if(emuOn){
emuOn = false;
ui->ctrlBtn->setText("Resume");
}
else if(!emuOn){
emuOn = true;
ui->ctrlBtn->setText("Pause");
}
emuMutex.unlock();
emuMutex.lock();
if(!emuOn && !emuInited){
//start emu
emulatorInit(romBuffer, NULL/*bootloader*/, ACCURATE);
emuInited = true;
emuOn = true;
ui->ctrlBtn->setText("Pause");
}
else if(emuOn){
emuOn = false;
ui->ctrlBtn->setText("Resume");
}
else if(!emuOn){
emuOn = true;
ui->ctrlBtn->setText("Pause");
}
emuMutex.unlock();
}

View File

@@ -8,14 +8,14 @@ extern uint32_t screenWidth;
extern uint32_t screenHeight;
enum{
FRONTEND_ERR_NONE,
FRONTEND_FILE_DOESNT_EXIST,
FRONTEND_FILE_EMPTY_PATH,
FRONTEND_FILE_UNFINISHED,
FRONTEND_FILE_MODIFYED,
FRONTEND_FILE_INVALID_TYPE,
FRONTEND_FILE_PROTECTED,
FRONTEND_OUT_OF_MEMORY
FRONTEND_ERR_NONE,
FRONTEND_FILE_DOESNT_EXIST,
FRONTEND_FILE_EMPTY_PATH,
FRONTEND_FILE_UNFINISHED,
FRONTEND_FILE_MODIFYED,
FRONTEND_FILE_INVALID_TYPE,
FRONTEND_FILE_PROTECTED,
FRONTEND_OUT_OF_MEMORY
};
namespace Ui {
@@ -24,44 +24,44 @@ class MainWindow;
class MainWindow : public QMainWindow
{
Q_OBJECT
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void loadRom();
void selectRom();
void on_install_pressed();
void loadRom();
void selectRom();
void on_install_pressed();
//display
void updateDisplay();
void on_display_destroyed();
//display
void updateDisplay();
void on_display_destroyed();
//palm buttons
void on_power_pressed();
void on_power_released();
void on_calender_pressed();
void on_calender_released();
void on_addressBook_pressed();
void on_addressBook_released();
void on_todo_pressed();
void on_todo_released();
void on_notes_pressed();
void on_notes_released();
//palm buttons
void on_power_pressed();
void on_power_released();
void on_calender_pressed();
void on_calender_released();
void on_addressBook_pressed();
void on_addressBook_released();
void on_todo_pressed();
void on_todo_released();
void on_notes_pressed();
void on_notes_released();
//ui buttons
void on_mainLeft_clicked();
void on_mainRight_clicked();
void on_settingsLeft_clicked();
void on_settingsRight_clicked();
void on_joyLeft_clicked();
void on_joyRight_clicked();
void on_settings_clicked();
//ui buttons
void on_mainLeft_clicked();
void on_mainRight_clicked();
void on_settingsLeft_clicked();
void on_settingsRight_clicked();
void on_joyLeft_clicked();
void on_joyRight_clicked();
void on_settings_clicked();
void on_ctrlBtn_clicked();
void on_ctrlBtn_clicked();
private:
Ui::MainWindow *ui;
Ui::MainWindow *ui;
};

View File

@@ -3,7 +3,7 @@
#include "src/emulator.h"
float rangeSwap(float newRange, float oldRange, float value){
return value / oldRange * newRange;
return value / oldRange * newRange;
}
TouchScreen::TouchScreen(QWidget* parent)
@@ -16,17 +16,17 @@ TouchScreen::~TouchScreen(){
}
void TouchScreen::mousePressEvent(QMouseEvent* ev){
palmInput.touchscreenX = (uint16_t)rangeSwap(screenWidth, this->width(), ev->x());
palmInput.touchscreenY = (uint16_t)rangeSwap(screenHeight, this->height(), ev->y());
palmInput.touchscreenX = (uint16_t)rangeSwap(screenWidth, this->width(), ev->x());
palmInput.touchscreenY = (uint16_t)rangeSwap(screenHeight, this->height(), ev->y());
palmInput.touchscreenTouched = true;
}
void TouchScreen::mouseMoveEvent(QMouseEvent* ev){
palmInput.touchscreenX = (uint16_t)rangeSwap(screenWidth, this->width(), ev->x());
palmInput.touchscreenY = (uint16_t)rangeSwap(screenHeight, this->height(), ev->y());
palmInput.touchscreenX = (uint16_t)rangeSwap(screenWidth, this->width(), ev->x());
palmInput.touchscreenY = (uint16_t)rangeSwap(screenHeight, this->height(), ev->y());
}
void TouchScreen::mouseReleaseEvent(QMouseEvent* ev){
palmInput.touchscreenTouched = false;
palmInput.touchscreenTouched = false;
}
/*

View File

@@ -8,13 +8,13 @@ class TouchScreen : public QLabel
{
Q_OBJECT
public:
explicit TouchScreen(QWidget* parent=0 );
~TouchScreen();
explicit TouchScreen(QWidget* parent=0 );
~TouchScreen();
protected:
void mousePressEvent(QMouseEvent* ev);
void mouseMoveEvent(QMouseEvent* ev);
void mouseReleaseEvent(QMouseEvent* ev);
void mousePressEvent(QMouseEvent* ev);
void mouseMoveEvent(QMouseEvent* ev);
void mouseReleaseEvent(QMouseEvent* ev);
//void touchReleaseEvent(QTouchEvent* ev);
//void touchReleaseEvent(QTouchEvent* ev);
};

View File

@@ -38,6 +38,7 @@ double palmCrystalCycles;//how many cycles before toggling the 32.768 kHz cry
double palmCycleCounter;//can be greater then 0 if too many cycles where run
double palmClockMultiplier;//used by the emulator to overclock the emulated Palm
uint64_t (*emulatorGetSysTime)();
uint64_t* (*emulatorGetSdCardStateChunkList)(uint64_t sessionId, uint64_t stateId);//returns the bps chunkIds for a stateId in the order they need to be applied
void (*emulatorSetSdCardStateChunkList)(uint64_t sessionId, uint64_t stateId, uint64_t* data);//sets the bps chunkIds for a stateId in the order they need to be applied
@@ -52,12 +53,48 @@ static inline bool allSdCardCallbacksPresent(){
}
//debug
#ifdef EMU_OPCODE_LEVEL_DEBUG
#define LOGGED_OPCODES 10
static bool invalidBehaviorAbort;
static char disassemblyBuffer[LOGGED_OPCODES][100];//store the opcode and program counter for the last 10 opcodes
static void invalidBehaviorCheck(){
for(uint32_t i = 0; i < LOGGED_OPCODES - 1; i++)
strcpy(disassemblyBuffer[i], disassemblyBuffer[i + 1]);
uint32_t programCounter = m68k_get_reg(NULL, M68K_REG_PC);
uint16_t instruction = m68k_get_reg(NULL, M68K_REG_IR);
m68k_disassemble(disassemblyBuffer[LOGGED_OPCODES - 1], programCounter, M68K_CPU_TYPE_68020);
strcat(disassemblyBuffer[LOGGED_OPCODES - 1], "\n");
if(bankType[programCounter >> 16] == EMPTY_BANK)
invalidBehaviorAbort = true;
if(!m68k_is_valid_instruction(instruction, M68K_CPU_TYPE_68020) || instruction == 0x0000){
//0x0000 is "ori.b #$0, D0", effectivly NOP but still a valid opcode
//usualy never encountered unless executing empty address space, so it still triggers debug abort
invalidBehaviorAbort = true;
}
if(invalidBehaviorAbort)
m68k_end_timeslice();
}
#endif
void emulatorInit(uint8_t* palmRomDump, uint8_t* palmBootDump, uint32_t specialFeatures){
//cpu
//CPU
m68k_init();
m68k_set_cpu_type(M68K_CPU_TYPE_68020);
m68k_set_reset_instr_callback(emulatorReset);
m68k_set_int_ack_callback(interruptAcknowledge);
#ifdef EMU_OPCODE_LEVEL_DEBUG
for(uint32_t i = 0; i < LOGGED_OPCODES; i++)
strcpy(disassemblyBuffer[i], "Not an opcode.\n");
m68k_set_instr_hook_callback(invalidBehaviorCheck);
#endif
patchMusashiOpcodeHandlerCpu32();
resetHwRegisters();
lowPowerStopActive = false;
@@ -342,3 +379,30 @@ void emulateFrame(){
//debugLog("Ran frame, executed %f cycles.\n", palmCycleCounter + CPU_FREQUENCY / EMU_FPS);
}
bool emulateUntilDebugEventOrFrameEnd(){
#ifdef EMU_OPCODE_LEVEL_DEBUG
invalidBehaviorAbort = false;
refreshButtonState();
while(palmCycleCounter < CPU_FREQUENCY / EMU_FPS){
if(cpuIsOn())
palmCycleCounter += m68k_execute(palmCrystalCycles * palmClockMultiplier) / palmClockMultiplier;//normaly 33mhz / 60fps
else
palmCycleCounter += palmCrystalCycles;
clk32();
if(invalidBehaviorAbort)
break;
}
palmCycleCounter -= CPU_FREQUENCY / EMU_FPS;
if(invalidBehaviorAbort)
for(uint32_t i = 0; i < LOGGED_OPCODES; i++)
debugLog(disassemblyBuffer[i]);
return invalidBehaviorAbort;
#else
emulateFrame();
return false;
#endif
}

View File

@@ -7,6 +7,8 @@
#include <boolean.h>
//to enable opcode level debugging define EMU_OPCODE_LEVEL_DEBUG
#ifdef EMU_DEBUG
#define debugLog(...) printf(__VA_ARGS__)
#else
@@ -151,6 +153,7 @@ void emulatorSaveState(uint8_t* data);
void emulatorLoadState(uint8_t* data);
uint32_t emulatorInstallPrcPdb(uint8_t* data, uint32_t size);
void emulateFrame();
bool emulateUntilDebugEventOrFrameEnd();//false for frame end, true for debug event
#ifdef __cplusplus
}

View File

@@ -45,7 +45,7 @@ void setHwRegister32(unsigned int address, unsigned int value);
//timing
void clk32();//also checks all interrupts
//cpu
//CPU
bool cpuIsOn();
int interruptAcknowledge(int intLevel);
bool registersAreXXFFMapped();

View File

@@ -130,7 +130,11 @@
/* If ON, CPU will call the instruction hook callback before every
* instruction.
*/
#ifdef EMU_OPCODE_LEVEL_DEBUG
#define M68K_INSTRUCTION_HOOK OPT_ON
#else
#define M68K_INSTRUCTION_HOOK OPT_OFF
#endif
#define M68K_INSTRUCTION_CALLBACK() your_instruction_hook_function()