diff --git a/qtBuildSystem/Mu/Mu.pro b/qtBuildSystem/Mu/Mu.pro index 8f546d0..d1fb7bc 100644 --- a/qtBuildSystem/Mu/Mu.pro +++ b/qtBuildSystem/Mu/Mu.pro @@ -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. diff --git a/qtBuildSystem/Mu/main.cpp b/qtBuildSystem/Mu/main.cpp index 26d2721..4222042 100644 --- a/qtBuildSystem/Mu/main.cpp +++ b/qtBuildSystem/Mu/main.cpp @@ -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(); } diff --git a/qtBuildSystem/Mu/mainwindow.cpp b/qtBuildSystem/Mu/mainwindow.cpp index c1e986b..71d57e7 100644 --- a/qtBuildSystem/Mu/mainwindow.cpp +++ b/qtBuildSystem/Mu/mainwindow.cpp @@ -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(); } diff --git a/qtBuildSystem/Mu/mainwindow.h b/qtBuildSystem/Mu/mainwindow.h index 69960ac..7ead064 100644 --- a/qtBuildSystem/Mu/mainwindow.h +++ b/qtBuildSystem/Mu/mainwindow.h @@ -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; }; diff --git a/qtBuildSystem/Mu/touchscreen.cpp b/qtBuildSystem/Mu/touchscreen.cpp index 97d3c5f..8479f8a 100644 --- a/qtBuildSystem/Mu/touchscreen.cpp +++ b/qtBuildSystem/Mu/touchscreen.cpp @@ -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; } /* diff --git a/qtBuildSystem/Mu/touchscreen.h b/qtBuildSystem/Mu/touchscreen.h index d9d69c0..61ed2ba 100644 --- a/qtBuildSystem/Mu/touchscreen.h +++ b/qtBuildSystem/Mu/touchscreen.h @@ -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); }; diff --git a/src/emulator.c b/src/emulator.c index a1bceb5..a7bb72c 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -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 +} diff --git a/src/emulator.h b/src/emulator.h index d12a310..07344eb 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -7,6 +7,8 @@ #include +//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 } diff --git a/src/hardwareRegisters.h b/src/hardwareRegisters.h index e572adf..92ee59e 100644 --- a/src/hardwareRegisters.h +++ b/src/hardwareRegisters.h @@ -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(); diff --git a/src/m68k/m68kconf.h b/src/m68k/m68kconf.h index 7e175ed..22e7ecb 100755 --- a/src/m68k/m68kconf.h +++ b/src/m68k/m68kconf.h @@ -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()