diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f4143fc..d8f8268f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -187,8 +187,8 @@ if(USE_RTMIDI) endif() -set(SC55_SRC - src/mcu.cpp src/mcu.h # main() is here! +set(SC55_BACKEND_SRC + src/mcu.cpp src/mcu.h src/lcd.cpp src/lcd.h src/lcd_font.h src/mcu_interrupt.cpp src/mcu_interrupt.h src/mcu_opcodes.cpp src/mcu_opcodes.h @@ -196,17 +196,26 @@ set(SC55_SRC src/midi.h src/pcm.cpp src/pcm.h src/submcu.cpp src/submcu.h + src/emu.cpp src/emu.h + src/ringbuffer.h + src/math_util.h src/utils/files.cpp src/utils/files.h ) +set(SC55_FRONTEND_SRC + src/main_frontend.cpp # main() is here! +) + if(USE_RTMIDI) - list(APPEND SC55_SRC src/midi_rtmidi.cpp) + list(APPEND SC55_FRONTEND_SRC src/midi_rtmidi.cpp) elseif(WIN32) - list(APPEND SC55_SRC src/midi_win32.cpp) + list(APPEND SC55_FRONTEND_SRC src/midi_win32.cpp) endif() -add_executable(nuked-sc55 ${SC55_SRC} ${UTF8MAIN_SRCS}) +add_library(nuked-sc55-backend ${SC55_BACKEND_SRC}) +add_executable(nuked-sc55 ${SC55_FRONTEND_SRC} ${UTF8MAIN_SRCS}) +target_link_libraries(nuked-sc55 PRIVATE nuked-sc55-backend) set_nopie(nuked-sc55) if(MSVC) @@ -214,9 +223,12 @@ if(MSVC) endif() if(TARGET SDL2::SDL2) + target_link_libraries(nuked-sc55-backend PRIVATE SDL2::SDL2) target_link_libraries(nuked-sc55 PRIVATE SDL2::SDL2) else() string(STRIP ${SDL2_LIBRARIES} SDL2_LIBRARIES) + target_include_directories(nuked-sc55-backend PRIVATE ${SDL2_INCLUDE_DIRS}) + target_link_libraries(nuked-sc55-backend PRIVATE ${SDL2_LIBRARIES}) target_include_directories(nuked-sc55 PRIVATE ${SDL2_INCLUDE_DIRS}) target_link_libraries(nuked-sc55 PRIVATE ${SDL2_LIBRARIES}) endif() diff --git a/src/emu.cpp b/src/emu.cpp new file mode 100644 index 00000000..24c4b422 --- /dev/null +++ b/src/emu.cpp @@ -0,0 +1,500 @@ +/* + * Copyright (C) 2021, 2024 nukeykt + * + * Redistribution and use of this code or any derivative works are permitted + * provided that the following conditions are met: + * + * - Redistributions may not be sold, nor may they be used in a commercial + * product or activity. + * + * - Redistributions that are modified from the original source must include the + * complete source code, including the source code for all components used by a + * binary built from the modified sources. However, as a special exception, the + * source code distributed need not include anything that is normally distributed + * (in either source or binary form) with the major components (compiler, kernel, + * and so on) of the operating system on which the executable runs, unless that + * component itself accompanies the executable. + * + * - Redistributions must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "emu.h" +#include "mcu.h" +#include "submcu.h" +#include "mcu_timer.h" +#include "lcd.h" +#include "pcm.h" +#include "utils/files.h" + +bool EMU_Init(emu_t& emu) +{ + memset(&emu, 0, sizeof(emu_t)); + + emu.mcu = (mcu_t*)malloc(sizeof(mcu_t)); + if (!emu.mcu) + { + EMU_Free(emu); + return false; + } + + emu.sm = (submcu_t*)malloc(sizeof(submcu_t)); + if (!emu.sm) + { + EMU_Free(emu); + return false; + } + + emu.timer = (mcu_timer_t*)malloc(sizeof(mcu_timer_t)); + if (!emu.timer) + { + EMU_Free(emu); + return false; + } + + emu.lcd = (lcd_t*)malloc(sizeof(lcd_t)); + if (!emu.lcd) + { + EMU_Free(emu); + return false; + } + + emu.pcm = (pcm_t*)malloc(sizeof(pcm_t)); + if (!emu.pcm) + { + EMU_Free(emu); + return false; + } + + if (!MCU_Init(*emu.mcu, *emu.sm, *emu.pcm, *emu.timer, *emu.lcd)) + { + EMU_Free(emu); + return false; + } + + SM_Init(*emu.sm, *emu.mcu); + PCM_Init(*emu.pcm, *emu.mcu); + TIMER_Init(*emu.timer, *emu.mcu); + LCD_Init(*emu.lcd, *emu.mcu); + + return true; +} + +void EMU_Free(emu_t& emu) +{ + if (emu.lcd) + { + LCD_UnInit(*emu.lcd); + } + if (emu.pcm) + { + free(emu.pcm); + emu.pcm = nullptr; + } + if (emu.lcd) + { + free(emu.lcd); + emu.lcd = nullptr; + } + if (emu.timer) + { + free(emu.timer); + emu.timer = nullptr; + } + if (emu.sm) + { + free(emu.sm); + emu.sm = nullptr; + } + if (emu.mcu) + { + free(emu.mcu); + emu.mcu = nullptr; + } +} + +void EMU_Reset(emu_t& emu) +{ + MCU_PatchROM(*emu.mcu); + MCU_Reset(*emu.mcu); + SM_Reset(*emu.sm); +} + +void EMU_SetSampleCallback(emu_t& emu, mcu_sample_callback callback, void* userdata) +{ + emu.mcu->callback_userdata = userdata; + emu.mcu->sample_callback = callback; +} + +const char* rs_name[ROM_SET_COUNT] = { + "SC-55mk2", + "SC-55st", + "SC-55mk1", + "CM-300/SCC-1", + "JV-880", + "SCB-55", + "RLP-3237", + "SC-155", + "SC-155mk2" +}; + +const char* roms[ROM_SET_COUNT][5] = +{ + "rom1.bin", + "rom2.bin", + "waverom1.bin", + "waverom2.bin", + "rom_sm.bin", + + "rom1.bin", + "rom2_st.bin", + "waverom1.bin", + "waverom2.bin", + "rom_sm.bin", + + "sc55_rom1.bin", + "sc55_rom2.bin", + "sc55_waverom1.bin", + "sc55_waverom2.bin", + "sc55_waverom3.bin", + + "cm300_rom1.bin", + "cm300_rom2.bin", + "cm300_waverom1.bin", + "cm300_waverom2.bin", + "cm300_waverom3.bin", + + "jv880_rom1.bin", + "jv880_rom2.bin", + "jv880_waverom1.bin", + "jv880_waverom2.bin", + "jv880_waverom_expansion.bin", + + "scb55_rom1.bin", + "scb55_rom2.bin", + "scb55_waverom1.bin", + "scb55_waverom2.bin", + "", + + "rlp3237_rom1.bin", + "rlp3237_rom2.bin", + "rlp3237_waverom1.bin", + "", + "", + + "sc155_rom1.bin", + "sc155_rom2.bin", + "sc155_waverom1.bin", + "sc155_waverom2.bin", + "sc155_waverom3.bin", + + "rom1.bin", + "rom2.bin", + "waverom1.bin", + "waverom2.bin", + "rom_sm.bin", +}; + +void unscramble(uint8_t *src, uint8_t *dst, int len) +{ + for (int i = 0; i < len; i++) + { + int address = i & ~0xfffff; + static const int aa[] = { + 2, 0, 3, 4, 1, 9, 13, 10, 18, 17, 6, 15, 11, 16, 8, 5, 12, 7, 14, 19 + }; + for (int j = 0; j < 20; j++) + { + if (i & (1 << j)) + address |= 1<romset = romset; + emu.mcu->mcu_mk1 = false; + emu.mcu->mcu_cm300 = false; + emu.mcu->mcu_st = false; + emu.mcu->mcu_jv880 = false; + emu.mcu->mcu_scb55 = false; + emu.mcu->mcu_sc155 = false; + switch (romset) + { + case ROM_SET_MK2: + case ROM_SET_SC155MK2: + if (romset == ROM_SET_SC155MK2) + emu.mcu->mcu_sc155 = true; + break; + case ROM_SET_ST: + emu.mcu->mcu_st = true; + break; + case ROM_SET_MK1: + case ROM_SET_SC155: + emu.mcu->mcu_mk1 = true; + emu.mcu->mcu_st = false; + if (romset == ROM_SET_SC155) + emu.mcu->mcu_sc155 = true; + break; + case ROM_SET_CM300: + emu.mcu->mcu_mk1 = true; + emu.mcu->mcu_cm300 = true; + break; + case ROM_SET_JV880: + emu.mcu->mcu_jv880 = true; + emu.mcu->rom2_mask /= 2; // rom is half the size + break; + case ROM_SET_SCB55: + case ROM_SET_RLP3237: + emu.mcu->mcu_scb55 = true; + break; + } + + std::string rpaths[5]; + + bool r_ok = true; + std::string errors_list; + + for(size_t i = 0; i < 5; ++i) + { + if (roms[romset][i][0] == '\0') + { + rpaths[i] = ""; + continue; + } + rpaths[i] = basePath + "/" + roms[romset][i]; + s_rf[i] = Files::utf8_fopen(rpaths[i].c_str(), "rb"); + bool optional = emu.mcu->mcu_jv880 && i == 4; + r_ok &= optional || (s_rf[i] != nullptr); + if(!s_rf[i]) + { + if(!errors_list.empty()) + errors_list.append(", "); + + errors_list.append(rpaths[i]); + } + } + + if (!r_ok) + { + fprintf(stderr, "FATAL ERROR: One of required data ROM files is missing: %s.\n", errors_list.c_str()); + fflush(stderr); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); + return false; + } + + if (fread(emu.mcu->rom1, 1, ROM1_SIZE, s_rf[0]) != ROM1_SIZE) + { + fprintf(stderr, "FATAL ERROR: Failed to read the mcu ROM1.\n"); + fflush(stderr); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); + return false; + } + + size_t rom2_read = fread(emu.mcu->rom2, 1, ROM2_SIZE, s_rf[1]); + + if (rom2_read == ROM2_SIZE || rom2_read == ROM2_SIZE / 2) + { + emu.mcu->rom2_mask = rom2_read - 1; + } + else + { + fprintf(stderr, "FATAL ERROR: Failed to read the mcu ROM2.\n"); + fflush(stderr); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); + return false; + } + + if (emu.mcu->mcu_mk1) + { + if (fread(tempbuf, 1, 0x100000, s_rf[2]) != 0x100000) + { + fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom1.\n"); + fflush(stderr); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); + return false; + } + + unscramble(tempbuf, emu.pcm->waverom1, 0x100000); + + if (fread(tempbuf, 1, 0x100000, s_rf[3]) != 0x100000) + { + fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom2.\n"); + fflush(stderr); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); + return false; + } + + unscramble(tempbuf, emu.pcm->waverom2, 0x100000); + + if (fread(tempbuf, 1, 0x100000, s_rf[4]) != 0x100000) + { + fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom3.\n"); + fflush(stderr); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); + return false; + } + + unscramble(tempbuf, emu.pcm->waverom3, 0x100000); + } + else if (emu.mcu->mcu_jv880) + { + if (fread(tempbuf, 1, 0x200000, s_rf[2]) != 0x200000) + { + fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom1.\n"); + fflush(stderr); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); + return false; + } + + unscramble(tempbuf, emu.pcm->waverom1, 0x200000); + + if (fread(tempbuf, 1, 0x200000, s_rf[3]) != 0x200000) + { + fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom2.\n"); + fflush(stderr); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); + return false; + } + + unscramble(tempbuf, emu.pcm->waverom2, 0x200000); + + if (s_rf[4] && fread(tempbuf, 1, 0x800000, s_rf[4])) + unscramble(tempbuf, emu.pcm->waverom_exp, 0x800000); + else + printf("WaveRom EXP not found, skipping it.\n"); + } + else + { + if (fread(tempbuf, 1, 0x200000, s_rf[2]) != 0x200000) + { + fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom1.\n"); + fflush(stderr); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); + return false; + } + + unscramble(tempbuf, emu.pcm->waverom1, 0x200000); + + if (s_rf[3]) + { + if (fread(tempbuf, 1, 0x100000, s_rf[3]) != 0x100000) + { + fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom2.\n"); + fflush(stderr); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); + return false; + } + + unscramble(tempbuf, emu.mcu->mcu_scb55 ? emu.pcm->waverom3 : emu.pcm->waverom2, 0x100000); + } + + if (s_rf[4] && fread(emu.sm->sm_rom, 1, ROMSM_SIZE, s_rf[4]) != ROMSM_SIZE) + { + fprintf(stderr, "FATAL ERROR: Failed to read the sub mcu ROM.\n"); + fflush(stderr); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); + return false; + } + } + + // Close all files as they no longer needed being open + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); + + return true; +} + +const char* EMU_RomsetName(int romset) +{ + return rs_name[romset]; +} diff --git a/src/emu.h b/src/emu.h new file mode 100644 index 00000000..8ea99146 --- /dev/null +++ b/src/emu.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2021, 2024 nukeykt + * + * Redistribution and use of this code or any derivative works are permitted + * provided that the following conditions are met: + * + * - Redistributions may not be sold, nor may they be used in a commercial + * product or activity. + * + * - Redistributions that are modified from the original source must include the + * complete source code, including the source code for all components used by a + * binary built from the modified sources. However, as a special exception, the + * source code distributed need not include anything that is normally distributed + * (in either source or binary form) with the major components (compiler, kernel, + * and so on) of the operating system on which the executable runs, unless that + * component itself accompanies the executable. + * + * - Redistributions must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#pragma once + +#include "mcu.h" +#include + +struct submcu_t; +struct mcu_timer_t; +struct lcd_t; +struct pcm_t; + +struct emu_t { + mcu_t* mcu; + submcu_t* sm; + mcu_timer_t* timer; + lcd_t* lcd; + pcm_t* pcm; +}; + +bool EMU_Init(emu_t& emu); +void EMU_Free(emu_t& emu); + +// Should be called after loading roms +void EMU_Reset(emu_t& emu); + +void EMU_SetSampleCallback(emu_t& emu, mcu_sample_callback callback, void* userdata); + +int EMU_DetectRomset(const std::string& basePath); +bool EMU_LoadRoms(emu_t& emu, int romset, const std::string& basePath); +const char* EMU_RomsetName(int romset); diff --git a/src/lcd.cpp b/src/lcd.cpp index 5667db73..10332305 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -42,67 +42,58 @@ #include "mcu.h" #include "submcu.h" #include "utils/files.h" +#include "emu.h" - -static uint32_t LCD_DL, LCD_N, LCD_F, LCD_D, LCD_C, LCD_B, LCD_ID, LCD_S; -static uint32_t LCD_DD_RAM, LCD_AC, LCD_CG_RAM; -static uint32_t LCD_RAM_MODE = 0; -static uint8_t LCD_Data[80]; -static uint8_t LCD_CG[64]; - -static uint8_t lcd_enable = 1; -static bool lcd_quit_requested = false; - -void LCD_Enable(uint32_t enable) +void LCD_Enable(lcd_t& lcd, uint32_t enable) { - lcd_enable = enable; + lcd.lcd_enable = enable; } -bool LCD_QuitRequested() +bool LCD_QuitRequested(lcd_t& lcd) { - return lcd_quit_requested; + return lcd.lcd_quit_requested; } -void LCD_Write(uint32_t address, uint8_t data) +void LCD_Write(lcd_t& lcd, uint32_t address, uint8_t data) { if (address == 0) { if ((data & 0xe0) == 0x20) { - LCD_DL = (data & 0x10) != 0; - LCD_N = (data & 0x8) != 0; - LCD_F = (data & 0x4) != 0; + lcd.LCD_DL = (data & 0x10) != 0; + lcd.LCD_N = (data & 0x8) != 0; + lcd.LCD_F = (data & 0x4) != 0; } else if ((data & 0xf8) == 0x8) { - LCD_D = (data & 0x4) != 0; - LCD_C = (data & 0x2) != 0; - LCD_B = (data & 0x1) != 0; + lcd.LCD_D = (data & 0x4) != 0; + lcd.LCD_C = (data & 0x2) != 0; + lcd.LCD_B = (data & 0x1) != 0; } else if ((data & 0xff) == 0x01) { - LCD_DD_RAM = 0; - LCD_ID = 1; - memset(LCD_Data, 0x20, sizeof(LCD_Data)); + lcd.LCD_DD_RAM = 0; + lcd.LCD_ID = 1; + memset(lcd.LCD_Data, 0x20, sizeof(lcd.LCD_Data)); } else if ((data & 0xff) == 0x02) { - LCD_DD_RAM = 0; + lcd.LCD_DD_RAM = 0; } else if ((data & 0xfc) == 0x04) { - LCD_ID = (data & 0x2) != 0; - LCD_S = (data & 0x1) != 0; + lcd.LCD_ID = (data & 0x2) != 0; + lcd.LCD_S = (data & 0x1) != 0; } else if ((data & 0xc0) == 0x40) { - LCD_CG_RAM = (data & 0x3f); - LCD_RAM_MODE = 0; + lcd.LCD_CG_RAM = (data & 0x3f); + lcd.LCD_RAM_MODE = 0; } else if ((data & 0x80) == 0x80) { - LCD_DD_RAM = (data & 0x7f); - LCD_RAM_MODE = 1; + lcd.LCD_DD_RAM = (data & 0x7f); + lcd.LCD_RAM_MODE = 1; } else { @@ -111,48 +102,48 @@ void LCD_Write(uint32_t address, uint8_t data) } else { - if (!LCD_RAM_MODE) + if (!lcd.LCD_RAM_MODE) { - LCD_CG[LCD_CG_RAM] = data & 0x1f; - if (LCD_ID) + lcd.LCD_CG[lcd.LCD_CG_RAM] = data & 0x1f; + if (lcd.LCD_ID) { - LCD_CG_RAM++; + lcd.LCD_CG_RAM++; } else { - LCD_CG_RAM--; + lcd.LCD_CG_RAM--; } - LCD_CG_RAM &= 0x3f; + lcd.LCD_CG_RAM &= 0x3f; } else { - if (LCD_N) + if (lcd.LCD_N) { - if (LCD_DD_RAM & 0x40) + if (lcd.LCD_DD_RAM & 0x40) { - if ((LCD_DD_RAM & 0x3f) < 40) - LCD_Data[(LCD_DD_RAM & 0x3f) + 40] = data; + if ((lcd.LCD_DD_RAM & 0x3f) < 40) + lcd.LCD_Data[(lcd.LCD_DD_RAM & 0x3f) + 40] = data; } else { - if ((LCD_DD_RAM & 0x3f) < 40) - LCD_Data[LCD_DD_RAM & 0x3f] = data; + if ((lcd.LCD_DD_RAM & 0x3f) < 40) + lcd.LCD_Data[lcd.LCD_DD_RAM & 0x3f] = data; } } else { - if (LCD_DD_RAM < 80) - LCD_Data[LCD_DD_RAM] = data; + if (lcd.LCD_DD_RAM < 80) + lcd.LCD_Data[lcd.LCD_DD_RAM] = data; } - if (LCD_ID) + if (lcd.LCD_ID) { - LCD_DD_RAM++; + lcd.LCD_DD_RAM++; } else { - LCD_DD_RAM--; + lcd.LCD_DD_RAM--; } - LCD_DD_RAM &= 0x7f; + lcd.LCD_DD_RAM &= 0x7f; } } //printf("%i %.2x ", address, data); @@ -162,21 +153,6 @@ void LCD_Write(uint32_t address, uint8_t data) // printf("\n"); } -int lcd_width = 741; -int lcd_height = 268; -static const int lcd_width_max = 1024; -static const int lcd_height_max = 1024; -static SDL_Window *window; -static SDL_Renderer *renderer; -static SDL_Texture *texture; - -static std::string m_back_path = "back.data"; - -static uint32_t lcd_buffer[lcd_height_max][lcd_width_max]; -static uint32_t lcd_background[268][741]; - -static uint32_t lcd_init = 0; - const int button_map_sc55[][2] = { SDL_SCANCODE_Q, MCU_BUTTON_POWER, @@ -221,63 +197,86 @@ const int button_map_jv880[][2] = }; -void LCD_SetBackPath(const std::string &path) -{ - m_back_path = path; -} - -void LCD_Init(void) +void LCD_LoadBack(lcd_t& lcd, const std::string& path) { FILE *raw; - if(lcd_init) + raw = Files::utf8_fopen(path.c_str(), "rb"); + if (!raw) return; - lcd_quit_requested = false; + fread(lcd.lcd_background, 1, sizeof(lcd.lcd_background), raw); + fclose(raw); +} - std::string title = "Nuked SC-55: "; +void LCD_Init(lcd_t& lcd, mcu_t& mcu) +{ + memset(&lcd, 0, sizeof(lcd_t)); + lcd.mcu = &mcu; +} - title += rs_name[romset]; +bool LCD_CreateWindow(lcd_t& lcd) +{ + if (lcd.mcu->romset == ROM_SET_JV880) + { + lcd.lcd_width = 820; + lcd.lcd_height = 100; + } + else + { + lcd.lcd_width = 741; + lcd.lcd_height = 268; + } - window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, lcd_width, lcd_height, SDL_WINDOW_SHOWN); - if (!window) - return; + std::string title = "Nuked SC-55: "; - renderer = SDL_CreateRenderer(window, -1, 0); - if (!renderer) - return; + title += EMU_RomsetName(lcd.mcu->romset); - texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_BGR888, SDL_TEXTUREACCESS_STREAMING, lcd_width, lcd_height); + lcd.window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, lcd.lcd_width, lcd.lcd_height, SDL_WINDOW_SHOWN); + if (!lcd.window) + return false; - if (!texture) - return; + lcd.renderer = SDL_CreateRenderer(lcd.window, -1, 0); + if (!lcd.renderer) + return false; - raw = Files::utf8_fopen(m_back_path.c_str(), "rb"); - if (!raw) - return; + lcd.texture = SDL_CreateTexture(lcd.renderer, SDL_PIXELFORMAT_BGR888, SDL_TEXTUREACCESS_STREAMING, lcd.lcd_width, lcd.lcd_height); - fread(lcd_background, 1, sizeof(lcd_background), raw); - fclose(raw); + if (!lcd.texture) + return false; - lcd_init = 1; + return true; } -void LCD_UnInit(void) +void LCD_UnInit(lcd_t& lcd) { - if(!lcd_init) - return; + if (lcd.texture) + { + SDL_DestroyTexture(lcd.texture); + lcd.texture = nullptr; + } + if (lcd.renderer) + { + SDL_DestroyRenderer(lcd.renderer); + lcd.renderer = nullptr; + } + if (lcd.window) + { + SDL_DestroyWindow(lcd.window); + lcd.window = nullptr; + } } uint32_t lcd_col1 = 0x000000; uint32_t lcd_col2 = 0x0050c8; -void LCD_FontRenderStandard(int32_t x, int32_t y, uint8_t ch, bool overlay = false) +void LCD_FontRenderStandard(lcd_t& lcd, int32_t x, int32_t y, uint8_t ch, bool overlay = false) { uint8_t* f; if (ch >= 16) f = &lcd_font[ch - 16][0]; else - f = &LCD_CG[(ch & 7) * 8]; + f = &lcd.LCD_CG[(ch & 7) * 8]; for (int i = 0; i < 7; i++) { for (int j = 0; j < 5; j++) @@ -298,22 +297,22 @@ void LCD_FontRenderStandard(int32_t x, int32_t y, uint8_t ch, bool overlay = fal for (int jj = 0; jj < 5; jj++) { if (overlay) - lcd_buffer[xx+ii][yy+jj] &= col; + lcd.lcd_buffer[xx+ii][yy+jj] &= col; else - lcd_buffer[xx+ii][yy+jj] = col; + lcd.lcd_buffer[xx+ii][yy+jj] = col; } } } } } -void LCD_FontRenderLevel(int32_t x, int32_t y, uint8_t ch, uint8_t width = 5) +void LCD_FontRenderLevel(lcd_t& lcd, int32_t x, int32_t y, uint8_t ch, uint8_t width = 5) { uint8_t* f; if (ch >= 16) f = &lcd_font[ch - 16][0]; else - f = &LCD_CG[(ch & 7) * 8]; + f = &lcd.LCD_CG[(ch & 7) * 8]; for (int i = 0; i < 8; i++) { for (int j = 0; j < width; j++) @@ -333,7 +332,7 @@ void LCD_FontRenderLevel(int32_t x, int32_t y, uint8_t ch, uint8_t width = 5) { for (int jj = 0; jj < 24; jj++) { - lcd_buffer[xx+ii][yy+jj] = col; + lcd.lcd_buffer[xx+ii][yy+jj] = col; } } } @@ -378,13 +377,13 @@ static const int LR_xy[2][2] = { }; -void LCD_FontRenderLR(uint8_t ch) +void LCD_FontRenderLR(lcd_t& lcd, uint8_t ch) { uint8_t* f; if (ch >= 16) f = &lcd_font[ch - 16][0]; else - f = &LCD_CG[(ch & 7) * 8]; + f = &lcd.LCD_CG[(ch & 7) * 8]; int col; if (f[0] & 1) { @@ -401,152 +400,175 @@ void LCD_FontRenderLR(uint8_t ch) for (int j = 0; j < 11; j++) { if (LR[f][i][j]) - lcd_buffer[i+LR_xy[f][0]][j+LR_xy[f][1]] = col; + lcd.lcd_buffer[i+LR_xy[f][0]][j+LR_xy[f][1]] = col; } } } } -void LCD_Update(void) +void LCD_Update(lcd_t& lcd) { - if (!lcd_init) - return; - - if (!mcu_cm300 && !mcu_st && !mcu_scb55) + if (!lcd.mcu->mcu_cm300 && !lcd.mcu->mcu_st && !lcd.mcu->mcu_scb55) { - MCU_WorkThread_Lock(); + MCU_WorkThread_Lock(*lcd.mcu); - if (!lcd_enable && !mcu_jv880) + if (!lcd.lcd_enable && !lcd.mcu->mcu_jv880) { - memset(lcd_buffer, 0, sizeof(lcd_buffer)); + memset(lcd.lcd_buffer, 0, sizeof(lcd.lcd_buffer)); } else { - if (mcu_jv880) + if (lcd.mcu->mcu_jv880) { - for (size_t i = 0; i < lcd_height; i++) { - for (size_t j = 0; j < lcd_width; j++) { - lcd_buffer[i][j] = 0xFF0F6FFF; + for (size_t i = 0; i < lcd.lcd_height; i++) { + for (size_t j = 0; j < lcd.lcd_width; j++) { + lcd.lcd_buffer[i][j] = 0xFF0F6FFF; } } } else { - for (size_t i = 0; i < lcd_height; i++) { - for (size_t j = 0; j < lcd_width; j++) { - lcd_buffer[i][j] = lcd_background[i][j]; + for (size_t i = 0; i < lcd.lcd_height; i++) { + for (size_t j = 0; j < lcd.lcd_width; j++) { + lcd.lcd_buffer[i][j] = lcd.lcd_background[i][j]; } } } - if (mcu_jv880) + if (lcd.mcu->mcu_jv880) { for (int i = 0; i < 2; i++) { for (int j = 0; j < 24; j++) { - uint8_t ch = LCD_Data[i * 40 + j]; - LCD_FontRenderStandard(4 + i * 50, 4 + j * 34, ch); + uint8_t ch = lcd.LCD_Data[i * 40 + j]; + LCD_FontRenderStandard(lcd, 4 + i * 50, 4 + j * 34, ch); } } // cursor - int j = LCD_DD_RAM % 0x40; - int i = LCD_DD_RAM / 0x40; - if (i < 2 && j < 24 && LCD_C) - LCD_FontRenderStandard(4 + i * 50, 4 + j * 34, '_', true); + int j = lcd.LCD_DD_RAM % 0x40; + int i = lcd.LCD_DD_RAM / 0x40; + if (i < 2 && j < 24 && lcd.LCD_C) + LCD_FontRenderStandard(lcd, 4 + i * 50, 4 + j * 34, '_', true); } else { for (int i = 0; i < 3; i++) { - uint8_t ch = LCD_Data[0 + i]; - LCD_FontRenderStandard(11, 34 + i * 35, ch); + uint8_t ch = lcd.LCD_Data[0 + i]; + LCD_FontRenderStandard(lcd, 11, 34 + i * 35, ch); } for (int i = 0; i < 16; i++) { - uint8_t ch = LCD_Data[3 + i]; - LCD_FontRenderStandard(11, 153 + i * 35, ch); + uint8_t ch = lcd.LCD_Data[3 + i]; + LCD_FontRenderStandard(lcd, 11, 153 + i * 35, ch); } for (int i = 0; i < 3; i++) { - uint8_t ch = LCD_Data[40 + i]; - LCD_FontRenderStandard(75, 34 + i * 35, ch); + uint8_t ch = lcd.LCD_Data[40 + i]; + LCD_FontRenderStandard(lcd, 75, 34 + i * 35, ch); } for (int i = 0; i < 3; i++) { - uint8_t ch = LCD_Data[43 + i]; - LCD_FontRenderStandard(75, 153 + i * 35, ch); + uint8_t ch = lcd.LCD_Data[43 + i]; + LCD_FontRenderStandard(lcd, 75, 153 + i * 35, ch); } for (int i = 0; i < 3; i++) { - uint8_t ch = LCD_Data[49 + i]; - LCD_FontRenderStandard(139, 34 + i * 35, ch); + uint8_t ch = lcd.LCD_Data[49 + i]; + LCD_FontRenderStandard(lcd, 139, 34 + i * 35, ch); } for (int i = 0; i < 3; i++) { - uint8_t ch = LCD_Data[46 + i]; - LCD_FontRenderStandard(139, 153 + i * 35, ch); + uint8_t ch = lcd.LCD_Data[46 + i]; + LCD_FontRenderStandard(lcd, 139, 153 + i * 35, ch); } for (int i = 0; i < 3; i++) { - uint8_t ch = LCD_Data[52 + i]; - LCD_FontRenderStandard(203, 34 + i * 35, ch); + uint8_t ch = lcd.LCD_Data[52 + i]; + LCD_FontRenderStandard(lcd, 203, 34 + i * 35, ch); } for (int i = 0; i < 3; i++) { - uint8_t ch = LCD_Data[55 + i]; - LCD_FontRenderStandard(203, 153 + i * 35, ch); + uint8_t ch = lcd.LCD_Data[55 + i]; + LCD_FontRenderStandard(lcd, 203, 153 + i * 35, ch); } - LCD_FontRenderLR(LCD_Data[58]); + LCD_FontRenderLR(lcd, lcd.LCD_Data[58]); for (int i = 0; i < 2; i++) { for (int j = 0; j < 4; j++) { - uint8_t ch = LCD_Data[20 + j + i * 40]; - LCD_FontRenderLevel(71 + i * 88, 293 + j * 130, ch, j == 3 ? 1 : 5); + uint8_t ch = lcd.LCD_Data[20 + j + i * 40]; + LCD_FontRenderLevel(lcd, 71 + i * 88, 293 + j * 130, ch, j == 3 ? 1 : 5); } } } } - MCU_WorkThread_Unlock(); + MCU_WorkThread_Unlock(*lcd.mcu); - SDL_UpdateTexture(texture, NULL, lcd_buffer, lcd_width_max * 4); - SDL_RenderCopy(renderer, texture, NULL, NULL); - SDL_RenderPresent(renderer); + SDL_UpdateTexture(lcd.texture, NULL, lcd.lcd_buffer, lcd_width_max * 4); + SDL_RenderCopy(lcd.renderer, lcd.texture, NULL, NULL); + SDL_RenderPresent(lcd.renderer); } +} - SDL_Event sdl_event; - while (SDL_PollEvent(&sdl_event)) +void LCD_HandleEvent(lcd_t& lcd, const SDL_Event& sdl_event) +{ + switch (sdl_event.type) { - if (sdl_event.type == SDL_KEYDOWN) - { - if (sdl_event.key.keysym.scancode == SDL_SCANCODE_COMMA) - MCU_EncoderTrigger(0); - if (sdl_event.key.keysym.scancode == SDL_SCANCODE_PERIOD) - MCU_EncoderTrigger(1); - } + case SDL_KEYDOWN: + case SDL_KEYUP: + if (sdl_event.key.windowID != SDL_GetWindowID(lcd.window)) + { + return; + } + break; + case SDL_WINDOWEVENT: + if (sdl_event.window.windowID != SDL_GetWindowID(lcd.window)) + { + return; + } + break; + default: + break; + } - switch (sdl_event.type) - { - case SDL_QUIT: - lcd_quit_requested = true; - break; + if (sdl_event.type == SDL_KEYDOWN) + { + if (sdl_event.key.keysym.scancode == SDL_SCANCODE_COMMA) + MCU_EncoderTrigger(*lcd.mcu, 0); + if (sdl_event.key.keysym.scancode == SDL_SCANCODE_PERIOD) + MCU_EncoderTrigger(*lcd.mcu, 1); + } + + switch (sdl_event.type) + { + case SDL_QUIT: + lcd.lcd_quit_requested = true; + break; - case SDL_KEYDOWN: - case SDL_KEYUP: + case SDL_WINDOWEVENT: + if (sdl_event.window.event == SDL_WINDOWEVENT_CLOSE) + { + lcd.lcd_quit_requested = true; + } + break; + + case SDL_KEYDOWN: + case SDL_KEYUP: { if (sdl_event.key.repeat) - continue; - + break; + int mask = 0; - uint32_t button_pressed = (uint32_t)SDL_AtomicGet(&mcu_button_pressed); + uint32_t button_pressed = (uint32_t)SDL_AtomicGet(&lcd.mcu->mcu_button_pressed); - auto button_map = mcu_jv880 ? button_map_jv880 : button_map_sc55; - auto button_size = (mcu_jv880 ? sizeof(button_map_jv880) : sizeof(button_map_sc55)) / sizeof(button_map_sc55[0]); + auto button_map = lcd.mcu->mcu_jv880 ? button_map_jv880 : button_map_sc55; + auto button_size = (lcd.mcu->mcu_jv880 ? sizeof(button_map_jv880) : sizeof(button_map_sc55)) / sizeof(button_map_sc55[0]); for (size_t i = 0; i < button_size; i++) { if (button_map[i][0] == sdl_event.key.keysym.scancode) @@ -558,7 +580,7 @@ void LCD_Update(void) else button_pressed &= ~mask; - SDL_AtomicSet(&mcu_button_pressed, (int)button_pressed); + SDL_AtomicSet(&lcd.mcu->mcu_button_pressed, (int)button_pressed); #if 0 if (sdl_event.key.keysym.scancode >= SDL_SCANCODE_1 && sdl_event.key.keysym.scancode < SDL_SCANCODE_0) @@ -657,7 +679,5 @@ void LCD_Update(void) #endif break; } - } } } - diff --git a/src/lcd.h b/src/lcd.h index a9982a87..c3bd7682 100644 --- a/src/lcd.h +++ b/src/lcd.h @@ -36,14 +36,46 @@ #include #include -extern int lcd_width; -extern int lcd_height; - -void LCD_SetBackPath(const std::string &path); -void LCD_Init(void); -void LCD_UnInit(void); -void LCD_Write(uint32_t address, uint8_t data); -void LCD_Enable(uint32_t enable); -bool LCD_QuitRequested(); +struct mcu_t; + +struct SDL_Window; +struct SDL_Renderer; +struct SDL_Texture; + +static const int lcd_width_max = 1024; +static const int lcd_height_max = 1024; + +struct lcd_t { + mcu_t* mcu; + + int lcd_width; + int lcd_height; + + uint32_t LCD_DL, LCD_N, LCD_F, LCD_D, LCD_C, LCD_B, LCD_ID, LCD_S; + uint32_t LCD_DD_RAM, LCD_AC, LCD_CG_RAM; + uint32_t LCD_RAM_MODE; + uint8_t LCD_Data[80]; + uint8_t LCD_CG[64]; + + uint8_t lcd_enable; + bool lcd_quit_requested; + + uint32_t lcd_buffer[lcd_height_max][lcd_width_max]; + uint32_t lcd_background[268][741]; + + SDL_Window *window; + SDL_Renderer *renderer; + SDL_Texture *texture; +}; + + +void LCD_LoadBack(lcd_t& lcd, const std::string& path); +void LCD_Init(lcd_t& lcd, mcu_t& mcu); +bool LCD_CreateWindow(lcd_t& lcd); +void LCD_UnInit(lcd_t& lcd); +void LCD_Write(lcd_t& lcd, uint32_t address, uint8_t data); +void LCD_Enable(lcd_t& lcd, uint32_t enable); +bool LCD_QuitRequested(lcd_t& lcd); void LCD_Sync(void); -void LCD_Update(void); +void LCD_Update(lcd_t& lcd); +void LCD_HandleEvent(lcd_t& lcd, const SDL_Event& sdl_event); diff --git a/src/main_frontend.cpp b/src/main_frontend.cpp new file mode 100644 index 00000000..59c560ce --- /dev/null +++ b/src/main_frontend.cpp @@ -0,0 +1,627 @@ +/* + * Copyright (C) 2021, 2024 nukeykt + * + * Redistribution and use of this code or any derivative works are permitted + * provided that the following conditions are met: + * + * - Redistributions may not be sold, nor may they be used in a commercial + * product or activity. + * + * - Redistributions that are modified from the original source must include the + * complete source code, including the source code for all components used by a + * binary built from the modified sources. However, as a special exception, the + * source code distributed need not include anything that is normally distributed + * (in either source or binary form) with the major components (compiler, kernel, + * and so on) of the operating system on which the executable runs, unless that + * component itself accompanies the executable. + * + * - Redistributions must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#define SDL_MAIN_HANDLED +#include "SDL.h" +#include "mcu.h" +#include "mcu_opcodes.h" +#include "mcu_interrupt.h" +#include "mcu_timer.h" +#include "pcm.h" +#include "lcd.h" +#include "submcu.h" +#include "midi.h" +#include "utf8main.h" +#include "utils/files.h" +#include "emu.h" +#include "ringbuffer.h" +#include "math_util.h" + +#if __linux__ +#include +#include +#endif + +struct fe_emu_instance_t { + emu_t emu; + ringbuffer_t sample_buffer; + SDL_Thread* thread; + bool running; +}; + +const size_t FE_MAX_INSTANCES = 16; + +struct frontend_t { + fe_emu_instance_t instances[FE_MAX_INSTANCES]; + size_t instances_in_use = 0; + + int audio_buffer_size = 0; + int audio_page_size = 0; + + SDL_AudioDeviceID sdl_audio = 0; +}; + +bool FE_AllocateInstance(frontend_t& container, fe_emu_instance_t** result) +{ + if (container.instances_in_use == FE_MAX_INSTANCES) + { + return false; + } + + fe_emu_instance_t& fe = container.instances[container.instances_in_use]; + memset(&fe, 0, sizeof(fe_emu_instance_t)); + ++container.instances_in_use; + + if (result) + { + *result = &fe; + } + + return true; +} + +void FE_SendMIDI(frontend_t& fe, size_t n, uint8_t* first, uint8_t* last) +{ + while (first != last) + { + MCU_PostUART(*fe.instances[n].emu.mcu, *first); + ++first; + } +} + +void FE_BroadcastMIDI(frontend_t& fe, uint8_t* first, uint8_t* last) +{ + for (size_t i = 0; i < fe.instances_in_use; ++i) + { + FE_SendMIDI(fe, i, first, last); + } +} + +void FE_RouteMIDI(frontend_t& fe, uint8_t* first, uint8_t* last) +{ + if (*first < 0x80) + { + printf("FE_RouteMIDI received data byte %02x\n", *first); + return; + } + + const bool is_sysex = *first == 0xF0; + const uint8_t channel = *first & 0x0F; + + if (is_sysex) + { + FE_BroadcastMIDI(fe, first, last); + } + else + { + FE_SendMIDI(fe, channel % fe.instances_in_use, first, last); + } +} + +void FE_ReceiveSample(void* userdata, int *sample) +{ + fe_emu_instance_t& fe = *(fe_emu_instance_t*)userdata; + sample[0] >>= 15; + sample[1] >>= 15; + + audio_frame_t frame; + frame.left = (int16_t)clamp(sample[0], INT16_MIN, INT16_MAX); + frame.right = (int16_t)clamp(sample[1], INT16_MIN, INT16_MAX); + + RB_Write(fe.sample_buffer, frame); +} + +void FE_AudioCallback(void* userdata, Uint8* stream, int len) +{ + frontend_t& frontend = *(frontend_t*)userdata; + + const size_t num_frames = len / sizeof(audio_frame_t); + memset(stream, 0, len); + + size_t renderable_count = num_frames; + for (size_t i = 0; i < frontend.instances_in_use; ++i) + { + renderable_count = min( + renderable_count, + RB_ReadableFrameCount(frontend.instances[i].sample_buffer) + ); + } + + for (size_t i = 0; i < frontend.instances_in_use; ++i) + { + RB_ReadMix(frontend.instances[i].sample_buffer, (audio_frame_t*)stream, renderable_count); + } +} + +static const char* audio_format_to_str(int format) +{ + switch(format) + { + case AUDIO_S8: + return "S8"; + case AUDIO_U8: + return "U8"; + case AUDIO_S16MSB: + return "S16MSB"; + case AUDIO_S16LSB: + return "S16LSB"; + case AUDIO_U16MSB: + return "U16MSB"; + case AUDIO_U16LSB: + return "U16LSB"; + case AUDIO_S32MSB: + return "S32MSB"; + case AUDIO_S32LSB: + return "S32LSB"; + case AUDIO_F32MSB: + return "F32MSB"; + case AUDIO_F32LSB: + return "F32LSB"; + } + return "UNK"; +} + +bool FE_OpenAudio(frontend_t& fe, int deviceIndex, int pageSize, int pageNum) +{ + SDL_AudioSpec spec = {}; + SDL_AudioSpec spec_actual = {}; + + fe.audio_page_size = (pageSize/2)*2; // must be even + fe.audio_buffer_size = fe.audio_page_size*pageNum; + + // TODO: we just assume the first instance has the correct mcu type for + // all instances, which is PROBABLY correct but maybe we want to do some + // crazy stuff like running different mcu types concurrently in the future? + const mcu_t& mcu = *fe.instances[0].emu.mcu; + + spec.format = AUDIO_S16SYS; + spec.freq = (mcu.mcu_mk1 || mcu.mcu_jv880) ? 64000 : 66207; + spec.channels = 2; + spec.callback = FE_AudioCallback; + spec.userdata = &fe; + spec.samples = fe.audio_page_size / 4; + + int num = SDL_GetNumAudioDevices(0); + if (num == 0) + { + printf("No audio output device found.\n"); + return false; + } + + if (deviceIndex < -1 || deviceIndex >= num) + { + printf("Out of range audio device index is requested. Default audio output device is selected.\n"); + deviceIndex = -1; + } + + const char* audioDevicename = deviceIndex == -1 ? "Default device" : SDL_GetAudioDeviceName(deviceIndex, 0); + + fe.sdl_audio = SDL_OpenAudioDevice(deviceIndex == -1 ? NULL : audioDevicename, 0, &spec, &spec_actual, 0); + if (!fe.sdl_audio) + { + return false; + } + + printf("Audio device: %s\n", audioDevicename); + + printf("Audio Requested: F=%s, C=%d, R=%d, B=%d\n", + audio_format_to_str(spec.format), + spec.channels, + spec.freq, + spec.samples); + + printf("Audio Actual: F=%s, C=%d, R=%d, B=%d\n", + audio_format_to_str(spec_actual.format), + spec_actual.channels, + spec_actual.freq, + spec_actual.samples); + fflush(stdout); + + SDL_PauseAudioDevice(fe.sdl_audio, 0); + + return true; +} + +enum class ResetType { + NONE, + GS_RESET, + GM_RESET, +}; + +void MIDI_Reset(mcu_t& mcu, ResetType resetType) +{ + const unsigned char gmReset[] = { 0xF0, 0x7E, 0x7F, 0x09, 0x01, 0xF7 }; + const unsigned char gsReset[] = { 0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7F, 0x00, 0x41, 0xF7 }; + + if (resetType == ResetType::GS_RESET) + { + for (size_t i = 0; i < sizeof(gsReset); i++) + { + MCU_PostUART(mcu, gsReset[i]); + } + } + else if (resetType == ResetType::GM_RESET) + { + for (size_t i = 0; i < sizeof(gmReset); i++) + { + MCU_PostUART(mcu, gmReset[i]); + } + } + +} + +int SDLCALL FE_RunInstance(void* userdata) +{ + fe_emu_instance_t& instance = *(fe_emu_instance_t*)userdata; + + MCU_WorkThread_Lock(*instance.emu.mcu); + while (instance.running) + { + RB_SetOversamplingEnabled(instance.sample_buffer, instance.emu.pcm->config_reg_3c & 0x40); + if (RB_IsFull(instance.sample_buffer)) + { + MCU_WorkThread_Unlock(*instance.emu.mcu); + while (RB_IsFull(instance.sample_buffer)) + { + SDL_Delay(1); + } + MCU_WorkThread_Lock(*instance.emu.mcu); + } + + MCU_Step(*instance.emu.mcu); + } + MCU_WorkThread_Unlock(*instance.emu.mcu); + + return 0; +} + +void FE_Run(frontend_t& fe) +{ + bool working = true; + + for (size_t i = 0; i < fe.instances_in_use; ++i) + { + fe.instances[i].running = true; + fe.instances[i].thread = SDL_CreateThread(FE_RunInstance, "work thread", &fe.instances[i]); + } + + while (working) + { + for (size_t i = 0; i < fe.instances_in_use; ++i) + { + if (LCD_QuitRequested(*fe.instances[i].emu.lcd)) + working = false; + + LCD_Update(*fe.instances[i].emu.lcd); + } + + SDL_Event sdl_event; + while (SDL_PollEvent(&sdl_event)) + { + for (size_t i = 0; i < fe.instances_in_use; ++i) + { + LCD_HandleEvent(*fe.instances[i].emu.lcd, sdl_event); + } + } + + SDL_Delay(15); + } + + for (size_t i = 0; i < fe.instances_in_use; ++i) + { + fe.instances[i].running = false; + SDL_WaitThread(fe.instances[i].thread, 0); + } +} + +bool FE_Init() +{ + if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) + { + fprintf(stderr, "FATAL ERROR: Failed to initialize the SDL2: %s.\n", SDL_GetError()); + fflush(stderr); + return false; + } + + return true; +} + +bool FE_CreateInstance(frontend_t& container, const std::string& basePath, int romset) +{ + fe_emu_instance_t* fe = nullptr; + + if (!FE_AllocateInstance(container, &fe)) + { + fprintf(stderr, "ERROR: Failed to allocate instance.\n"); + return false; + } + + if (!EMU_Init(fe->emu)) + { + fprintf(stderr, "ERROR: Failed to init emulator.\n"); + return false; + } + + EMU_SetSampleCallback(fe->emu, FE_ReceiveSample, fe); + + LCD_LoadBack(*fe->emu.lcd, basePath + "/back.data"); + + if (!EMU_LoadRoms(fe->emu, romset, basePath)) + { + fprintf(stderr, "ERROR: Failed to load roms.\n"); + return false; + } + EMU_Reset(fe->emu); + + if (!LCD_CreateWindow(*fe->emu.lcd)) + { + fprintf(stderr, "ERROR: Failed to create window.\n"); + return false; + } + + return true; +} + +void FE_DestroyInstance(fe_emu_instance_t& fe) +{ + EMU_Free(fe.emu); + RB_Free(fe.sample_buffer); + fe.thread = nullptr; + fe.running = false; +} + +void FE_Quit(frontend_t& container) +{ + // Important to close audio devices first since this will stop the SDL + // audio thread. Otherwise we might get a UAF destroying ringbuffers + // while they're still in use. + SDL_CloseAudioDevice(container.sdl_audio); + for (size_t i = 0; i < container.instances_in_use; ++i) + { + FE_DestroyInstance(container.instances[i]); + } + MIDI_Quit(); + SDL_Quit(); +} + +int main(int argc, char *argv[]) +{ + (void)argc; + std::string basePath; + + int port = 0; + int audioDeviceIndex = -1; + int pageSize = 512; + int pageNum = 32; + bool autodetect = true; + ResetType resetType = ResetType::NONE; + int instance_count = 1; + + int romset = ROM_SET_MK2; + + frontend_t frontend; + + { + for (int i = 1; i < argc; i++) + { + if (!strncmp(argv[i], "-p:", 3)) + { + port = atoi(argv[i] + 3); + } + else if (!strncmp(argv[i], "-a:", 3)) + { + audioDeviceIndex = atoi(argv[i] + 3); + } + else if (!strncmp(argv[i], "-ab:", 4)) + { + char* pColon = argv[i] + 3; + + if (pColon[1] != 0) + { + pageSize = atoi(++pColon); + pColon = strchr(pColon, ':'); + if (pColon && pColon[1] != 0) + { + pageNum = atoi(++pColon); + } + } + + // reset both if either is invalid + if (pageSize <= 0 || pageNum <= 0) + { + pageSize = 512; + pageNum = 32; + } + } + else if (!strncmp(argv[i], "-instances:", 11)) + { + instance_count = atoi(argv[i] + 11); + instance_count = clamp(instance_count, 1, FE_MAX_INSTANCES); + } + else if (!strcmp(argv[i], "-mk2")) + { + romset = ROM_SET_MK2; + autodetect = false; + } + else if (!strcmp(argv[i], "-st")) + { + romset = ROM_SET_ST; + autodetect = false; + } + else if (!strcmp(argv[i], "-mk1")) + { + romset = ROM_SET_MK1; + autodetect = false; + } + else if (!strcmp(argv[i], "-cm300")) + { + romset = ROM_SET_CM300; + autodetect = false; + } + else if (!strcmp(argv[i], "-jv880")) + { + romset = ROM_SET_JV880; + autodetect = false; + } + else if (!strcmp(argv[i], "-scb55")) + { + romset = ROM_SET_SCB55; + autodetect = false; + } + else if (!strcmp(argv[i], "-rlp3237")) + { + romset = ROM_SET_RLP3237; + autodetect = false; + } + else if (!strcmp(argv[i], "-gs")) + { + resetType = ResetType::GS_RESET; + } + else if (!strcmp(argv[i], "-gm")) + { + resetType = ResetType::GM_RESET; + } + else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "-help") || !strcmp(argv[i], "--help")) + { + // TODO: Might want to try to find a way to print out the executable's actual name (without any full paths). + printf("Usage: nuked-sc55 [options]\n"); + printf("Options:\n"); + printf(" -h, -help, --help Display this information.\n"); + printf("\n"); + printf(" -p: Set MIDI port.\n"); + printf(" -a: Set Audio Device index.\n"); + printf(" -ab::[page_count] Set Audio Buffer size.\n"); + printf(" -instances: Set number of emulator instances.\n"); + printf("\n"); + printf(" -mk2 Use SC-55mk2 ROM set.\n"); + printf(" -st Use SC-55st ROM set.\n"); + printf(" -mk1 Use SC-55mk1 ROM set.\n"); + printf(" -cm300 Use CM-300/SCC-1 ROM set.\n"); + printf(" -jv880 Use JV-880 ROM set.\n"); + printf(" -scb55 Use SCB-55 ROM set.\n"); + printf(" -rlp3237 Use RLP-3237 ROM set.\n"); + printf("\n"); + printf(" -gs Reset system in GS mode.\n"); + printf(" -gm Reset system in GM mode.\n"); + return 0; + } + else if (!strcmp(argv[i], "-sc155")) + { + romset = ROM_SET_SC155; + autodetect = false; + } + else if (!strcmp(argv[i], "-sc155mk2")) + { + romset = ROM_SET_SC155MK2; + autodetect = false; + } + } + } + +#if __linux__ + char self_path[PATH_MAX]; + memset(&self_path[0], 0, PATH_MAX); + + if(readlink("/proc/self/exe", self_path, PATH_MAX) == -1) + basePath = Files::real_dirname(argv[0]); + else + basePath = Files::dirname(self_path); +#else + basePath = Files::real_dirname(argv[0]); +#endif + + printf("Base path is: %s\n", argv[0]); + + if(Files::dirExists(basePath + "/../share/nuked-sc55")) + basePath += "/../share/nuked-sc55"; + + if (autodetect) + { + romset = EMU_DetectRomset(basePath); + printf("ROM set autodetect: %s\n", EMU_RomsetName(romset)); + } + + if (!FE_Init()) + { + fprintf(stderr, "FATAL ERROR: Failed to initialize frontend\n"); + return 1; + } + + for (int i = 0; i < instance_count; ++i) + { + if (!FE_CreateInstance(frontend, basePath, romset)) + { + fprintf(stderr, "FATAL ERROR: Failed to create instance %d\n", i); + return 1; + } + } + + if (!FE_OpenAudio(frontend, audioDeviceIndex, pageSize, pageNum)) + { + fprintf(stderr, "FATAL ERROR: Failed to open the audio stream.\n"); + fflush(stderr); + return 1; + } + + for (size_t i = 0; i < frontend.instances_in_use; ++i) + { + fe_emu_instance_t& fe = frontend.instances[i]; + if (!RB_Init(fe.sample_buffer, frontend.audio_buffer_size / 2)) + { + fprintf(stderr, "FATAL ERROR: Failed to allocate ringbuffer %lld\n", i); + return 1; + } + } + + if (!MIDI_Init(frontend, port)) + { + fprintf(stderr, "ERROR: Failed to initialize the MIDI Input.\nWARNING: Continuing without MIDI Input...\n"); + fflush(stderr); + } + + if (resetType != ResetType::NONE) + { + for (size_t i = 0; i < frontend.instances_in_use; ++i) + { + MIDI_Reset(*frontend.instances[i].emu.mcu, resetType); + } + } + + FE_Run(frontend); + + FE_Quit(frontend); + + return 0; +} diff --git a/src/math_util.h b/src/math_util.h new file mode 100644 index 00000000..5e1847c4 --- /dev/null +++ b/src/math_util.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2021, 2024 nukeykt + * + * Redistribution and use of this code or any derivative works are permitted + * provided that the following conditions are met: + * + * - Redistributions may not be sold, nor may they be used in a commercial + * product or activity. + * + * - Redistributions that are modified from the original source must include the + * complete source code, including the source code for all components used by a + * binary built from the modified sources. However, as a special exception, the + * source code distributed need not include anything that is normally distributed + * (in either source or binary form) with the major components (compiler, kernel, + * and so on) of the operating system on which the executable runs, unless that + * component itself accompanies the executable. + * + * - Redistributions must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#pragma once + +#include + +template +inline T min(T a, T b) +{ + return a < b ? a : b; +} + +template +inline T clamp(T value, T min, T max) +{ + if (value < min) return min; + if (value > max) return max; + return value; +} + +inline int16_t saturating_add(int16_t a, int16_t b) +{ + int32_t result = (int32_t)a + (int32_t)b; + return (int16_t)clamp(result, INT16_MIN, INT16_MAX); +} diff --git a/src/mcu.cpp b/src/mcu.cpp index e4105594..e27d1d71 100644 --- a/src/mcu.cpp +++ b/src/mcu.cpp @@ -51,122 +51,11 @@ #include #endif -const char* rs_name[ROM_SET_COUNT] = { - "SC-55mk2", - "SC-55st", - "SC-55mk1", - "CM-300/SCC-1", - "JV-880", - "SCB-55", - "RLP-3237", - "SC-155", - "SC-155mk2" -}; - -const char* roms[ROM_SET_COUNT][5] = -{ - "rom1.bin", - "rom2.bin", - "waverom1.bin", - "waverom2.bin", - "rom_sm.bin", - - "rom1.bin", - "rom2_st.bin", - "waverom1.bin", - "waverom2.bin", - "rom_sm.bin", - - "sc55_rom1.bin", - "sc55_rom2.bin", - "sc55_waverom1.bin", - "sc55_waverom2.bin", - "sc55_waverom3.bin", - - "cm300_rom1.bin", - "cm300_rom2.bin", - "cm300_waverom1.bin", - "cm300_waverom2.bin", - "cm300_waverom3.bin", - - "jv880_rom1.bin", - "jv880_rom2.bin", - "jv880_waverom1.bin", - "jv880_waverom2.bin", - "jv880_waverom_expansion.bin", - - "scb55_rom1.bin", - "scb55_rom2.bin", - "scb55_waverom1.bin", - "scb55_waverom2.bin", - "", - - "rlp3237_rom1.bin", - "rlp3237_rom2.bin", - "rlp3237_waverom1.bin", - "", - "", - - "sc155_rom1.bin", - "sc155_rom2.bin", - "sc155_waverom1.bin", - "sc155_waverom2.bin", - "sc155_waverom3.bin", - - "rom1.bin", - "rom2.bin", - "waverom1.bin", - "waverom2.bin", - "rom_sm.bin", -}; - -int romset = ROM_SET_MK2; - -static const int ROM1_SIZE = 0x8000; -static const int ROM2_SIZE = 0x80000; -static const int RAM_SIZE = 0x400; -static const int SRAM_SIZE = 0x8000; -static const int NVRAM_SIZE = 0x8000; // JV880 only -static const int CARDRAM_SIZE = 0x8000; // JV880 only -static const int ROMSM_SIZE = 0x1000; - - -static int audio_buffer_size; -static int audio_page_size; -static short *sample_buffer; - -static int sample_read_ptr; -static int sample_write_ptr; - -static SDL_AudioDeviceID sdl_audio; - -void MCU_ErrorTrap(void) +void MCU_ErrorTrap(mcu_t& mcu) { printf("%.2x %.4x\n", mcu.cp, mcu.pc); } -int mcu_mk1 = 0; // 0 - SC-55mkII, SC-55ST. 1 - SC-55, CM-300/SCC-1 -int mcu_cm300 = 0; // 0 - SC-55, 1 - CM-300/SCC-1 -int mcu_st = 0; // 0 - SC-55mk2, 1 - SC-55ST -int mcu_jv880 = 0; // 0 - SC-55, 1 - JV880 -int mcu_scb55 = 0; // 0 - sub mcu (e.g SC-55mk2), 1 - no sub mcu (e.g SCB-55) -int mcu_sc155 = 0; // 0 - SC-55(MK2), 1 - SC-155(MK2) - -static int ga_int[8]; -static int ga_int_enable = 0; -static int ga_int_trigger = 0; -static int ga_lcd_counter = 0; - - -uint8_t dev_register[0x80]; - -static uint16_t ad_val[4]; -static uint8_t ad_nibble = 0x00; -static uint8_t sw_pos = 3; -static uint8_t io_sd = 0x00; - -SDL_atomic_t mcu_button_pressed = { 0 }; - uint8_t RCU_Read(void) { return 0; @@ -182,7 +71,7 @@ enum { ANALOG_LEVEL_BATTERY = 0x2a0, }; -uint16_t MCU_SC155Sliders(uint32_t index) +uint16_t MCU_SC155Sliders(mcu_t& mcu, uint32_t index) { // 0 - 1/9 // 1 - 2/10 @@ -196,11 +85,11 @@ uint16_t MCU_SC155Sliders(uint32_t index) return 0x0; } -uint16_t MCU_AnalogReadPin(uint32_t pin) +uint16_t MCU_AnalogReadPin(mcu_t& mcu, uint32_t pin) { - if (mcu_cm300) + if (mcu.mcu_cm300) return 0; - if (mcu_jv880) + if (mcu.mcu_jv880) { if (pin == 1) return ANALOG_LEVEL_BATTERY; @@ -215,16 +104,16 @@ uint16_t MCU_AnalogReadPin(uint32_t pin) else return ANALOG_LEVEL_RCU_LOW; } - if (mcu_mk1) + if (mcu.mcu_mk1) { - if (mcu_sc155 && (dev_register[DEV_P9DR] & 1) != 0) + if (mcu.mcu_sc155 && (mcu.dev_register[DEV_P9DR] & 1) != 0) { - return MCU_SC155Sliders(pin); + return MCU_SC155Sliders(mcu, pin); } if (pin == 7) { - if (mcu_sc155 && (dev_register[DEV_P9DR] & 2) != 0) - return MCU_SC155Sliders(8); + if (mcu.mcu_sc155 && (mcu.dev_register[DEV_P9DR] & 2) != 0) + return MCU_SC155Sliders(mcu, 8); else return ANALOG_LEVEL_BATTERY; } @@ -233,24 +122,24 @@ uint16_t MCU_AnalogReadPin(uint32_t pin) } else { - if (mcu_sc155 && (io_sd & 16) != 0) + if (mcu.mcu_sc155 && (mcu.io_sd & 16) != 0) { - return MCU_SC155Sliders(pin); + return MCU_SC155Sliders(mcu, pin); } if (pin == 7) { - if (mcu_mk1) + if (mcu.mcu_mk1) return ANALOG_LEVEL_BATTERY; - switch ((io_sd >> 2) & 3) + switch ((mcu.io_sd >> 2) & 3) { case 0: // Battery voltage return ANALOG_LEVEL_BATTERY; case 1: // NC - if (mcu_sc155) - return MCU_SC155Sliders(8); + if (mcu.mcu_sc155) + return MCU_SC155Sliders(mcu, 8); return 0; case 2: // SW - switch (sw_pos) + switch (mcu.sw_pos) { case 0: default: @@ -271,39 +160,25 @@ uint16_t MCU_AnalogReadPin(uint32_t pin) } } -void MCU_AnalogSample(int channel) +void MCU_AnalogSample(mcu_t& mcu, int channel) { - int value = MCU_AnalogReadPin(channel); + int value = MCU_AnalogReadPin(mcu, channel); int dest = (channel << 1) & 6; - dev_register[DEV_ADDRAH + dest] = value >> 2; - dev_register[DEV_ADDRAL + dest] = (value << 6) & 0xc0; + mcu.dev_register[DEV_ADDRAH + dest] = value >> 2; + mcu.dev_register[DEV_ADDRAL + dest] = (value << 6) & 0xc0; } -int adf_rd = 0; - -uint64_t analog_end_time; - -int ssr_rd = 0; - -uint32_t uart_write_ptr; -uint32_t uart_read_ptr; -uint8_t uart_buffer[uart_buffer_size]; - -static uint8_t uart_rx_byte; -static uint64_t uart_rx_delay; -static uint64_t uart_tx_delay; - -void MCU_DeviceWrite(uint32_t address, uint8_t data) +void MCU_DeviceWrite(mcu_t& mcu, uint32_t address, uint8_t data) { address &= 0x7f; if (address >= 0x10 && address < 0x40) { - TIMER_Write(address, data); + TIMER_Write(*mcu.timer, address, data); return; } if (address >= 0x50 && address < 0x55) { - TIMER2_Write(address, data); + TIMER2_Write(*mcu.timer, address, data); return; } switch (address) @@ -372,38 +247,38 @@ void MCU_DeviceWrite(uint32_t address, uint8_t data) break; case DEV_ADCSR: { - dev_register[address] &= ~0x7f; - dev_register[address] |= data & 0x7f; - if ((data & 0x80) == 0 && adf_rd) + mcu.dev_register[address] &= ~0x7f; + mcu.dev_register[address] |= data & 0x7f; + if ((data & 0x80) == 0 && mcu.adf_rd) { - dev_register[address] &= ~0x80; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_ANALOG, 0); + mcu.dev_register[address] &= ~0x80; + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_ANALOG, 0); } if ((data & 0x40) == 0) - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_ANALOG, 0); + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_ANALOG, 0); return; } case DEV_SSR: { - if ((data & 0x80) == 0 && (ssr_rd & 0x80) != 0) + if ((data & 0x80) == 0 && (mcu.ssr_rd & 0x80) != 0) { - dev_register[address] &= ~0x80; - uart_tx_delay = mcu.cycles + 3000; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_UART_TX, 0); + mcu.dev_register[address] &= ~0x80; + mcu.uart_tx_delay = mcu.cycles + 3000; + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_UART_TX, 0); } - if ((data & 0x40) == 0 && (ssr_rd & 0x40) != 0) + if ((data & 0x40) == 0 && (mcu.ssr_rd & 0x40) != 0) { - uart_rx_delay = mcu.cycles + 3000; - dev_register[address] &= ~0x40; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_UART_RX, 0); + mcu.uart_rx_delay = mcu.cycles + 3000; + mcu.dev_register[address] &= ~0x40; + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_UART_RX, 0); } - if ((data & 0x20) == 0 && (ssr_rd & 0x20) != 0) + if ((data & 0x20) == 0 && (mcu.ssr_rd & 0x20) != 0) { - dev_register[address] &= ~0x20; + mcu.dev_register[address] &= ~0x20; } - if ((data & 0x10) == 0 && (ssr_rd & 0x10) != 0) + if ((data & 0x10) == 0 && (mcu.ssr_rd & 0x10) != 0) { - dev_register[address] &= ~0x10; + mcu.dev_register[address] &= ~0x10; } break; } @@ -411,19 +286,19 @@ void MCU_DeviceWrite(uint32_t address, uint8_t data) address += 0; break; } - dev_register[address] = data; + mcu.dev_register[address] = data; } -uint8_t MCU_DeviceRead(uint32_t address) +uint8_t MCU_DeviceRead(mcu_t& mcu, uint32_t address) { address &= 0x7f; if (address >= 0x10 && address < 0x40) { - return TIMER_Read(address); + return TIMER_Read(*mcu.timer, address); } if (address >= 0x50 && address < 0x55) { - return TIMER_Read2(address); + return TIMER_Read2(*mcu.timer, address); } switch (address) { @@ -435,29 +310,29 @@ uint8_t MCU_DeviceRead(uint32_t address) case DEV_ADDRCL: case DEV_ADDRDH: case DEV_ADDRDL: - return dev_register[address]; + return mcu.dev_register[address]; case DEV_ADCSR: - adf_rd = (dev_register[address] & 0x80) != 0; - return dev_register[address]; + mcu.adf_rd = (mcu.dev_register[address] & 0x80) != 0; + return mcu.dev_register[address]; case DEV_SSR: - ssr_rd = dev_register[address]; - return dev_register[address]; + mcu.ssr_rd = mcu.dev_register[address]; + return mcu.dev_register[address]; case DEV_RDR: - return uart_rx_byte; + return mcu.uart_rx_byte; case 0x00: return 0xff; case DEV_P7DR: { - if (!mcu_jv880) return 0xff; + if (!mcu.mcu_jv880) return 0xff; uint8_t data = 0xff; - uint32_t button_pressed = (uint32_t)SDL_AtomicGet(&mcu_button_pressed); + uint32_t button_pressed = (uint32_t)SDL_AtomicGet(&mcu.mcu_button_pressed); - if (io_sd == 0b11111011) + if (mcu.io_sd == 0b11111011) data &= ((button_pressed >> 0) & 0b11111) ^ 0xFF; - if (io_sd == 0b11110111) + if (mcu.io_sd == 0b11110111) data &= ((button_pressed >> 5) & 0b11111) ^ 0xFF; - if (io_sd == 0b11101111) + if (mcu.io_sd == 0b11101111) data &= ((button_pressed >> 10) & 0b1111) ^ 0xFF; data |= 0b10000000; @@ -466,19 +341,19 @@ uint8_t MCU_DeviceRead(uint32_t address) case DEV_P9DR: { int cfg = 0; - if (!mcu_mk1) - cfg = mcu_sc155 ? 0 : 2; // bit 1: 0 - SC-155mk2 (???), 1 - SC-55mk2 + if (!mcu.mcu_mk1) + cfg = mcu.mcu_sc155 ? 0 : 2; // bit 1: 0 - SC-155mk2 (???), 1 - SC-55mk2 - int dir = dev_register[DEV_P9DDR]; + int dir = mcu.dev_register[DEV_P9DDR]; int val = cfg & (dir ^ 0xff); - val |= dev_register[DEV_P9DR] & dir; + val |= mcu.dev_register[DEV_P9DR] & dir; return val; } case DEV_SCR: case DEV_TDR: case DEV_SMR: - return dev_register[address]; + return mcu.dev_register[address]; case DEV_IPRC: case DEV_IPRD: case DEV_DTEC: @@ -491,67 +366,56 @@ uint8_t MCU_DeviceRead(uint32_t address) case DEV_FRT3_TCSR: case DEV_FRT3_OCRAH: case DEV_FRT3_OCRAL: - return dev_register[address]; + return mcu.dev_register[address]; } - return dev_register[address]; + return mcu.dev_register[address]; } -void MCU_DeviceReset(void) +void MCU_DeviceReset(mcu_t& mcu) { - // dev_register[0x00] = 0x03; - // dev_register[0x7c] = 0x87; - dev_register[DEV_RAME] = 0x80; - dev_register[DEV_SSR] = 0x80; + // mcu.dev_register[0x00] = 0x03; + // mcu.dev_register[0x7c] = 0x87; + mcu.dev_register[DEV_RAME] = 0x80; + mcu.dev_register[DEV_SSR] = 0x80; } -void MCU_UpdateAnalog(uint64_t cycles) +void MCU_UpdateAnalog(mcu_t& mcu, uint64_t cycles) { - int ctrl = dev_register[DEV_ADCSR]; + int ctrl = mcu.dev_register[DEV_ADCSR]; int isscan = (ctrl & 16) != 0; if (ctrl & 0x20) { - if (analog_end_time == 0) - analog_end_time = cycles + 200; - else if (analog_end_time < cycles) + if (mcu.analog_end_time == 0) + mcu.analog_end_time = cycles + 200; + else if (mcu.analog_end_time < cycles) { if (isscan) { int base = ctrl & 4; for (int i = 0; i <= (ctrl & 3); i++) - MCU_AnalogSample(base + i); - analog_end_time = cycles + 200; + MCU_AnalogSample(mcu, base + i); + mcu.analog_end_time = cycles + 200; } else { - MCU_AnalogSample(ctrl & 7); - dev_register[DEV_ADCSR] &= ~0x20; - analog_end_time = 0; + MCU_AnalogSample(mcu, ctrl & 7); + mcu.dev_register[DEV_ADCSR] &= ~0x20; + mcu.analog_end_time = 0; } - dev_register[DEV_ADCSR] |= 0x80; + mcu.dev_register[DEV_ADCSR] |= 0x80; if (ctrl & 0x40) - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_ANALOG, 1); + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_ANALOG, 1); } } else - analog_end_time = 0; + mcu.analog_end_time = 0; } -mcu_t mcu; - -uint8_t rom1[ROM1_SIZE]; -uint8_t rom2[ROM2_SIZE]; -uint8_t ram[RAM_SIZE]; -uint8_t sram[SRAM_SIZE]; -uint8_t nvram[NVRAM_SIZE]; -uint8_t cardram[CARDRAM_SIZE]; - -int rom2_mask = ROM2_SIZE - 1; - -uint8_t MCU_Read(uint32_t address) +uint8_t MCU_Read(mcu_t& mcu, uint32_t address) { uint32_t address_rom = address & 0x3ffff; - if (address & 0x80000 && !mcu_jv880) + if (address & 0x80000 && !mcu.mcu_jv880) address_rom |= 0x40000; uint8_t page = (address >> 16) & 0xf; address &= 0xffff; @@ -560,36 +424,36 @@ uint8_t MCU_Read(uint32_t address) { case 0: if (!(address & 0x8000)) - ret = rom1[address & 0x7fff]; + ret = mcu.rom1[address & 0x7fff]; else { - if (!mcu_mk1) + if (!mcu.mcu_mk1) { - uint16_t base = mcu_jv880 ? 0xf000 : 0xe000; + uint16_t base = mcu.mcu_jv880 ? 0xf000 : 0xe000; if (address >= base && address < (base | 0x400)) { - ret = PCM_Read(address & 0x3f); + ret = PCM_Read(*mcu.pcm, address & 0x3f); } - else if (!mcu_scb55 && address >= 0xec00 && address < 0xf000) + else if (!mcu.mcu_scb55 && address >= 0xec00 && address < 0xf000) { - ret = SM_SysRead(address & 0xff); + ret = SM_SysRead(*mcu.sm, address & 0xff); } else if (address >= 0xff80) { - ret = MCU_DeviceRead(address & 0x7f); + ret = MCU_DeviceRead(mcu, address & 0x7f); } else if (address >= 0xfb80 && address < 0xff80 - && (dev_register[DEV_RAME] & 0x80) != 0) - ret = ram[(address - 0xfb80) & 0x3ff]; + && (mcu.dev_register[DEV_RAME] & 0x80) != 0) + ret = mcu.ram[(address - 0xfb80) & 0x3ff]; else if (address >= 0x8000 && address < 0xe000) { - ret = sram[address & 0x7fff]; + ret = mcu.sram[address & 0x7fff]; } else if (address == (base | 0x402)) { - ret = ga_int_trigger; - ga_int_trigger = 0; - MCU_Interrupt_SetRequest(mcu_jv880 ? INTERRUPT_SOURCE_IRQ0 : INTERRUPT_SOURCE_IRQ1, 0); + ret = mcu.ga_int_trigger; + mcu.ga_int_trigger = 0; + MCU_Interrupt_SetRequest(mcu, mcu.mcu_jv880 ? INTERRUPT_SOURCE_IRQ0 : INTERRUPT_SOURCE_IRQ1, 0); } else { @@ -604,48 +468,48 @@ uint8_t MCU_Read(uint32_t address) { if (address >= 0xe000 && address < 0xe040) { - ret = PCM_Read(address & 0x3f); + ret = PCM_Read(*mcu.pcm, address & 0x3f); } else if (address >= 0xff80) { - ret = MCU_DeviceRead(address & 0x7f); + ret = MCU_DeviceRead(mcu, address & 0x7f); } else if (address >= 0xfb80 && address < 0xff80 - && (dev_register[DEV_RAME] & 0x80) != 0) + && (mcu.dev_register[DEV_RAME] & 0x80) != 0) { - ret = ram[(address - 0xfb80) & 0x3ff]; + ret = mcu.ram[(address - 0xfb80) & 0x3ff]; } else if (address >= 0x8000 && address < 0xe000) { - ret = sram[address & 0x7fff]; + ret = mcu.sram[address & 0x7fff]; } else if (address >= 0xf000 && address < 0xf100) { - io_sd = address & 0xff; + mcu.io_sd = address & 0xff; - if (mcu_cm300) + if (mcu.mcu_cm300) return 0xff; - LCD_Enable((io_sd & 8) != 0); + LCD_Enable(*mcu.lcd, (mcu.io_sd & 8) != 0); uint8_t data = 0xff; - uint32_t button_pressed = (uint32_t)SDL_AtomicGet(&mcu_button_pressed); + uint32_t button_pressed = (uint32_t)SDL_AtomicGet(&mcu.mcu_button_pressed); - if ((io_sd & 1) == 0) + if ((mcu.io_sd & 1) == 0) data &= ((button_pressed >> 0) & 255) ^ 255; - if ((io_sd & 2) == 0) + if ((mcu.io_sd & 2) == 0) data &= ((button_pressed >> 8) & 255) ^ 255; - if ((io_sd & 4) == 0) + if ((mcu.io_sd & 4) == 0) data &= ((button_pressed >> 16) & 255) ^ 255; - if ((io_sd & 8) == 0) + if ((mcu.io_sd & 8) == 0) data &= ((button_pressed >> 24) & 255) ^ 255; return data; } else if (address == 0xf106) { - ret = ga_int_trigger; - ga_int_trigger = 0; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_IRQ1, 0); + ret = mcu.ga_int_trigger; + mcu.ga_int_trigger = 0; + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_IRQ1, 0); } else { @@ -673,53 +537,53 @@ uint8_t MCU_Read(uint32_t address) break; #endif case 1: - ret = rom2[address_rom & rom2_mask]; + ret = mcu.rom2[address_rom & mcu.rom2_mask]; break; case 2: - ret = rom2[address_rom & rom2_mask]; + ret = mcu.rom2[address_rom & mcu.rom2_mask]; break; case 3: - ret = rom2[address_rom & rom2_mask]; + ret = mcu.rom2[address_rom & mcu.rom2_mask]; break; case 4: - ret = rom2[address_rom & rom2_mask]; + ret = mcu.rom2[address_rom & mcu.rom2_mask]; break; case 8: - if (!mcu_jv880) - ret = rom2[address_rom & rom2_mask]; + if (!mcu.mcu_jv880) + ret = mcu.rom2[address_rom & mcu.rom2_mask]; else ret = 0xff; break; case 9: - if (!mcu_jv880) - ret = rom2[address_rom & rom2_mask]; + if (!mcu.mcu_jv880) + ret = mcu.rom2[address_rom & mcu.rom2_mask]; else ret = 0xff; break; case 14: case 15: - if (!mcu_jv880) - ret = rom2[address_rom & rom2_mask]; + if (!mcu.mcu_jv880) + ret = mcu.rom2[address_rom & mcu.rom2_mask]; else - ret = cardram[address & 0x7fff]; // FIXME + ret = mcu.cardram[address & 0x7fff]; // FIXME break; case 10: case 11: - if (!mcu_mk1) - ret = sram[address & 0x7fff]; // FIXME + if (!mcu.mcu_mk1) + ret = mcu.sram[address & 0x7fff]; // FIXME else ret = 0xff; break; case 12: case 13: - if (mcu_jv880) - ret = nvram[address & 0x7fff]; // FIXME + if (mcu.mcu_jv880) + ret = mcu.nvram[address & 0x7fff]; // FIXME else ret = 0xff; break; case 5: - if (mcu_mk1) - ret = sram[address & 0x7fff]; // FIXME + if (mcu.mcu_mk1) + ret = mcu.sram[address & 0x7fff]; // FIXME else ret = 0xff; break; @@ -730,27 +594,27 @@ uint8_t MCU_Read(uint32_t address) return ret; } -uint16_t MCU_Read16(uint32_t address) +uint16_t MCU_Read16(mcu_t& mcu, uint32_t address) { address &= ~1; uint8_t b0, b1; - b0 = MCU_Read(address); - b1 = MCU_Read(address+1); + b0 = MCU_Read(mcu, address); + b1 = MCU_Read(mcu, address+1); return (b0 << 8) + b1; } -uint32_t MCU_Read32(uint32_t address) +uint32_t MCU_Read32(mcu_t& mcu, uint32_t address) { address &= ~3; uint8_t b0, b1, b2, b3; - b0 = MCU_Read(address); - b1 = MCU_Read(address+1); - b2 = MCU_Read(address+2); - b3 = MCU_Read(address+3); + b0 = MCU_Read(mcu, address); + b1 = MCU_Read(mcu, address+1); + b2 = MCU_Read(mcu, address+2); + b3 = MCU_Read(mcu, address+3); return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; } -void MCU_Write(uint32_t address, uint8_t value) +void MCU_Write(mcu_t& mcu, uint32_t address, uint8_t value) { uint8_t page = (address >> 16) & 0xf; address &= 0xffff; @@ -758,20 +622,20 @@ void MCU_Write(uint32_t address, uint8_t value) { if (address & 0x8000) { - if (!mcu_mk1) + if (!mcu.mcu_mk1) { - uint16_t base = mcu_jv880 ? 0xf000 : 0xe000; + uint16_t base = mcu.mcu_jv880 ? 0xf000 : 0xe000; if (address >= (base | 0x400) && address < (base | 0x800)) { if (address == (base | 0x404) || address == (base | 0x405)) - LCD_Write(address & 1, value); + LCD_Write(*mcu.lcd, address & 1, value); else if (address == (base | 0x401)) { - io_sd = value; - LCD_Enable((value & 1) == 0); + mcu.io_sd = value; + LCD_Enable(*mcu.lcd, (value & 1) == 0); } else if (address == (base | 0x402)) - ga_int_enable = (value << 1); + mcu.ga_int_enable = (value << 1); else printf("Unknown write %x %x\n", address, value); // @@ -787,24 +651,24 @@ void MCU_Write(uint32_t address, uint8_t value) } else if (address >= (base | 0x000) && address < (base | 0x400)) { - PCM_Write(address & 0x3f, value); + PCM_Write(*mcu.pcm, address & 0x3f, value); } - else if (!mcu_scb55 && address >= 0xec00 && address < 0xf000) + else if (!mcu.mcu_scb55 && address >= 0xec00 && address < 0xf000) { - SM_SysWrite(address & 0xff, value); + SM_SysWrite(*mcu.sm, address & 0xff, value); } else if (address >= 0xff80) { - MCU_DeviceWrite(address & 0x7f, value); + MCU_DeviceWrite(mcu, address & 0x7f, value); } else if (address >= 0xfb80 && address < 0xff80 - && (dev_register[DEV_RAME] & 0x80) != 0) + && (mcu.dev_register[DEV_RAME] & 0x80) != 0) { - ram[(address - 0xfb80) & 0x3ff] = value; + mcu.ram[(address - 0xfb80) & 0x3ff] = value; } else if (address >= 0x8000 && address < 0xe000) { - sram[address & 0x7fff] = value; + mcu.sram[address & 0x7fff] = value; } else { @@ -815,39 +679,39 @@ void MCU_Write(uint32_t address, uint8_t value) { if (address >= 0xe000 && address < 0xe040) { - PCM_Write(address & 0x3f, value); + PCM_Write(*mcu.pcm, address & 0x3f, value); } else if (address >= 0xff80) { - MCU_DeviceWrite(address & 0x7f, value); + MCU_DeviceWrite(mcu, address & 0x7f, value); } else if (address >= 0xfb80 && address < 0xff80 - && (dev_register[DEV_RAME] & 0x80) != 0) + && (mcu.dev_register[DEV_RAME] & 0x80) != 0) { - ram[(address - 0xfb80) & 0x3ff] = value; + mcu.ram[(address - 0xfb80) & 0x3ff] = value; } else if (address >= 0x8000 && address < 0xe000) { - sram[address & 0x7fff] = value; + mcu.sram[address & 0x7fff] = value; } else if (address >= 0xf000 && address < 0xf100) { - io_sd = address & 0xff; - LCD_Enable((io_sd & 8) != 0); + mcu.io_sd = address & 0xff; + LCD_Enable(*mcu.lcd, (mcu.io_sd & 8) != 0); } else if (address == 0xf105) { - LCD_Write(0, value); - ga_lcd_counter = 500; + LCD_Write(*mcu.lcd, 0, value); + mcu.ga_lcd_counter = 500; } else if (address == 0xf104) { - LCD_Write(1, value); - ga_lcd_counter = 500; + LCD_Write(*mcu.lcd, 1, value); + mcu.ga_lcd_counter = 500; } else if (address == 0xf107) { - io_sd = value; + mcu.io_sd = value; } else { @@ -860,21 +724,21 @@ void MCU_Write(uint32_t address, uint8_t value) printf("Unknown write %x %x\n", address, value); } } - else if (page == 5 && mcu_mk1) + else if (page == 5 && mcu.mcu_mk1) { - sram[address & 0x7fff] = value; // FIXME + mcu.sram[address & 0x7fff] = value; // FIXME } - else if (page == 10 && !mcu_mk1) + else if (page == 10 && !mcu.mcu_mk1) { - sram[address & 0x7fff] = value; // FIXME + mcu.sram[address & 0x7fff] = value; // FIXME } - else if (page == 12 && mcu_jv880) + else if (page == 12 && mcu.mcu_jv880) { - nvram[address & 0x7fff] = value; // FIXME + mcu.nvram[address & 0x7fff] = value; // FIXME } - else if (page == 14 && mcu_jv880) + else if (page == 14 && mcu.mcu_jv880) { - cardram[address & 0x7fff] = value; // FIXME + mcu.cardram[address & 0x7fff] = value; // FIXME } else { @@ -882,31 +746,56 @@ void MCU_Write(uint32_t address, uint8_t value) } } -void MCU_Write16(uint32_t address, uint16_t value) +void MCU_Write16(mcu_t& mcu, uint32_t address, uint16_t value) { address &= ~1; - MCU_Write(address, value >> 8); - MCU_Write(address + 1, value & 0xff); + MCU_Write(mcu, address, value >> 8); + MCU_Write(mcu, address + 1, value & 0xff); } -void MCU_ReadInstruction(void) +void MCU_ReadInstruction(mcu_t& mcu) { - uint8_t operand = MCU_ReadCodeAdvance(); + uint8_t operand = MCU_ReadCodeAdvance(mcu); - MCU_Operand_Table[operand](operand); + MCU_Operand_Table[operand](mcu, operand); if (mcu.sr & STATUS_T) { - MCU_Interrupt_Exception(EXCEPTION_SOURCE_TRACE); + MCU_Interrupt_Exception(mcu, EXCEPTION_SOURCE_TRACE); } } -void MCU_Init(void) +void MCU_DefaultSampleCallback(void* userdata, int* sample) +{ + (void)userdata; + (void)sample; +} + +bool MCU_Init(mcu_t& mcu, submcu_t& sm, pcm_t& pcm, mcu_timer_t& timer, lcd_t& lcd) { memset(&mcu, 0, sizeof(mcu_t)); + mcu.sw_pos = 3; + mcu.sm = &sm; + mcu.pcm = &pcm; + mcu.timer = &timer; + mcu.lcd = &lcd; + mcu.romset = ROM_SET_MK2; + mcu.rom2_mask = ROM2_SIZE - 1; + mcu.sample_callback = MCU_DefaultSampleCallback; + mcu.work_thread_lock = SDL_CreateMutex(); + if (!mcu.work_thread_lock) + { + return false; + } + return true; +} + +void MCU_Deinit(mcu_t& mcu) +{ + SDL_DestroyMutex(mcu.work_thread_lock); } -void MCU_Reset(void) +void MCU_Reset(mcu_t& mcu) { mcu.r[0] = 0; mcu.r[1] = 0; @@ -927,828 +816,179 @@ void MCU_Reset(void) mcu.tp = 0; mcu.br = 0; - uint32_t reset_address = MCU_GetVectorAddress(VECTOR_RESET); + uint32_t reset_address = MCU_GetVectorAddress(mcu, VECTOR_RESET); mcu.cp = (reset_address >> 16) & 0xff; mcu.pc = reset_address & 0xffff; mcu.exception_pending = -1; - MCU_DeviceReset(); + MCU_DeviceReset(mcu); - if (mcu_mk1) + if (mcu.mcu_mk1) { - ga_int_enable = 255; + mcu.ga_int_enable = 255; } } -void MCU_PostUART(uint8_t data) +void MCU_PostUART(mcu_t& mcu, uint8_t data) { - uart_buffer[uart_write_ptr] = data; - uart_write_ptr = (uart_write_ptr + 1) % uart_buffer_size; + mcu.uart_buffer[mcu.uart_write_ptr] = data; + mcu.uart_write_ptr = (mcu.uart_write_ptr + 1) % uart_buffer_size; } -void MCU_UpdateUART_RX(void) +void MCU_UpdateUART_RX(mcu_t& mcu) { - if ((dev_register[DEV_SCR] & 16) == 0) // RX disabled + if ((mcu.dev_register[DEV_SCR] & 16) == 0) // RX disabled return; - if (uart_write_ptr == uart_read_ptr) // no byte + if (mcu.uart_write_ptr == mcu.uart_read_ptr) // no byte return; - if (dev_register[DEV_SSR] & 0x40) + if (mcu.dev_register[DEV_SSR] & 0x40) return; - if (mcu.cycles < uart_rx_delay) + if (mcu.cycles < mcu.uart_rx_delay) return; - uart_rx_byte = uart_buffer[uart_read_ptr]; - uart_read_ptr = (uart_read_ptr + 1) % uart_buffer_size; - dev_register[DEV_SSR] |= 0x40; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_UART_RX, (dev_register[DEV_SCR] & 0x40) != 0); + mcu.uart_rx_byte = mcu.uart_buffer[mcu.uart_read_ptr]; + mcu.uart_read_ptr = (mcu.uart_read_ptr + 1) % uart_buffer_size; + mcu.dev_register[DEV_SSR] |= 0x40; + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_UART_RX, (mcu.dev_register[DEV_SCR] & 0x40) != 0); } // dummy TX -void MCU_UpdateUART_TX(void) +void MCU_UpdateUART_TX(mcu_t& mcu) { - if ((dev_register[DEV_SCR] & 32) == 0) // TX disabled + if ((mcu.dev_register[DEV_SCR] & 32) == 0) // TX disabled return; - if (dev_register[DEV_SSR] & 0x80) + if (mcu.dev_register[DEV_SSR] & 0x80) return; - if (mcu.cycles < uart_tx_delay) + if (mcu.cycles < mcu.uart_tx_delay) return; - dev_register[DEV_SSR] |= 0x80; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_UART_TX, (dev_register[DEV_SCR] & 0x80) != 0); + mcu.dev_register[DEV_SSR] |= 0x80; + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_UART_TX, (mcu.dev_register[DEV_SCR] & 0x80) != 0); - // printf("tx:%x\n", dev_register[DEV_TDR]); + // printf("tx:%x\n", mcu.dev_register[DEV_TDR]); } -static bool work_thread_run = false; - -static SDL_mutex *work_thread_lock; - -void MCU_WorkThread_Lock(void) +void MCU_WorkThread_Lock(mcu_t& mcu) { - SDL_LockMutex(work_thread_lock); + SDL_LockMutex(mcu.work_thread_lock); } -void MCU_WorkThread_Unlock(void) +void MCU_WorkThread_Unlock(mcu_t& mcu) { - SDL_UnlockMutex(work_thread_lock); + SDL_UnlockMutex(mcu.work_thread_lock); } -int SDLCALL work_thread(void* data) +void MCU_Step(mcu_t& mcu) { - work_thread_lock = SDL_CreateMutex(); - - MCU_WorkThread_Lock(); - while (work_thread_run) - { - if (pcm.config_reg_3c & 0x40) - sample_write_ptr &= ~3; - else - sample_write_ptr &= ~1; - if (sample_read_ptr == sample_write_ptr) - { - MCU_WorkThread_Unlock(); - while (sample_read_ptr == sample_write_ptr) - { - SDL_Delay(1); - } - MCU_WorkThread_Lock(); - } - - if (!mcu.ex_ignore) - MCU_Interrupt_Handle(); - else - mcu.ex_ignore = 0; + if (!mcu.ex_ignore) + MCU_Interrupt_Handle(mcu); + else + mcu.ex_ignore = 0; - if (!mcu.sleep) - MCU_ReadInstruction(); + if (!mcu.sleep) + MCU_ReadInstruction(mcu); - mcu.cycles += 12; // FIXME: assume 12 cycles per instruction + mcu.cycles += 12; // FIXME: assume 12 cycles per instruction - // if (mcu.cycles % 24000000 == 0) - // printf("seconds: %i\n", (int)(mcu.cycles / 24000000)); + // if (mcu.cycles % 24000000 == 0) + // printf("seconds: %i\n", (int)(mcu.cycles / 24000000)); - PCM_Update(mcu.cycles); + PCM_Update(*mcu.pcm, mcu.cycles); - TIMER_Clock(mcu.cycles); + TIMER_Clock(*mcu.timer, mcu.cycles); - if (!mcu_mk1 && !mcu_jv880 && !mcu_scb55) - SM_Update(mcu.cycles); - else - { - MCU_UpdateUART_RX(); - MCU_UpdateUART_TX(); - } + if (!mcu.mcu_mk1 && !mcu.mcu_jv880 && !mcu.mcu_scb55) + SM_Update(*mcu.sm, mcu.cycles); + else + { + MCU_UpdateUART_RX(mcu); + MCU_UpdateUART_TX(mcu); + } - MCU_UpdateAnalog(mcu.cycles); + MCU_UpdateAnalog(mcu, mcu.cycles); - if (mcu_mk1) + if (mcu.mcu_mk1) + { + if (mcu.ga_lcd_counter) { - if (ga_lcd_counter) + mcu.ga_lcd_counter--; + if (mcu.ga_lcd_counter == 0) { - ga_lcd_counter--; - if (ga_lcd_counter == 0) - { - MCU_GA_SetGAInt(1, 0); - MCU_GA_SetGAInt(1, 1); - } + MCU_GA_SetGAInt(mcu, 1, 0); + MCU_GA_SetGAInt(mcu, 1, 1); } } } - MCU_WorkThread_Unlock(); - - SDL_DestroyMutex(work_thread_lock); - - return 0; } -static void MCU_Run() -{ - bool working = true; - - work_thread_run = true; - SDL_Thread *thread = SDL_CreateThread(work_thread, "work thread", 0); - - while (working) - { - if(LCD_QuitRequested()) - working = false; - - LCD_Update(); - SDL_Delay(15); - } - - work_thread_run = false; - SDL_WaitThread(thread, 0); -} - -void MCU_PatchROM(void) +void MCU_PatchROM(mcu_t& mcu) { + (void)mcu; //rom2[0x1333] = 0x11; //rom2[0x1334] = 0x19; //rom1[0x622d] = 0x19; } -uint8_t mcu_p0_data = 0x00; -uint8_t mcu_p1_data = 0x00; - -uint8_t MCU_ReadP0(void) +uint8_t MCU_ReadP0(mcu_t& mcu) { + (void)mcu; return 0xff; } -uint8_t MCU_ReadP1(void) +uint8_t MCU_ReadP1(mcu_t& mcu) { uint8_t data = 0xff; - uint32_t button_pressed = (uint32_t)SDL_AtomicGet(&mcu_button_pressed); + uint32_t button_pressed = (uint32_t)SDL_AtomicGet(&mcu.mcu_button_pressed); - if ((mcu_p0_data & 1) == 0) + if ((mcu.mcu_p0_data & 1) == 0) data &= ((button_pressed >> 0) & 255) ^ 255; - if ((mcu_p0_data & 2) == 0) + if ((mcu.mcu_p0_data & 2) == 0) data &= ((button_pressed >> 8) & 255) ^ 255; - if ((mcu_p0_data & 4) == 0) + if ((mcu.mcu_p0_data & 4) == 0) data &= ((button_pressed >> 16) & 255) ^ 255; - if ((mcu_p0_data & 8) == 0) + if ((mcu.mcu_p0_data & 8) == 0) data &= ((button_pressed >> 24) & 255) ^ 255; return data; } -void MCU_WriteP0(uint8_t data) -{ - mcu_p0_data = data; -} - -void MCU_WriteP1(uint8_t data) +void MCU_WriteP0(mcu_t& mcu, uint8_t data) { - mcu_p1_data = data; + mcu.mcu_p0_data = data; } -uint8_t tempbuf[0x800000]; - -void unscramble(uint8_t *src, uint8_t *dst, int len) -{ - for (int i = 0; i < len; i++) - { - int address = i & ~0xfffff; - static const int aa[] = { - 2, 0, 3, 4, 1, 9, 13, 10, 18, 17, 6, 15, 11, 16, 8, 5, 12, 7, 14, 19 - }; - for (int j = 0; j < 20; j++) - { - if (i & (1 << j)) - address |= 1<= num) - { - printf("Out of range audio device index is requested. Default audio output device is selected.\n"); - deviceIndex = -1; - } - - const char* audioDevicename = deviceIndex == -1 ? "Default device" : SDL_GetAudioDeviceName(deviceIndex, 0); - - sdl_audio = SDL_OpenAudioDevice(deviceIndex == -1 ? NULL : audioDevicename, 0, &spec, &spec_actual, 0); - if (!sdl_audio) - { - return 0; - } - - printf("Audio device: %s\n", audioDevicename); - - printf("Audio Requested: F=%s, C=%d, R=%d, B=%d\n", - audio_format_to_str(spec.format), - spec.channels, - spec.freq, - spec.samples); - - printf("Audio Actual: F=%s, C=%d, R=%d, B=%d\n", - audio_format_to_str(spec_actual.format), - spec_actual.channels, - spec_actual.freq, - spec_actual.samples); - fflush(stdout); - - SDL_PauseAudioDevice(sdl_audio, 0); - - return 1; -} - -void MCU_CloseAudio(void) +void MCU_WriteP1(mcu_t& mcu, uint8_t data) { - SDL_CloseAudio(); - if (sample_buffer) free(sample_buffer); + mcu.mcu_p1_data = data; } -void MCU_PostSample(int *sample) +void MCU_PostSample(mcu_t& mcu, int *sample) { - sample[0] >>= 15; - if (sample[0] > INT16_MAX) - sample[0] = INT16_MAX; - else if (sample[0] < INT16_MIN) - sample[0] = INT16_MIN; - sample[1] >>= 15; - if (sample[1] > INT16_MAX) - sample[1] = INT16_MAX; - else if (sample[1] < INT16_MIN) - sample[1] = INT16_MIN; - sample_buffer[sample_write_ptr + 0] = sample[0]; - sample_buffer[sample_write_ptr + 1] = sample[1]; - sample_write_ptr = (sample_write_ptr + 2) % audio_buffer_size; + mcu.sample_callback(mcu.callback_userdata, sample); } -void MCU_GA_SetGAInt(int line, int value) +void MCU_GA_SetGAInt(mcu_t& mcu, int line, int value) { // guesswork - if (value && !ga_int[line] && (ga_int_enable & (1 << line)) != 0) - ga_int_trigger = line; - ga_int[line] = value; + if (value && !mcu.ga_int[line] && (mcu.ga_int_enable & (1 << line)) != 0) + mcu.ga_int_trigger = line; + mcu.ga_int[line] = value; - if (mcu_jv880) - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_IRQ0, ga_int_trigger != 0); + if (mcu.mcu_jv880) + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_IRQ0, mcu.ga_int_trigger != 0); else - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_IRQ1, ga_int_trigger != 0); -} - -void MCU_EncoderTrigger(int dir) -{ - if (!mcu_jv880) return; - MCU_GA_SetGAInt(dir == 0 ? 3 : 4, 0); - MCU_GA_SetGAInt(dir == 0 ? 3 : 4, 1); + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_IRQ1, mcu.ga_int_trigger != 0); } - -static const size_t rf_num = 5; -static FILE *s_rf[rf_num] = -{ - nullptr, - nullptr, - nullptr, - nullptr, - nullptr -}; - -static void closeAllR() +void MCU_EncoderTrigger(mcu_t& mcu, int dir) { - for(size_t i = 0; i < rf_num; ++i) - { - if(s_rf[i]) - fclose(s_rf[i]); - s_rf[i] = nullptr; - } + if (!mcu.mcu_jv880) return; + MCU_GA_SetGAInt(mcu, dir == 0 ? 3 : 4, 0); + MCU_GA_SetGAInt(mcu, dir == 0 ? 3 : 4, 1); } -enum class ResetType { - NONE, - GS_RESET, - GM_RESET, -}; - -void MIDI_Reset(ResetType resetType) -{ - const unsigned char gmReset[] = { 0xF0, 0x7E, 0x7F, 0x09, 0x01, 0xF7 }; - const unsigned char gsReset[] = { 0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7F, 0x00, 0x41, 0xF7 }; - - if (resetType == ResetType::GS_RESET) - { - for (size_t i = 0; i < sizeof(gsReset); i++) - { - MCU_PostUART(gsReset[i]); - } - } - else if (resetType == ResetType::GM_RESET) - { - for (size_t i = 0; i < sizeof(gmReset); i++) - { - MCU_PostUART(gmReset[i]); - } - } - -} - -int main(int argc, char *argv[]) -{ - (void)argc; - std::string basePath; - - int port = 0; - int audioDeviceIndex = -1; - int pageSize = 512; - int pageNum = 32; - bool autodetect = true; - ResetType resetType = ResetType::NONE; - - romset = ROM_SET_MK2; - - { - for (int i = 1; i < argc; i++) - { - if (!strncmp(argv[i], "-p:", 3)) - { - port = atoi(argv[i] + 3); - } - else if (!strncmp(argv[i], "-a:", 3)) - { - audioDeviceIndex = atoi(argv[i] + 3); - } - else if (!strncmp(argv[i], "-ab:", 4)) - { - char* pColon = argv[i] + 3; - - if (pColon[1] != 0) - { - pageSize = atoi(++pColon); - pColon = strchr(pColon, ':'); - if (pColon && pColon[1] != 0) - { - pageNum = atoi(++pColon); - } - } - - // reset both if either is invalid - if (pageSize <= 0 || pageNum <= 0) - { - pageSize = 512; - pageNum = 32; - } - } - else if (!strcmp(argv[i], "-mk2")) - { - romset = ROM_SET_MK2; - autodetect = false; - } - else if (!strcmp(argv[i], "-st")) - { - romset = ROM_SET_ST; - autodetect = false; - } - else if (!strcmp(argv[i], "-mk1")) - { - romset = ROM_SET_MK1; - autodetect = false; - } - else if (!strcmp(argv[i], "-cm300")) - { - romset = ROM_SET_CM300; - autodetect = false; - } - else if (!strcmp(argv[i], "-jv880")) - { - romset = ROM_SET_JV880; - autodetect = false; - } - else if (!strcmp(argv[i], "-scb55")) - { - romset = ROM_SET_SCB55; - autodetect = false; - } - else if (!strcmp(argv[i], "-rlp3237")) - { - romset = ROM_SET_RLP3237; - autodetect = false; - } - else if (!strcmp(argv[i], "-gs")) - { - resetType = ResetType::GS_RESET; - } - else if (!strcmp(argv[i], "-gm")) - { - resetType = ResetType::GM_RESET; - } - else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "-help") || !strcmp(argv[i], "--help")) - { - // TODO: Might want to try to find a way to print out the executable's actual name (without any full paths). - printf("Usage: nuked-sc55 [options]\n"); - printf("Options:\n"); - printf(" -h, -help, --help Display this information.\n"); - printf("\n"); - printf(" -p: Set MIDI port.\n"); - printf(" -a: Set Audio Device index.\n"); - printf(" -ab::[page_count] Set Audio Buffer size.\n"); - printf("\n"); - printf(" -mk2 Use SC-55mk2 ROM set.\n"); - printf(" -st Use SC-55st ROM set.\n"); - printf(" -mk1 Use SC-55mk1 ROM set.\n"); - printf(" -cm300 Use CM-300/SCC-1 ROM set.\n"); - printf(" -jv880 Use JV-880 ROM set.\n"); - printf(" -scb55 Use SCB-55 ROM set.\n"); - printf(" -rlp3237 Use RLP-3237 ROM set.\n"); - printf("\n"); - printf(" -gs Reset system in GS mode.\n"); - printf(" -gm Reset system in GM mode.\n"); - return 0; - } - else if (!strcmp(argv[i], "-sc155")) - { - romset = ROM_SET_SC155; - autodetect = false; - } - else if (!strcmp(argv[i], "-sc155mk2")) - { - romset = ROM_SET_SC155MK2; - autodetect = false; - } - } - } - -#if __linux__ - char self_path[PATH_MAX]; - memset(&self_path[0], 0, PATH_MAX); - - if(readlink("/proc/self/exe", self_path, PATH_MAX) == -1) - basePath = Files::real_dirname(argv[0]); - else - basePath = Files::dirname(self_path); -#else - basePath = Files::real_dirname(argv[0]); -#endif - - printf("Base path is: %s\n", argv[0]); - - if(Files::dirExists(basePath + "/../share/nuked-sc55")) - basePath += "/../share/nuked-sc55"; - - if (autodetect) - { - for (size_t i = 0; i < ROM_SET_COUNT; i++) - { - bool good = true; - for (size_t j = 0; j < 5; j++) - { - if (roms[i][j][0] == '\0') - continue; - std::string path = basePath + "/" + roms[i][j]; - auto h = Files::utf8_fopen(path.c_str(), "rb"); - if (!h) - { - good = false; - break; - } - fclose(h); - } - if (good) - { - romset = i; - break; - } - } - printf("ROM set autodetect: %s\n", rs_name[romset]); - } - - mcu_mk1 = false; - mcu_cm300 = false; - mcu_st = false; - mcu_jv880 = false; - mcu_scb55 = false; - mcu_sc155 = false; - switch (romset) - { - case ROM_SET_MK2: - case ROM_SET_SC155MK2: - if (romset == ROM_SET_SC155MK2) - mcu_sc155 = true; - break; - case ROM_SET_ST: - mcu_st = true; - break; - case ROM_SET_MK1: - case ROM_SET_SC155: - mcu_mk1 = true; - mcu_st = false; - if (romset == ROM_SET_SC155) - mcu_sc155 = true; - break; - case ROM_SET_CM300: - mcu_mk1 = true; - mcu_cm300 = true; - break; - case ROM_SET_JV880: - mcu_jv880 = true; - rom2_mask /= 2; // rom is half the size - lcd_width = 820; - lcd_height = 100; - break; - case ROM_SET_SCB55: - case ROM_SET_RLP3237: - mcu_scb55 = true; - break; - } - - std::string rpaths[5]; - - bool r_ok = true; - std::string errors_list; - - for(size_t i = 0; i < 5; ++i) - { - if (roms[romset][i][0] == '\0') - { - rpaths[i] = ""; - continue; - } - rpaths[i] = basePath + "/" + roms[romset][i]; - s_rf[i] = Files::utf8_fopen(rpaths[i].c_str(), "rb"); - bool optional = mcu_jv880 && i == 4; - r_ok &= optional || (s_rf[i] != nullptr); - if(!s_rf[i]) - { - if(!errors_list.empty()) - errors_list.append(", "); - - errors_list.append(rpaths[i]); - } - } - - if (!r_ok) - { - fprintf(stderr, "FATAL ERROR: One of required data ROM files is missing: %s.\n", errors_list.c_str()); - fflush(stderr); - closeAllR(); - return 1; - } - - LCD_SetBackPath(basePath + "/back.data"); - - memset(&mcu, 0, sizeof(mcu_t)); - - - if (fread(rom1, 1, ROM1_SIZE, s_rf[0]) != ROM1_SIZE) - { - fprintf(stderr, "FATAL ERROR: Failed to read the mcu ROM1.\n"); - fflush(stderr); - closeAllR(); - return 1; - } - - size_t rom2_read = fread(rom2, 1, ROM2_SIZE, s_rf[1]); - - if (rom2_read == ROM2_SIZE || rom2_read == ROM2_SIZE / 2) - { - rom2_mask = rom2_read - 1; - } - else - { - fprintf(stderr, "FATAL ERROR: Failed to read the mcu ROM2.\n"); - fflush(stderr); - closeAllR(); - return 1; - } - - if (mcu_mk1) - { - if (fread(tempbuf, 1, 0x100000, s_rf[2]) != 0x100000) - { - fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom1.\n"); - fflush(stderr); - closeAllR(); - return 1; - } - - unscramble(tempbuf, waverom1, 0x100000); - - if (fread(tempbuf, 1, 0x100000, s_rf[3]) != 0x100000) - { - fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom2.\n"); - fflush(stderr); - closeAllR(); - return 1; - } - - unscramble(tempbuf, waverom2, 0x100000); - - if (fread(tempbuf, 1, 0x100000, s_rf[4]) != 0x100000) - { - fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom3.\n"); - fflush(stderr); - closeAllR(); - return 1; - } - - unscramble(tempbuf, waverom3, 0x100000); - } - else if (mcu_jv880) - { - if (fread(tempbuf, 1, 0x200000, s_rf[2]) != 0x200000) - { - fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom1.\n"); - fflush(stderr); - closeAllR(); - return 1; - } - - unscramble(tempbuf, waverom1, 0x200000); - - if (fread(tempbuf, 1, 0x200000, s_rf[3]) != 0x200000) - { - fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom2.\n"); - fflush(stderr); - closeAllR(); - return 1; - } - - unscramble(tempbuf, waverom2, 0x200000); - - if (s_rf[4] && fread(tempbuf, 1, 0x800000, s_rf[4])) - unscramble(tempbuf, waverom_exp, 0x800000); - else - printf("WaveRom EXP not found, skipping it.\n"); - } - else - { - if (fread(tempbuf, 1, 0x200000, s_rf[2]) != 0x200000) - { - fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom1.\n"); - fflush(stderr); - closeAllR(); - return 1; - } - - unscramble(tempbuf, waverom1, 0x200000); - - if (s_rf[3]) - { - if (fread(tempbuf, 1, 0x100000, s_rf[3]) != 0x100000) - { - fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom2.\n"); - fflush(stderr); - closeAllR(); - return 1; - } - - unscramble(tempbuf, mcu_scb55 ? waverom3 : waverom2, 0x100000); - } - - if (s_rf[4] && fread(sm_rom, 1, ROMSM_SIZE, s_rf[4]) != ROMSM_SIZE) - { - fprintf(stderr, "FATAL ERROR: Failed to read the sub mcu ROM.\n"); - fflush(stderr); - closeAllR(); - return 1; - } - } - - // Close all files as they no longer needed being open - closeAllR(); - - if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) - { - fprintf(stderr, "FATAL ERROR: Failed to initialize the SDL2: %s.\n", SDL_GetError()); - fflush(stderr); - return 2; - } - - if (!MCU_OpenAudio(audioDeviceIndex, pageSize, pageNum)) - { - fprintf(stderr, "FATAL ERROR: Failed to open the audio stream.\n"); - fflush(stderr); - return 2; - } - - if(!MIDI_Init(port)) - { - fprintf(stderr, "ERROR: Failed to initialize the MIDI Input.\nWARNING: Continuing without MIDI Input...\n"); - fflush(stderr); - } - - LCD_Init(); - MCU_Init(); - MCU_PatchROM(); - MCU_Reset(); - SM_Reset(); - PCM_Reset(); - - if (resetType != ResetType::NONE) MIDI_Reset(resetType); - - MCU_Run(); - - MCU_CloseAudio(); - MIDI_Quit(); - LCD_UnInit(); - SDL_Quit(); - - return 0; -} diff --git a/src/mcu.h b/src/mcu.h index ba490678..2921dca1 100644 --- a/src/mcu.h +++ b/src/mcu.h @@ -36,6 +36,12 @@ #include #include "mcu_interrupt.h" #include "SDL_atomic.h" +#include "SDL.h" + +struct submcu_t; +struct pcm_t; +struct mcu_timer_t; +struct lcd_t; enum { DEV_P1DDR = 0x00, @@ -102,8 +108,6 @@ enum { DEV_P9DR = 0x7f, }; -extern uint8_t dev_register[0x80]; - const uint16_t sr_mask = 0x870f; enum { STATUS_T = 0x8000, @@ -174,6 +178,17 @@ enum { VECTOR_INTERNAL_INTERRUPT_E0, // ADI }; +static const int ROM1_SIZE = 0x8000; +static const int ROM2_SIZE = 0x80000; +static const int RAM_SIZE = 0x400; +static const int SRAM_SIZE = 0x8000; +static const int NVRAM_SIZE = 0x8000; // JV880 only +static const int CARDRAM_SIZE = 0x8000; // JV880 only +static const int ROMSM_SIZE = 0x1000; + +static const uint32_t uart_buffer_size = 8192; + +typedef void(*mcu_sample_callback)(void* userdata, int* sample); struct mcu_t { uint16_t r[8]; @@ -186,43 +201,114 @@ struct mcu_t { uint8_t interrupt_pending[INTERRUPT_SOURCE_MAX]; uint8_t trapa_pending[16]; uint64_t cycles; + + uint8_t rom1[ROM1_SIZE]; + uint8_t rom2[ROM2_SIZE]; + uint8_t ram[RAM_SIZE]; + uint8_t sram[SRAM_SIZE]; + uint8_t nvram[NVRAM_SIZE]; + uint8_t cardram[CARDRAM_SIZE]; + + uint8_t dev_register[0x80]; + + uint16_t ad_val[4]; + uint8_t ad_nibble; + uint8_t sw_pos; + uint8_t io_sd; + + submcu_t* sm; + pcm_t* pcm; + mcu_timer_t* timer; + lcd_t* lcd; + + uint32_t uart_write_ptr; + uint32_t uart_read_ptr; + uint8_t uart_buffer[uart_buffer_size]; + + uint8_t uart_rx_byte; + uint64_t uart_rx_delay; + uint64_t uart_tx_delay; + + int romset; + + int mcu_mk1; // 0 - SC-55mkII, SC-55ST. 1 - SC-55, CM-300/SCC-1 + int mcu_cm300; // 0 - SC-55, 1 - CM-300/SCC-1 + int mcu_st; // 0 - SC-55mk2, 1 - SC-55ST + int mcu_jv880; // 0 - SC-55, 1 - JV880 + int mcu_scb55; // 0 - sub mcu (e.g SC-55mk2), 1 - no sub mcu (e.g SCB-55) + int mcu_sc155; // 0 - SC-55(MK2), 1 - SC-155(MK2) + + int rom2_mask; + + int ga_int[8]; + int ga_int_enable; + int ga_int_trigger; + int ga_lcd_counter; + + SDL_atomic_t mcu_button_pressed; + + uint8_t mcu_p0_data; + uint8_t mcu_p1_data; + + int adf_rd; + + uint64_t analog_end_time; + + int ssr_rd; + + uint32_t operand_type; + uint16_t operand_ea; + uint8_t operand_ep; + uint8_t operand_size; + uint8_t operand_reg; + uint8_t operand_status; + uint16_t operand_data; + uint8_t opcode_extended; + + void* callback_userdata; + mcu_sample_callback sample_callback; + + SDL_mutex *work_thread_lock; }; -extern mcu_t mcu; +bool MCU_Init(mcu_t& mcu, submcu_t& sm, pcm_t& pcm, mcu_timer_t& timer, lcd_t& lcd); +void MCU_Reset(mcu_t& mcu); +void MCU_PatchROM(mcu_t& mcu); +void MCU_Step(mcu_t& mcu); -void MCU_ErrorTrap(void); +void MCU_ErrorTrap(mcu_t& mcu); -uint8_t MCU_Read(uint32_t address); -uint16_t MCU_Read16(uint32_t address); -uint32_t MCU_Read32(uint32_t address); -void MCU_Write(uint32_t address, uint8_t value); -void MCU_Write16(uint32_t address, uint16_t value); +uint8_t MCU_Read(mcu_t& mcu, uint32_t address); +uint16_t MCU_Read16(mcu_t& mcu, uint32_t address); +uint32_t MCU_Read32(mcu_t& mcu, uint32_t address); +void MCU_Write(mcu_t& mcu, uint32_t address, uint8_t value); +void MCU_Write16(mcu_t& mcu, uint32_t address, uint16_t value); inline uint32_t MCU_GetAddress(uint8_t page, uint16_t address) { return (page << 16) + address; } -inline uint8_t MCU_ReadCode(void) { - return MCU_Read(MCU_GetAddress(mcu.cp, mcu.pc)); +inline uint8_t MCU_ReadCode(mcu_t& mcu) { + return MCU_Read(mcu, MCU_GetAddress(mcu.cp, mcu.pc)); } -inline uint8_t MCU_ReadCodeAdvance(void) { - uint8_t ret = MCU_ReadCode(); +inline uint8_t MCU_ReadCodeAdvance(mcu_t& mcu) { + uint8_t ret = MCU_ReadCode(mcu); mcu.pc++; return ret; } -inline void MCU_SetRegisterByte(uint8_t reg, uint8_t val) +inline void MCU_SetRegisterByte(mcu_t& mcu, uint8_t reg, uint8_t val) { mcu.r[reg] = val; } -inline uint32_t MCU_GetVectorAddress(uint32_t vector) +inline uint32_t MCU_GetVectorAddress(mcu_t& mcu, uint32_t vector) { - return MCU_Read32(vector * 4); + return MCU_Read32(mcu, vector * 4); } -inline uint32_t MCU_GetPageForRegister(uint32_t reg) +inline uint32_t MCU_GetPageForRegister(mcu_t& mcu, uint32_t reg) { if (reg >= 6) return mcu.tp; @@ -231,7 +317,7 @@ inline uint32_t MCU_GetPageForRegister(uint32_t reg) return mcu.dp; } -inline void MCU_ControlRegisterWrite(uint32_t reg, uint32_t siz, uint32_t data) +inline void MCU_ControlRegisterWrite(mcu_t& mcu, uint32_t reg, uint32_t siz, uint32_t data) { if (siz) { @@ -254,7 +340,7 @@ inline void MCU_ControlRegisterWrite(uint32_t reg, uint32_t siz, uint32_t data) } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } } else @@ -283,12 +369,12 @@ inline void MCU_ControlRegisterWrite(uint32_t reg, uint32_t siz, uint32_t data) } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } } } -inline uint32_t MCU_ControlRegisterRead(uint32_t reg, uint32_t siz) +inline uint32_t MCU_ControlRegisterRead(mcu_t& mcu, uint32_t reg, uint32_t siz) { uint32_t ret = 0; if (siz) @@ -311,7 +397,7 @@ inline uint32_t MCU_ControlRegisterRead(uint32_t reg, uint32_t siz) } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } ret &= 0xffff; } @@ -339,14 +425,14 @@ inline uint32_t MCU_ControlRegisterRead(uint32_t reg, uint32_t siz) } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } ret &= 0xff; } return ret; } -inline void MCU_SetStatus(uint32_t condition, uint32_t mask) +inline void MCU_SetStatus(mcu_t& mcu, uint32_t condition, uint32_t mask) { if (condition) mcu.sr |= mask; @@ -354,20 +440,20 @@ inline void MCU_SetStatus(uint32_t condition, uint32_t mask) mcu.sr &= ~mask; } -inline void MCU_PushStack(uint16_t data) +inline void MCU_PushStack(mcu_t& mcu, uint16_t data) { if (mcu.r[7] & 1) - MCU_Interrupt_Exception(EXCEPTION_SOURCE_ADDRESS_ERROR); + MCU_Interrupt_Exception(mcu, EXCEPTION_SOURCE_ADDRESS_ERROR); mcu.r[7] -= 2; - MCU_Write16(mcu.r[7], data); + MCU_Write16(mcu, mcu.r[7], data); } -inline uint16_t MCU_PopStack(void) +inline uint16_t MCU_PopStack(mcu_t& mcu) { uint16_t ret; if (mcu.r[7] & 1) - MCU_Interrupt_Exception(EXCEPTION_SOURCE_ADDRESS_ERROR); - ret = MCU_Read16(mcu.r[7]); + MCU_Interrupt_Exception(mcu, EXCEPTION_SOURCE_ADDRESS_ERROR); + ret = MCU_Read16(mcu, mcu.r[7]); mcu.r[7] += 2; return ret; } @@ -442,34 +528,16 @@ enum { ROM_SET_COUNT }; -extern const char* rs_name[ROM_SET_COUNT]; - -extern int romset; - -extern int mcu_mk1; -extern int mcu_cm300; -extern int mcu_st; -extern int mcu_jv880; -extern int mcu_scb55; -extern int mcu_sc155; - -extern SDL_atomic_t mcu_button_pressed; - -static const uint32_t uart_buffer_size = 8192; -extern uint32_t uart_write_ptr; -extern uint32_t uart_read_ptr; -extern uint8_t uart_buffer[uart_buffer_size]; - -uint8_t MCU_ReadP0(void); -uint8_t MCU_ReadP1(void); -void MCU_WriteP0(uint8_t data); -void MCU_WriteP1(uint8_t data); -void MCU_GA_SetGAInt(int line, int value); +uint8_t MCU_ReadP0(mcu_t& mcu); +uint8_t MCU_ReadP1(mcu_t& mcu); +void MCU_WriteP0(mcu_t& mcu, uint8_t data); +void MCU_WriteP1(mcu_t& mcu, uint8_t data); +void MCU_GA_SetGAInt(mcu_t& mcu, int line, int value); -void MCU_EncoderTrigger(int dir); +void MCU_EncoderTrigger(mcu_t& mcu, int dir); -void MCU_PostSample(int *sample); -void MCU_PostUART(uint8_t data); +void MCU_PostSample(mcu_t& mcu, int *sample); +void MCU_PostUART(mcu_t& mcu, uint8_t data); -void MCU_WorkThread_Lock(void); -void MCU_WorkThread_Unlock(void); +void MCU_WorkThread_Lock(mcu_t& mcu); +void MCU_WorkThread_Unlock(mcu_t& mcu); diff --git a/src/mcu_interrupt.cpp b/src/mcu_interrupt.cpp index edb517ed..fa36b600 100644 --- a/src/mcu_interrupt.cpp +++ b/src/mcu_interrupt.cpp @@ -35,11 +35,11 @@ #include "mcu.h" #include "mcu_interrupt.h" -void MCU_Interrupt_Start(int32_t mask) +void MCU_Interrupt_Start(mcu_t& mcu, int32_t mask) { - MCU_PushStack(mcu.pc); - MCU_PushStack(mcu.cp); - MCU_PushStack(mcu.sr); + MCU_PushStack(mcu, mcu.pc); + MCU_PushStack(mcu, mcu.cp); + MCU_PushStack(mcu, mcu.sr); mcu.sr &= ~STATUS_T; if (mask >= 0) { @@ -49,36 +49,36 @@ void MCU_Interrupt_Start(int32_t mask) mcu.sleep = 0; } -void MCU_Interrupt_SetRequest(uint32_t interrupt, uint32_t value) +void MCU_Interrupt_SetRequest(mcu_t& mcu, uint32_t interrupt, uint32_t value) { mcu.interrupt_pending[interrupt] = value; } -void MCU_Interrupt_Exception(uint32_t exception) +void MCU_Interrupt_Exception(mcu_t& mcu, uint32_t exception) { #if 0 - if (interrupt == INTERRUPT_SOURCE_IRQ0 && (dev_register[DEV_P1CR] & 0x20) == 0) + if (interrupt == INTERRUPT_SOURCE_IRQ0 && (mcu.dev_register[DEV_P1CR] & 0x20) == 0) return; - if (interrupt == INTERRUPT_SOURCE_IRQ1 && (dev_register[DEV_P1CR] & 0x40) == 0) + if (interrupt == INTERRUPT_SOURCE_IRQ1 && (mcu.dev_register[DEV_P1CR] & 0x40) == 0) return; #endif mcu.exception_pending = exception; } -void MCU_Interrupt_TRAPA(uint32_t vector) +void MCU_Interrupt_TRAPA(mcu_t& mcu, uint32_t vector) { mcu.trapa_pending[vector] = 1; } -void MCU_Interrupt_StartVector(uint32_t vector, int32_t mask) +void MCU_Interrupt_StartVector(mcu_t& mcu, uint32_t vector, int32_t mask) { - uint32_t address = MCU_GetVectorAddress(vector); - MCU_Interrupt_Start(mask); + uint32_t address = MCU_GetVectorAddress(mcu, vector); + MCU_Interrupt_Start(mcu, mask); mcu.cp = address >> 16; mcu.pc = address; } -void MCU_Interrupt_Handle(void) +void MCU_Interrupt_Handle(mcu_t& mcu) { #if 0 if (mcu.cycles % 2000 == 0 && mcu.sleep) @@ -103,7 +103,7 @@ void MCU_Interrupt_Handle(void) if (mcu.trapa_pending[i]) { mcu.trapa_pending[i] = 0; - MCU_Interrupt_StartVector(VECTOR_TRAPA_0 + i, -1); + MCU_Interrupt_StartVector(mcu, VECTOR_TRAPA_0 + i, -1); return; } } @@ -112,13 +112,13 @@ void MCU_Interrupt_Handle(void) switch (mcu.exception_pending) { case EXCEPTION_SOURCE_ADDRESS_ERROR: - MCU_Interrupt_StartVector(VECTOR_ADDRESS_ERROR, -1); + MCU_Interrupt_StartVector(mcu, VECTOR_ADDRESS_ERROR, -1); break; case EXCEPTION_SOURCE_INVALID_INSTRUCTION: - MCU_Interrupt_StartVector(VECTOR_INVALID_INSTRUCTION, -1); + MCU_Interrupt_StartVector(mcu, VECTOR_INVALID_INSTRUCTION, -1); break; case EXCEPTION_SOURCE_TRACE: - MCU_Interrupt_StartVector(VECTOR_TRACE, -1); + MCU_Interrupt_StartVector(mcu, VECTOR_TRACE, -1); break; } @@ -128,7 +128,7 @@ void MCU_Interrupt_Handle(void) if (mcu.interrupt_pending[INTERRUPT_SOURCE_NMI]) { // mcu.interrupt_pending[INTERRUPT_SOURCE_NMI] = 0; - MCU_Interrupt_StartVector(VECTOR_NMI, 7); + MCU_Interrupt_StartVector(mcu, VECTOR_NMI, 7); return; } uint32_t mask = (mcu.sr >> 8) & 7; @@ -141,76 +141,76 @@ void MCU_Interrupt_Handle(void) switch (i) { case INTERRUPT_SOURCE_IRQ0: - if ((dev_register[DEV_P1CR] & 0x20) == 0) + if ((mcu.dev_register[DEV_P1CR] & 0x20) == 0) continue; vector = VECTOR_IRQ0; - level = (dev_register[DEV_IPRA] >> 4) & 7; + level = (mcu.dev_register[DEV_IPRA] >> 4) & 7; break; case INTERRUPT_SOURCE_IRQ1: - if ((dev_register[DEV_P1CR] & 0x40) == 0) + if ((mcu.dev_register[DEV_P1CR] & 0x40) == 0) continue; vector = VECTOR_IRQ1; - level = (dev_register[DEV_IPRA] >> 0) & 7; + level = (mcu.dev_register[DEV_IPRA] >> 0) & 7; break; case INTERRUPT_SOURCE_FRT0_OCIA: vector = VECTOR_INTERNAL_INTERRUPT_94; - level = (dev_register[DEV_IPRB] >> 4) & 7; + level = (mcu.dev_register[DEV_IPRB] >> 4) & 7; break; case INTERRUPT_SOURCE_FRT0_OCIB: vector = VECTOR_INTERNAL_INTERRUPT_98; - level = (dev_register[DEV_IPRB] >> 4) & 7; + level = (mcu.dev_register[DEV_IPRB] >> 4) & 7; break; case INTERRUPT_SOURCE_FRT0_FOVI: vector = VECTOR_INTERNAL_INTERRUPT_9C; - level = (dev_register[DEV_IPRB] >> 4) & 7; + level = (mcu.dev_register[DEV_IPRB] >> 4) & 7; break; case INTERRUPT_SOURCE_FRT1_OCIA: vector = VECTOR_INTERNAL_INTERRUPT_A4; - level = (dev_register[DEV_IPRB] >> 0) & 7; + level = (mcu.dev_register[DEV_IPRB] >> 0) & 7; break; case INTERRUPT_SOURCE_FRT1_OCIB: vector = VECTOR_INTERNAL_INTERRUPT_A8; - level = (dev_register[DEV_IPRB] >> 0) & 7; + level = (mcu.dev_register[DEV_IPRB] >> 0) & 7; break; case INTERRUPT_SOURCE_FRT1_FOVI: vector = VECTOR_INTERNAL_INTERRUPT_AC; - level = (dev_register[DEV_IPRB] >> 0) & 7; + level = (mcu.dev_register[DEV_IPRB] >> 0) & 7; break; case INTERRUPT_SOURCE_FRT2_OCIA: vector = VECTOR_INTERNAL_INTERRUPT_B4; - level = (dev_register[DEV_IPRC] >> 4) & 7; + level = (mcu.dev_register[DEV_IPRC] >> 4) & 7; break; case INTERRUPT_SOURCE_FRT2_OCIB: vector = VECTOR_INTERNAL_INTERRUPT_B8; - level = (dev_register[DEV_IPRC] >> 4) & 7; + level = (mcu.dev_register[DEV_IPRC] >> 4) & 7; break; case INTERRUPT_SOURCE_FRT2_FOVI: vector = VECTOR_INTERNAL_INTERRUPT_BC; - level = (dev_register[DEV_IPRC] >> 4) & 7; + level = (mcu.dev_register[DEV_IPRC] >> 4) & 7; break; case INTERRUPT_SOURCE_TIMER_CMIA: vector = VECTOR_INTERNAL_INTERRUPT_C0; - level = (dev_register[DEV_IPRC] >> 0) & 7; + level = (mcu.dev_register[DEV_IPRC] >> 0) & 7; break; case INTERRUPT_SOURCE_TIMER_CMIB: vector = VECTOR_INTERNAL_INTERRUPT_C4; - level = (dev_register[DEV_IPRC] >> 0) & 7; + level = (mcu.dev_register[DEV_IPRC] >> 0) & 7; break; case INTERRUPT_SOURCE_TIMER_OVI: vector = VECTOR_INTERNAL_INTERRUPT_C8; - level = (dev_register[DEV_IPRC] >> 0) & 7; + level = (mcu.dev_register[DEV_IPRC] >> 0) & 7; break; case INTERRUPT_SOURCE_ANALOG: vector = VECTOR_INTERNAL_INTERRUPT_E0; - level = (dev_register[DEV_IPRD] >> 0) & 7; + level = (mcu.dev_register[DEV_IPRD] >> 0) & 7; break; case INTERRUPT_SOURCE_UART_RX: vector = VECTOR_INTERNAL_INTERRUPT_D4; - level = (dev_register[DEV_IPRD] >> 4) & 7; + level = (mcu.dev_register[DEV_IPRD] >> 4) & 7; break; case INTERRUPT_SOURCE_UART_TX: vector = VECTOR_INTERNAL_INTERRUPT_D8; - level = (dev_register[DEV_IPRD] >> 4) & 7; + level = (mcu.dev_register[DEV_IPRD] >> 4) & 7; break; default: break; @@ -219,7 +219,7 @@ void MCU_Interrupt_Handle(void) if ((int32_t)mask < level) { // mcu.interrupt_pending[INTERRUPT_SOURCE_NMI] = 0; - MCU_Interrupt_StartVector(vector, level); + MCU_Interrupt_StartVector(mcu, vector, level); return; } } diff --git a/src/mcu_interrupt.h b/src/mcu_interrupt.h index dd2b4d83..d5c27876 100644 --- a/src/mcu_interrupt.h +++ b/src/mcu_interrupt.h @@ -35,10 +35,12 @@ #include -void MCU_Interrupt_SetRequest(uint32_t interrupt, uint32_t value); -void MCU_Interrupt_Exception(uint32_t exception); -void MCU_Interrupt_TRAPA(uint32_t vector); -void MCU_Interrupt_Handle(void); +struct mcu_t; + +void MCU_Interrupt_SetRequest(mcu_t& mcu, uint32_t interrupt, uint32_t value); +void MCU_Interrupt_Exception(mcu_t& mcu, uint32_t exception); +void MCU_Interrupt_TRAPA(mcu_t& mcu, uint32_t vector); +void MCU_Interrupt_Handle(mcu_t& mcu); enum { INTERRUPT_SOURCE_NMI = 0, @@ -69,4 +71,4 @@ enum { EXCEPTION_SOURCE_ADDRESS_ERROR = 0, EXCEPTION_SOURCE_INVALID_INSTRUCTION, EXCEPTION_SOURCE_TRACE, -}; \ No newline at end of file +}; diff --git a/src/mcu_opcodes.cpp b/src/mcu_opcodes.cpp index dd01c25e..5c4c9a13 100644 --- a/src/mcu_opcodes.cpp +++ b/src/mcu_opcodes.cpp @@ -36,7 +36,7 @@ #include "mcu_opcodes.h" #include "mcu_interrupt.h" -int32_t MCU_SUB_Common(int32_t t1, int32_t t2, int32_t c_bit, uint32_t siz) +int32_t MCU_SUB_Common(mcu_t& mcu, int32_t t1, int32_t t2, int32_t c_bit, uint32_t siz) { int32_t st1, st2; int32_t N, Z, C, V = 0; @@ -78,15 +78,15 @@ int32_t MCU_SUB_Common(int32_t t1, int32_t t2, int32_t c_bit, uint32_t siz) if (st1 < INT8_MIN || st1 > INT8_MAX) V = 1; } - MCU_SetStatus(N, STATUS_N); - MCU_SetStatus(Z, STATUS_Z); - MCU_SetStatus(C, STATUS_C); - MCU_SetStatus(V, STATUS_V); + MCU_SetStatus(mcu, N, STATUS_N); + MCU_SetStatus(mcu, Z, STATUS_Z); + MCU_SetStatus(mcu, C, STATUS_C); + MCU_SetStatus(mcu, V, STATUS_V); return t1; } -int32_t MCU_ADD_Common(int32_t t1, int32_t t2, int32_t c_bit, uint32_t siz) +int32_t MCU_ADD_Common(mcu_t& mcu, int32_t t1, int32_t t2, int32_t c_bit, uint32_t siz) { int32_t st1, st2; int32_t N, Z, C, V = 0; @@ -128,26 +128,26 @@ int32_t MCU_ADD_Common(int32_t t1, int32_t t2, int32_t c_bit, uint32_t siz) if (st1 < INT8_MIN || st1 > INT8_MAX) V = 1; } - MCU_SetStatus(N, STATUS_N); - MCU_SetStatus(Z, STATUS_Z); - MCU_SetStatus(C, STATUS_C); - MCU_SetStatus(V, STATUS_V); + MCU_SetStatus(mcu, N, STATUS_N); + MCU_SetStatus(mcu, Z, STATUS_Z); + MCU_SetStatus(mcu, C, STATUS_C); + MCU_SetStatus(mcu, V, STATUS_V); return t1; } -void MCU_Operand_Nop(uint8_t operand) +void MCU_Operand_Nop(mcu_t& mcu, uint8_t operand) { } -void MCU_Operand_Sleep(uint8_t operand) +void MCU_Operand_Sleep(mcu_t& mcu, uint8_t operand) { mcu.sleep = 1; } -void MCU_Operand_NotImplemented(uint8_t operand) +void MCU_Operand_NotImplemented(mcu_t& mcu, uint8_t operand) { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } enum { @@ -168,24 +168,24 @@ enum { INCREASE_INCREASE }; -void MCU_LDM(uint8_t operand) +void MCU_LDM(mcu_t& mcu, uint8_t operand) { - uint8_t rlist = MCU_ReadCodeAdvance(); + uint8_t rlist = MCU_ReadCodeAdvance(mcu); int32_t i; for (i = 0; i < 8; i++) { if (rlist & (1 << i)) { - uint16_t data = MCU_PopStack(); + uint16_t data = MCU_PopStack(mcu); if (i != 7) mcu.r[i] = data; } } } -void MCU_STM(uint8_t operand) +void MCU_STM(mcu_t& mcu, uint8_t operand) { - uint8_t rlist = MCU_ReadCodeAdvance(); + uint8_t rlist = MCU_ReadCodeAdvance(mcu); int32_t i; for (i = 7; i >= 0; i--) { @@ -194,58 +194,58 @@ void MCU_STM(uint8_t operand) uint16_t data = mcu.r[i]; if (i == 7) data -= 2; - MCU_PushStack(data); + MCU_PushStack(mcu, data); } } } -void MCU_TRAPA(uint8_t operand) +void MCU_TRAPA(mcu_t& mcu, uint8_t operand) { - uint32_t opcode = MCU_ReadCodeAdvance(); + uint32_t opcode = MCU_ReadCodeAdvance(mcu); if ((opcode & 0xf0) == 0x10) { - MCU_Interrupt_TRAPA(opcode & 0x0f); + MCU_Interrupt_TRAPA(mcu, opcode & 0x0f); } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } } -void MCU_Jump_PJSR(uint8_t operand) +void MCU_Jump_PJSR(mcu_t& mcu, uint8_t operand) { uint32_t ocp = mcu.cp; uint32_t opc = mcu.pc; - uint8_t page = MCU_ReadCodeAdvance(); + uint8_t page = MCU_ReadCodeAdvance(mcu); uint16_t address; - address = MCU_ReadCodeAdvance() << 8; - address |= MCU_ReadCodeAdvance(); - MCU_PushStack(mcu.pc); - MCU_PushStack(mcu.cp); + address = MCU_ReadCodeAdvance(mcu) << 8; + address |= MCU_ReadCodeAdvance(mcu); + MCU_PushStack(mcu, mcu.pc); + MCU_PushStack(mcu, mcu.cp); mcu.cp = page; if (mcu.cp == 0x27) mcu.cp += 0; mcu.pc = address; } -void MCU_Jump_JSR(uint8_t operand) +void MCU_Jump_JSR(mcu_t& mcu, uint8_t operand) { uint16_t address; - address = MCU_ReadCodeAdvance() << 8; - address |= MCU_ReadCodeAdvance(); - MCU_PushStack(mcu.pc); + address = MCU_ReadCodeAdvance(mcu) << 8; + address |= MCU_ReadCodeAdvance(mcu); + MCU_PushStack(mcu, mcu.pc); mcu.pc = address; } -void MCU_Jump_RTE(uint8_t operand) +void MCU_Jump_RTE(mcu_t& mcu, uint8_t operand) { - mcu.sr = MCU_PopStack(); - mcu.cp = (uint8_t)MCU_PopStack(); - mcu.pc = MCU_PopStack(); + mcu.sr = MCU_PopStack(mcu); + mcu.cp = (uint8_t)MCU_PopStack(mcu); + mcu.pc = MCU_PopStack(mcu); mcu.ex_ignore = 1; } -void MCU_Jump_Bcc(uint8_t operand) +void MCU_Jump_Bcc(mcu_t& mcu, uint8_t operand) { uint16_t disp; uint32_t cond; @@ -253,12 +253,12 @@ void MCU_Jump_Bcc(uint8_t operand) uint32_t N, C, Z, V; if (operand & 0x10) { - disp = MCU_ReadCodeAdvance() << 8; - disp |= MCU_ReadCodeAdvance(); + disp = MCU_ReadCodeAdvance(mcu) << 8; + disp |= MCU_ReadCodeAdvance(mcu); } else { - disp = (int8_t)MCU_ReadCodeAdvance(); + disp = (int8_t)MCU_ReadCodeAdvance(mcu); } cond = operand & 0x0f; @@ -325,49 +325,49 @@ void MCU_Jump_Bcc(uint8_t operand) } } -void MCU_Jump_RTS(uint8_t operand) +void MCU_Jump_RTS(mcu_t& mcu, uint8_t operand) { - mcu.pc = MCU_PopStack(); + mcu.pc = MCU_PopStack(mcu); } -void MCU_Jump_RTD(uint8_t operand) +void MCU_Jump_RTD(mcu_t& mcu, uint8_t operand) { - int16_t imm = (int8_t)MCU_ReadCodeAdvance(); - mcu.pc = MCU_PopStack(); + int16_t imm = (int8_t)MCU_ReadCodeAdvance(mcu); + mcu.pc = MCU_PopStack(mcu); if (operand == 0x14) { mcu.r[7] += imm; if (mcu.r[7] & 1) - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } else if (operand == 0x1c) { // TODO - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } } -void MCU_Jump_JMP(uint8_t operand) +void MCU_Jump_JMP(mcu_t& mcu, uint8_t operand) { if (operand == 0x11) { - uint8_t opcode = MCU_ReadCodeAdvance(); + uint8_t opcode = MCU_ReadCodeAdvance(mcu); uint8_t opcode_h = opcode >> 3; uint8_t opcode_l = opcode & 0x07; if (opcode == 0x19) { - mcu.cp = (uint8_t)MCU_PopStack(); - mcu.pc = MCU_PopStack(); + mcu.cp = (uint8_t)MCU_PopStack(mcu); + mcu.pc = MCU_PopStack(mcu); } else if (opcode_h == 0x19) { - MCU_PushStack(mcu.pc); - MCU_PushStack(mcu.cp); + MCU_PushStack(mcu, mcu.pc); + MCU_PushStack(mcu, mcu.cp); opcode_l &= ~1; mcu.cp = mcu.r[opcode_l] & 0xff; mcu.pc = mcu.r[opcode_l + 1]; @@ -378,22 +378,22 @@ void MCU_Jump_JMP(uint8_t operand) } else if (opcode_h == 0x1b) { - MCU_PushStack(mcu.pc); + MCU_PushStack(mcu, mcu.pc); mcu.pc = mcu.r[opcode_l]; } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } } else if (operand == 0x01) { - uint8_t opcode = MCU_ReadCodeAdvance(); + uint8_t opcode = MCU_ReadCodeAdvance(mcu); uint8_t reg = opcode & 0x07; opcode >>= 3; if (opcode == 0x17) { - uint16_t disp = (int8_t)MCU_ReadCodeAdvance(); + uint16_t disp = (int8_t)MCU_ReadCodeAdvance(mcu); mcu.r[reg]--; if (mcu.r[reg] != 0xffff) { @@ -402,24 +402,24 @@ void MCU_Jump_JMP(uint8_t operand) } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } } else if (operand == 0x10) { uint32_t addr; - addr = MCU_ReadCodeAdvance() << 8; - addr |= MCU_ReadCodeAdvance(); + addr = MCU_ReadCodeAdvance(mcu) << 8; + addr |= MCU_ReadCodeAdvance(mcu); mcu.pc = addr; } else if (operand == 0x06) { - uint8_t opcode = MCU_ReadCodeAdvance(); + uint8_t opcode = MCU_ReadCodeAdvance(mcu); uint8_t reg = opcode & 0x07; opcode >>= 3; if (opcode == 0x17) { - uint16_t disp = (int8_t)MCU_ReadCodeAdvance(); + uint16_t disp = (int8_t)MCU_ReadCodeAdvance(mcu); uint32_t Z = (mcu.sr & STATUS_Z) != 0; if (Z) { @@ -432,17 +432,17 @@ void MCU_Jump_JMP(uint8_t operand) } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } } else if (operand == 0x07) { - uint8_t opcode = MCU_ReadCodeAdvance(); + uint8_t opcode = MCU_ReadCodeAdvance(mcu); uint8_t reg = opcode & 0x07; opcode >>= 3; if (opcode == 0x17) { - uint16_t disp = (int8_t)MCU_ReadCodeAdvance(); + uint16_t disp = (int8_t)MCU_ReadCodeAdvance(mcu); uint32_t Z = (mcu.sr & STATUS_Z) != 0; if (!Z) { @@ -455,109 +455,100 @@ void MCU_Jump_JMP(uint8_t operand) } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } } -void MCU_Jump_BSR(uint8_t operand) +void MCU_Jump_BSR(mcu_t& mcu, uint8_t operand) { uint16_t disp; if (operand == 0x0e) { - disp = (int8_t)MCU_ReadCodeAdvance(); + disp = (int8_t)MCU_ReadCodeAdvance(mcu); } else { - disp = MCU_ReadCodeAdvance() << 8; - disp |= MCU_ReadCodeAdvance(); + disp = MCU_ReadCodeAdvance(mcu) << 8; + disp |= MCU_ReadCodeAdvance(mcu); } - MCU_PushStack(mcu.pc); + MCU_PushStack(mcu, mcu.pc); mcu.pc += disp; } -void MCU_Jump_PJMP(uint8_t operand) +void MCU_Jump_PJMP(mcu_t& mcu, uint8_t operand) { uint8_t page; uint16_t address; - page = MCU_ReadCodeAdvance(); - address = MCU_ReadCodeAdvance() << 8; - address |= MCU_ReadCodeAdvance(); + page = MCU_ReadCodeAdvance(mcu); + address = MCU_ReadCodeAdvance(mcu) << 8; + address |= MCU_ReadCodeAdvance(mcu); mcu.cp = page; mcu.pc = address; } -uint32_t operand_type; -uint16_t operand_ea; -uint8_t operand_ep; -uint8_t operand_size; -uint8_t operand_reg; -uint8_t operand_status; -uint16_t operand_data; -uint8_t opcode_extended; - -uint32_t MCU_Operand_Read(void) +uint32_t MCU_Operand_Read(mcu_t& mcu) { - switch (operand_type) + switch (mcu.operand_type) { case GENERAL_DIRECT: - if (operand_size) - return mcu.r[operand_reg]; - return mcu.r[operand_reg] & 0xff; + if (mcu.operand_size) + return mcu.r[mcu.operand_reg]; + return mcu.r[mcu.operand_reg] & 0xff; case GENERAL_INDIRECT: case GENERAL_ABSOLUTE: - if (operand_size) + if (mcu.operand_size) { - if (operand_ea & 1) + if (mcu.operand_ea & 1) { - MCU_Interrupt_Exception(EXCEPTION_SOURCE_ADDRESS_ERROR); + MCU_Interrupt_Exception(mcu, EXCEPTION_SOURCE_ADDRESS_ERROR); } - return MCU_Read16(MCU_GetAddress(operand_ep, operand_ea)); + return MCU_Read16(mcu, MCU_GetAddress(mcu.operand_ep, mcu.operand_ea)); } - return MCU_Read(MCU_GetAddress(operand_ep, operand_ea)); + return MCU_Read(mcu, MCU_GetAddress(mcu.operand_ep, mcu.operand_ea)); case GENERAL_IMMEDIATE: - return operand_data; + return mcu.operand_data; } return 0; } -void MCU_Operand_Write(uint32_t data) +void MCU_Operand_Write(mcu_t& mcu, uint32_t data) { - switch (operand_type) + switch (mcu.operand_type) { case GENERAL_DIRECT: - if (operand_size) - mcu.r[operand_reg] = data; + if (mcu.operand_size) + mcu.r[mcu.operand_reg] = data; else { - mcu.r[operand_reg] &= ~0xff; - mcu.r[operand_reg] |= data & 0xff; + mcu.r[mcu.operand_reg] &= ~0xff; + mcu.r[mcu.operand_reg] |= data & 0xff; } break; case GENERAL_INDIRECT: case GENERAL_ABSOLUTE: - if (operand_size) + if (mcu.operand_size) { - if (operand_ea & 1) + if (mcu.operand_ea & 1) { - MCU_Interrupt_Exception(EXCEPTION_SOURCE_ADDRESS_ERROR); + MCU_Interrupt_Exception(mcu, EXCEPTION_SOURCE_ADDRESS_ERROR); } - MCU_Write16(MCU_GetAddress(operand_ep, operand_ea), data); + MCU_Write16(mcu, MCU_GetAddress(mcu.operand_ep, mcu.operand_ea), data); } else - MCU_Write(MCU_GetAddress(operand_ep, operand_ea), data); + MCU_Write(mcu, MCU_GetAddress(mcu.operand_ep, mcu.operand_ea), data); break; case GENERAL_IMMEDIATE: - MCU_Interrupt_Exception(EXCEPTION_SOURCE_INVALID_INSTRUCTION); + MCU_Interrupt_Exception(mcu, EXCEPTION_SOURCE_INVALID_INSTRUCTION); break; } } -void MCU_Operand_General(uint8_t operand) +void MCU_Operand_General(mcu_t& mcu, uint8_t operand) { uint32_t type = GENERAL_DIRECT; uint32_t disp = 0; @@ -587,13 +578,13 @@ void MCU_Operand_General(uint8_t operand) break; case 0xe0: type = GENERAL_INDIRECT; - disp = (int8_t)MCU_ReadCodeAdvance(); + disp = (int8_t)MCU_ReadCodeAdvance(mcu); break; case 0xf0: type = GENERAL_INDIRECT; - disp = MCU_ReadCodeAdvance(); + disp = MCU_ReadCodeAdvance(mcu); disp <<= 8; - disp |= MCU_ReadCodeAdvance(); + disp |= MCU_ReadCodeAdvance(mcu); break; case 0xb0: type = GENERAL_INDIRECT; @@ -608,17 +599,17 @@ void MCU_Operand_General(uint8_t operand) { type = GENERAL_ABSOLUTE; addr = mcu.br << 8; - addr |= MCU_ReadCodeAdvance(); + addr |= MCU_ReadCodeAdvance(mcu); addrpage = 0; } else if (reg == 4) { type = GENERAL_IMMEDIATE; - data = MCU_ReadCodeAdvance(); + data = MCU_ReadCodeAdvance(mcu); if (siz) { data <<= 8; - data |= MCU_ReadCodeAdvance(); + data |= MCU_ReadCodeAdvance(mcu); } } break; @@ -626,8 +617,8 @@ void MCU_Operand_General(uint8_t operand) if (reg == 5) { type = GENERAL_ABSOLUTE; - addr = MCU_ReadCodeAdvance() << 8; - addr |= MCU_ReadCodeAdvance(); + addr = MCU_ReadCodeAdvance(mcu) << 8; + addr |= MCU_ReadCodeAdvance(mcu); addrpage = mcu.dp; } break; @@ -660,7 +651,7 @@ void MCU_Operand_General(uint8_t operand) ea &= 0xffff; - ep = MCU_GetPageForRegister(reg) & 0xff; + ep = MCU_GetPageForRegister(mcu, reg) & 0xff; } else if (type == GENERAL_ABSOLUTE) { @@ -669,69 +660,69 @@ void MCU_Operand_General(uint8_t operand) ep = addrpage & 0xff; } - opcode = MCU_ReadCodeAdvance(); - opcode_extended = opcode == 0x00; - if (opcode_extended) + opcode = MCU_ReadCodeAdvance(mcu); + mcu.opcode_extended = opcode == 0x00; + if (mcu.opcode_extended) { - opcode = MCU_ReadCodeAdvance(); + opcode = MCU_ReadCodeAdvance(mcu); } opcode_reg = opcode & 0x07; opcode >>= 3; - operand_type = type; - operand_ea = ea; - operand_ep = ep; - operand_size = siz; - operand_reg = reg; - operand_data = data; - operand_status = 0; + mcu.operand_type = type; + mcu.operand_ea = ea; + mcu.operand_ep = ep; + mcu.operand_size = siz; + mcu.operand_reg = reg; + mcu.operand_data = data; + mcu.operand_status = 0; - MCU_Opcode_Table[opcode](opcode, opcode_reg); + MCU_Opcode_Table[opcode](mcu, opcode, opcode_reg); } -void MCU_SetStatusCommon(uint32_t val, uint32_t siz) +void MCU_SetStatusCommon(mcu_t& mcu, uint32_t val, uint32_t siz) { if (siz) val &= 0xffff; else val &= 0xff; if (siz) - MCU_SetStatus(val & 0x8000, STATUS_N); + MCU_SetStatus(mcu, val & 0x8000, STATUS_N); else - MCU_SetStatus(val & 0x80, STATUS_N); - MCU_SetStatus(val == 0, STATUS_Z); - MCU_SetStatus(0, STATUS_V); + MCU_SetStatus(mcu, val & 0x80, STATUS_N); + MCU_SetStatus(mcu, val == 0, STATUS_Z); + MCU_SetStatus(mcu, 0, STATUS_V); } -void MCU_Opcode_Short_NotImplemented(uint8_t opcode) +void MCU_Opcode_Short_NotImplemented(mcu_t& mcu, uint8_t opcode) { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } -void MCU_Opcode_Short_MOVE(uint8_t opcode) +void MCU_Opcode_Short_MOVE(mcu_t& mcu, uint8_t opcode) { uint32_t reg = opcode & 0x07; - uint8_t data = MCU_ReadCodeAdvance(); + uint8_t data = MCU_ReadCodeAdvance(mcu); mcu.r[reg] &= ~0xff; mcu.r[reg] |= data; - MCU_SetStatusCommon(data, 0); + MCU_SetStatusCommon(mcu, data, 0); } -void MCU_Opcode_Short_MOVI(uint8_t opcode) +void MCU_Opcode_Short_MOVI(mcu_t& mcu, uint8_t opcode) { uint32_t reg = opcode & 0x07; uint16_t data; - data = MCU_ReadCodeAdvance() << 8; - data |= MCU_ReadCodeAdvance(); + data = MCU_ReadCodeAdvance(mcu) << 8; + data |= MCU_ReadCodeAdvance(mcu); mcu.r[reg] = data; - MCU_SetStatusCommon(data, 1); + MCU_SetStatusCommon(mcu, data, 1); } -void MCU_Opcode_Short_MOVF(uint8_t opcode) +void MCU_Opcode_Short_MOVF(mcu_t& mcu, uint8_t opcode) { uint32_t reg = opcode & 0x07; uint32_t siz = (opcode & 0x08) != 0; - int8_t disp = MCU_ReadCodeAdvance(); + int8_t disp = MCU_ReadCodeAdvance(mcu); uint32_t addr = (mcu.r[6] + disp) & 0xffff; addr |= mcu.tp << 16; if ((opcode & 0x10) == 0) @@ -739,16 +730,16 @@ void MCU_Opcode_Short_MOVF(uint8_t opcode) uint16_t data; if (siz) { - data = MCU_Read16(addr); + data = MCU_Read16(mcu, addr); mcu.r[reg] &= ~0xff; mcu.r[reg] |= data; - MCU_SetStatusCommon(data, 0); + MCU_SetStatusCommon(mcu, data, 0); } else { - data = MCU_Read(addr); + data = MCU_Read(mcu, addr); mcu.r[reg] = data; - MCU_SetStatusCommon(data, 1); + MCU_SetStatusCommon(mcu, data, 1); } } else @@ -757,317 +748,317 @@ void MCU_Opcode_Short_MOVF(uint8_t opcode) if (siz) { data = mcu.r[reg] & 0xff; - MCU_Write(addr, data); - MCU_SetStatusCommon(data, 0); + MCU_Write(mcu, addr, data); + MCU_SetStatusCommon(mcu, data, 0); } else { data = mcu.r[reg]; - MCU_Write16(addr, data); - MCU_SetStatusCommon(data, 1); + MCU_Write16(mcu, addr, data); + MCU_SetStatusCommon(mcu, data, 1); } } } -void MCU_Opcode_Short_MOVL(uint8_t opcode) +void MCU_Opcode_Short_MOVL(mcu_t& mcu, uint8_t opcode) { uint32_t reg = opcode & 0x07; uint32_t siz = (opcode & 0x08) != 0; uint16_t addr = mcu.br << 8; uint32_t data; - addr |= MCU_ReadCodeAdvance(); + addr |= MCU_ReadCodeAdvance(mcu); if (siz) { if (addr & 1) - MCU_Interrupt_Exception(EXCEPTION_SOURCE_ADDRESS_ERROR); - data = MCU_Read16(addr); + MCU_Interrupt_Exception(mcu, EXCEPTION_SOURCE_ADDRESS_ERROR); + data = MCU_Read16(mcu, addr); mcu.r[reg] = data; - MCU_SetStatusCommon(data, 1); + MCU_SetStatusCommon(mcu, data, 1); } else { - data = MCU_Read(addr); + data = MCU_Read(mcu, addr); mcu.r[reg] &= ~0xff; mcu.r[reg] |= data; - MCU_SetStatusCommon(data, 0); + MCU_SetStatusCommon(mcu, data, 0); } } -void MCU_Opcode_Short_MOVS(uint8_t opcode) +void MCU_Opcode_Short_MOVS(mcu_t& mcu, uint8_t opcode) { uint32_t reg = opcode & 0x07; uint32_t siz = (opcode & 0x08) != 0; uint16_t addr = mcu.br << 8; uint32_t data; - addr |= MCU_ReadCodeAdvance(); + addr |= MCU_ReadCodeAdvance(mcu); if (siz) { if (addr & 1) - MCU_Interrupt_Exception(EXCEPTION_SOURCE_ADDRESS_ERROR); + MCU_Interrupt_Exception(mcu, EXCEPTION_SOURCE_ADDRESS_ERROR); data = mcu.r[reg]; - MCU_Write16(addr, data); - MCU_SetStatusCommon(data, 1); + MCU_Write16(mcu, addr, data); + MCU_SetStatusCommon(mcu, data, 1); } else { data = mcu.r[reg] & 0xff; - MCU_Write(addr, data); - MCU_SetStatusCommon(data, 0); + MCU_Write(mcu, addr, data); + MCU_SetStatusCommon(mcu, data, 0); } } -void MCU_Opcode_Short_CMP(uint8_t opcode) +void MCU_Opcode_Short_CMP(mcu_t& mcu, uint8_t opcode) { uint32_t reg = opcode & 0x07; uint32_t siz = (opcode & 0x08) != 0; int32_t t1, t2; if (siz) { - t2 = MCU_ReadCodeAdvance() << 8; - t2 |= MCU_ReadCodeAdvance(); + t2 = MCU_ReadCodeAdvance(mcu) << 8; + t2 |= MCU_ReadCodeAdvance(mcu); } else { - t2 = MCU_ReadCodeAdvance(); + t2 = MCU_ReadCodeAdvance(mcu); } t1 = mcu.r[reg]; - MCU_SUB_Common(t1, t2, 0, siz); + MCU_SUB_Common(mcu, t1, t2, 0, siz); } -void MCU_Opcode_NotImplemented(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_NotImplemented(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } -void MCU_Opcode_MOVG_Immediate(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_MOVG_Immediate(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { uint32_t data; - if (opcode_reg == 6 && (operand_type == GENERAL_INDIRECT || operand_type == GENERAL_ABSOLUTE)) + if (opcode_reg == 6 && (mcu.operand_type == GENERAL_INDIRECT || mcu.operand_type == GENERAL_ABSOLUTE)) { - data = (int8_t)MCU_ReadCodeAdvance(); - MCU_Operand_Write(data); - MCU_SetStatusCommon(data, operand_size); + data = (int8_t)MCU_ReadCodeAdvance(mcu); + MCU_Operand_Write(mcu, data); + MCU_SetStatusCommon(mcu, data, mcu.operand_size); } - else if (opcode_reg == 7 && (operand_type == GENERAL_INDIRECT || operand_type == GENERAL_ABSOLUTE)) + else if (opcode_reg == 7 && (mcu.operand_type == GENERAL_INDIRECT || mcu.operand_type == GENERAL_ABSOLUTE)) { - data = MCU_ReadCodeAdvance() << 8; - data |= MCU_ReadCodeAdvance(); - MCU_Operand_Write(data); - MCU_SetStatusCommon(data, operand_size); + data = MCU_ReadCodeAdvance(mcu) << 8; + data |= MCU_ReadCodeAdvance(mcu); + MCU_Operand_Write(mcu, data); + MCU_SetStatusCommon(mcu, data, mcu.operand_size); } - else if (opcode_reg == 4 && (operand_type == GENERAL_INDIRECT || operand_type == GENERAL_ABSOLUTE) && operand_size == OPERAND_BYTE) + else if (opcode_reg == 4 && (mcu.operand_type == GENERAL_INDIRECT || mcu.operand_type == GENERAL_ABSOLUTE) && mcu.operand_size == OPERAND_BYTE) { - uint32_t t1 = MCU_Operand_Read(); - uint32_t t2 = MCU_ReadCodeAdvance(); - MCU_SUB_Common(t1, t2, 0, OPERAND_BYTE); + uint32_t t1 = MCU_Operand_Read(mcu); + uint32_t t2 = MCU_ReadCodeAdvance(mcu); + MCU_SUB_Common(mcu, t1, t2, 0, OPERAND_BYTE); } - else if (opcode_reg == 4 && (operand_type == GENERAL_INDIRECT || operand_type == GENERAL_ABSOLUTE) && operand_size == OPERAND_WORD) // FIXME + else if (opcode_reg == 4 && (mcu.operand_type == GENERAL_INDIRECT || mcu.operand_type == GENERAL_ABSOLUTE) && mcu.operand_size == OPERAND_WORD) // FIXME { - uint32_t t1 = MCU_Operand_Read(); - uint32_t t2 = (uint16_t)((int8_t)MCU_ReadCodeAdvance()); - MCU_SUB_Common(t1, t2, 0, OPERAND_WORD); + uint32_t t1 = MCU_Operand_Read(mcu); + uint32_t t2 = (uint16_t)((int8_t)MCU_ReadCodeAdvance(mcu)); + MCU_SUB_Common(mcu, t1, t2, 0, OPERAND_WORD); } - else if (opcode_reg == 5 && (operand_type == GENERAL_INDIRECT || operand_type == GENERAL_ABSOLUTE) && operand_size == OPERAND_WORD) + else if (opcode_reg == 5 && (mcu.operand_type == GENERAL_INDIRECT || mcu.operand_type == GENERAL_ABSOLUTE) && mcu.operand_size == OPERAND_WORD) { uint32_t t1, t2; - t1 = MCU_Operand_Read(); - t2 = MCU_ReadCodeAdvance() << 8; - t2 |= MCU_ReadCodeAdvance(); - MCU_SUB_Common(t1, t2, 0, OPERAND_WORD); + t1 = MCU_Operand_Read(mcu); + t2 = MCU_ReadCodeAdvance(mcu) << 8; + t2 |= MCU_ReadCodeAdvance(mcu); + MCU_SUB_Common(mcu, t1, t2, 0, OPERAND_WORD); } - else if (opcode_reg == 5 && (operand_type == GENERAL_INDIRECT || operand_type == GENERAL_ABSOLUTE) && operand_size == OPERAND_BYTE) // FIXME + else if (opcode_reg == 5 && (mcu.operand_type == GENERAL_INDIRECT || mcu.operand_type == GENERAL_ABSOLUTE) && mcu.operand_size == OPERAND_BYTE) // FIXME { uint32_t t1, t2; - t1 = MCU_Operand_Read(); - t2 = MCU_ReadCodeAdvance() << 8; - t2 |= MCU_ReadCodeAdvance(); - MCU_SUB_Common(t1, t2, 0, OPERAND_BYTE); + t1 = MCU_Operand_Read(mcu); + t2 = MCU_ReadCodeAdvance(mcu) << 8; + t2 |= MCU_ReadCodeAdvance(mcu); + MCU_SUB_Common(mcu, t1, t2, 0, OPERAND_BYTE); } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } } -void MCU_Opcode_BSET_ORC(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_BSET_ORC(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { - if (operand_type == GENERAL_IMMEDIATE) // ORC + if (mcu.operand_type == GENERAL_IMMEDIATE) // ORC { - uint32_t data = MCU_Operand_Read(); - uint32_t val = MCU_ControlRegisterRead(opcode_reg, operand_size); + uint32_t data = MCU_Operand_Read(mcu); + uint32_t val = MCU_ControlRegisterRead(mcu, opcode_reg, mcu.operand_size); val |= data; - MCU_ControlRegisterWrite(opcode_reg, operand_size, val); + MCU_ControlRegisterWrite(mcu, opcode_reg, mcu.operand_size, val); if (opcode_reg >= 2) { - MCU_SetStatusCommon(val, operand_size); + MCU_SetStatusCommon(mcu, val, mcu.operand_size); } mcu.ex_ignore = 1; } else // BSET { - uint32_t data = MCU_Operand_Read(); + uint32_t data = MCU_Operand_Read(mcu); uint32_t bit = mcu.r[opcode_reg] & 0x0f; - MCU_SetStatus((data & (1 << bit)) == 0, STATUS_Z); + MCU_SetStatus(mcu, (data & (1 << bit)) == 0, STATUS_Z); data |= 1 << bit; - MCU_Operand_Write(data); + MCU_Operand_Write(mcu, data); } } -void MCU_Opcode_BCLR_ANDC(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_BCLR_ANDC(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { - if (operand_type == GENERAL_IMMEDIATE) // ANDC + if (mcu.operand_type == GENERAL_IMMEDIATE) // ANDC { - uint32_t data = MCU_Operand_Read(); - uint32_t val = MCU_ControlRegisterRead(opcode_reg, operand_size); + uint32_t data = MCU_Operand_Read(mcu); + uint32_t val = MCU_ControlRegisterRead(mcu, opcode_reg, mcu.operand_size); val &= data; - MCU_ControlRegisterWrite(opcode_reg, operand_size, val); + MCU_ControlRegisterWrite(mcu, opcode_reg, mcu.operand_size, val); if (opcode_reg >= 2) { - MCU_SetStatusCommon(val, operand_size); + MCU_SetStatusCommon(mcu, val, mcu.operand_size); } mcu.ex_ignore = 1; } else // BCLR { - uint32_t data = MCU_Operand_Read(); + uint32_t data = MCU_Operand_Read(mcu); uint32_t bit = mcu.r[opcode_reg] & 0x0f; - MCU_SetStatus((data & (1 << bit)) == 0, STATUS_Z); + MCU_SetStatus(mcu, (data & (1 << bit)) == 0, STATUS_Z); data &= ~(1 << bit); - MCU_Operand_Write(data); + MCU_Operand_Write(mcu, data); } } -void MCU_Opcode_BTST(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_BTST(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { - if (operand_type != GENERAL_IMMEDIATE) + if (mcu.operand_type != GENERAL_IMMEDIATE) { - uint32_t data = MCU_Operand_Read(); + uint32_t data = MCU_Operand_Read(mcu); uint32_t bit = mcu.r[opcode_reg] & 0x0f; - MCU_SetStatus((data & (1 << bit)) == 0, STATUS_Z); + MCU_SetStatus(mcu, (data & (1 << bit)) == 0, STATUS_Z); } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } } -void MCU_Opcode_CLR(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_CLR(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { - if (opcode_reg == 3 && operand_type != GENERAL_IMMEDIATE) // CLR + if (opcode_reg == 3 && mcu.operand_type != GENERAL_IMMEDIATE) // CLR { - MCU_Operand_Write(0); - MCU_SetStatus(0, STATUS_N); - MCU_SetStatus(1, STATUS_Z); - MCU_SetStatus(0, STATUS_V); - MCU_SetStatus(0, STATUS_C); + MCU_Operand_Write(mcu, 0); + MCU_SetStatus(mcu, 0, STATUS_N); + MCU_SetStatus(mcu, 1, STATUS_Z); + MCU_SetStatus(mcu, 0, STATUS_V); + MCU_SetStatus(mcu, 0, STATUS_C); } - else if (opcode_reg == 6 && operand_type != GENERAL_IMMEDIATE) // TST + else if (opcode_reg == 6 && mcu.operand_type != GENERAL_IMMEDIATE) // TST { - uint32_t data = MCU_Operand_Read(); - MCU_SetStatusCommon(data, operand_size); - MCU_SetStatus(0, STATUS_C); + uint32_t data = MCU_Operand_Read(mcu); + MCU_SetStatusCommon(mcu, data, mcu.operand_size); + MCU_SetStatus(mcu, 0, STATUS_C); } - else if (opcode_reg == 2 && operand_type == GENERAL_DIRECT && operand_size == 0) // EXTU + else if (opcode_reg == 2 && mcu.operand_type == GENERAL_DIRECT && mcu.operand_size == 0) // EXTU { - uint32_t data = (uint8_t)mcu.r[operand_reg]; - mcu.r[operand_reg] = data; - MCU_SetStatus(0, STATUS_N); - MCU_SetStatus(data == 0, STATUS_Z); - MCU_SetStatus(0, STATUS_V); - MCU_SetStatus(0, STATUS_C); + uint32_t data = (uint8_t)mcu.r[mcu.operand_reg]; + mcu.r[mcu.operand_reg] = data; + MCU_SetStatus(mcu, 0, STATUS_N); + MCU_SetStatus(mcu, data == 0, STATUS_Z); + MCU_SetStatus(mcu, 0, STATUS_V); + MCU_SetStatus(mcu, 0, STATUS_C); } - else if (opcode_reg == 0 && operand_type == GENERAL_DIRECT && operand_size == 0) // SWAP + else if (opcode_reg == 0 && mcu.operand_type == GENERAL_DIRECT && mcu.operand_size == 0) // SWAP { - uint32_t data = mcu.r[operand_reg]; + uint32_t data = mcu.r[mcu.operand_reg]; uint32_t data_h = data >> 8; uint32_t data_l = data & 0xff; data = (data_l << 8) | data_h; - mcu.r[operand_reg] = data; - MCU_SetStatusCommon(data, OPERAND_BYTE); // FIXME: might be WORD??? + mcu.r[mcu.operand_reg] = data; + MCU_SetStatusCommon(mcu, data, OPERAND_BYTE); // FIXME: might be WORD??? //MCU_SetStatusCommon(data, OPERAND_WORD); } - else if (opcode_reg == 5 && operand_type != GENERAL_IMMEDIATE) // NOT + else if (opcode_reg == 5 && mcu.operand_type != GENERAL_IMMEDIATE) // NOT { - uint32_t data = MCU_Operand_Read(); + uint32_t data = MCU_Operand_Read(mcu); data = ~data; - MCU_Operand_Write(data); - MCU_SetStatusCommon(data, operand_size); + MCU_Operand_Write(mcu, data); + MCU_SetStatusCommon(mcu, data, mcu.operand_size); } - else if (opcode_reg == 4 && operand_type != GENERAL_IMMEDIATE) // NEG + else if (opcode_reg == 4 && mcu.operand_type != GENERAL_IMMEDIATE) // NEG { - uint32_t data = MCU_Operand_Read(); - data = MCU_SUB_Common(0, data, 0, operand_size); - MCU_Operand_Write(data); + uint32_t data = MCU_Operand_Read(mcu); + data = MCU_SUB_Common(mcu, 0, data, 0, mcu.operand_size); + MCU_Operand_Write(mcu, data); } - else if (opcode_reg == 1 && operand_type == GENERAL_DIRECT && operand_size == 0) // EXTS + else if (opcode_reg == 1 && mcu.operand_type == GENERAL_DIRECT && mcu.operand_size == 0) // EXTS { - uint32_t data = mcu.r[operand_reg]; - mcu.r[operand_reg] = (int8_t)data; - MCU_SetStatusCommon(data, OPERAND_WORD); + uint32_t data = mcu.r[mcu.operand_reg]; + mcu.r[mcu.operand_reg] = (int8_t)data; + MCU_SetStatusCommon(mcu, data, OPERAND_WORD); } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } } -void MCU_Opcode_LDC(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_LDC(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { - uint32_t data = MCU_Operand_Read(); - MCU_ControlRegisterWrite(opcode_reg, operand_size, data); + uint32_t data = MCU_Operand_Read(mcu); + MCU_ControlRegisterWrite(mcu, opcode_reg, mcu.operand_size, data); mcu.ex_ignore = 1; } -void MCU_Opcode_STC(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_STC(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { - uint32_t data = MCU_ControlRegisterRead(opcode_reg, operand_size); - MCU_Operand_Write(data); + uint32_t data = MCU_ControlRegisterRead(mcu, opcode_reg, mcu.operand_size); + MCU_Operand_Write(mcu, data); } -void MCU_Opcode_BSET(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_BSET(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { - if (operand_type != GENERAL_IMMEDIATE) + if (mcu.operand_type != GENERAL_IMMEDIATE) { - uint32_t data = MCU_Operand_Read(); + uint32_t data = MCU_Operand_Read(mcu); uint32_t bit = opcode_reg | ((opcode & 1) << 3); - MCU_SetStatus((data & (1 << bit)) == 0, STATUS_Z); + MCU_SetStatus(mcu, (data & (1 << bit)) == 0, STATUS_Z); data |= 1 << bit; - MCU_Operand_Write(data); + MCU_Operand_Write(mcu, data); } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } } -void MCU_Opcode_BCLR(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_BCLR(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { - if (operand_type != GENERAL_IMMEDIATE) + if (mcu.operand_type != GENERAL_IMMEDIATE) { - uint32_t data = MCU_Operand_Read(); + uint32_t data = MCU_Operand_Read(mcu); uint32_t bit = opcode_reg | ((opcode & 1) << 3); - MCU_SetStatus((data & (1 << bit)) == 0, STATUS_Z); + MCU_SetStatus(mcu, (data & (1 << bit)) == 0, STATUS_Z); data &= ~(1 << bit); - MCU_Operand_Write(data); + MCU_Operand_Write(mcu, data); } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } } -void MCU_Opcode_MOVG(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_MOVG(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { - if (opcode_extended) + if (mcu.opcode_extended) { if (opcode == 0x12) { // FIXME - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } } else @@ -1076,89 +1067,89 @@ void MCU_Opcode_MOVG(uint8_t opcode, uint8_t opcode_reg) uint32_t data; if (d) { - if (operand_type == GENERAL_DIRECT) // XCH + if (mcu.operand_type == GENERAL_DIRECT) // XCH { - if (operand_size) + if (mcu.operand_size) { uint32_t r1 = mcu.r[opcode_reg]; - uint32_t r2 = mcu.r[operand_reg]; + uint32_t r2 = mcu.r[mcu.operand_reg]; mcu.r[opcode_reg] = r2; - mcu.r[operand_reg] = r1; + mcu.r[mcu.operand_reg] = r1; } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } } else { data = mcu.r[opcode_reg]; - MCU_Operand_Write(data); - MCU_SetStatusCommon(data, operand_size); + MCU_Operand_Write(mcu, data); + MCU_SetStatusCommon(mcu, data, mcu.operand_size); } } else { - data = MCU_Operand_Read(); - if (operand_size) + data = MCU_Operand_Read(mcu); + if (mcu.operand_size) mcu.r[opcode_reg] = data; else { mcu.r[opcode_reg] &= ~0xff; mcu.r[opcode_reg] |= data & 0xff; } - MCU_SetStatusCommon(data, operand_size); + MCU_SetStatusCommon(mcu, data, mcu.operand_size); } } } -void MCU_Opcode_BTSTI(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_BTSTI(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { - if (operand_type != GENERAL_IMMEDIATE) + if (mcu.operand_type != GENERAL_IMMEDIATE) { - uint32_t data = MCU_Operand_Read(); + uint32_t data = MCU_Operand_Read(mcu); uint32_t bit = opcode_reg | ((opcode & 1) << 3); - MCU_SetStatus((data & (1 << bit)) == 0, STATUS_Z); + MCU_SetStatus(mcu, (data & (1 << bit)) == 0, STATUS_Z); } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } } -void MCU_Opcode_BNOTI(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_BNOTI(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { - if (operand_type != GENERAL_IMMEDIATE) + if (mcu.operand_type != GENERAL_IMMEDIATE) { - uint32_t data = MCU_Operand_Read(); + uint32_t data = MCU_Operand_Read(mcu); uint32_t bit = opcode_reg | ((opcode & 1) << 3); - MCU_SetStatus((data & (1 << bit)) == 0, STATUS_Z); + MCU_SetStatus(mcu, (data & (1 << bit)) == 0, STATUS_Z); data ^= (1 << bit); - MCU_Operand_Write(data); + MCU_Operand_Write(mcu, data); } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } } -void MCU_Opcode_OR(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_OR(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { - uint32_t data = MCU_Operand_Read(); + uint32_t data = MCU_Operand_Read(mcu); mcu.r[opcode_reg] |= data; - MCU_SetStatusCommon(mcu.r[opcode_reg], operand_size); + MCU_SetStatusCommon(mcu, mcu.r[opcode_reg], mcu.operand_size); } -void MCU_Opcode_CMP(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_CMP(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { int32_t t1 = mcu.r[opcode_reg]; - int32_t t2 = MCU_Operand_Read(); - MCU_SUB_Common(t1, t2, 0, operand_size); + int32_t t2 = MCU_Operand_Read(mcu); + MCU_SUB_Common(mcu, t1, t2, 0, mcu.operand_size); } -void MCU_Opcode_ADDQ(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_ADDQ(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { - int32_t t1 = MCU_Operand_Read(); + int32_t t1 = MCU_Operand_Read(mcu); int32_t t2 = 0; switch (opcode_reg) { @@ -1175,19 +1166,19 @@ void MCU_Opcode_ADDQ(uint8_t opcode, uint8_t opcode_reg) t2 = -2; break; default: - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); break; } - t1 = MCU_ADD_Common(t1, t2, 0, operand_size); - MCU_Operand_Write(t1); + t1 = MCU_ADD_Common(mcu, t1, t2, 0, mcu.operand_size); + MCU_Operand_Write(mcu, t1); } -void MCU_Opcode_ADD(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_ADD(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { int32_t t1 = mcu.r[opcode_reg]; - int32_t t2 = MCU_Operand_Read(); - t1 = MCU_ADD_Common(t1, t2, 0, operand_size); - if (operand_size) + int32_t t2 = MCU_Operand_Read(mcu); + t1 = MCU_ADD_Common(mcu, t1, t2, 0, mcu.operand_size); + if (mcu.operand_size) mcu.r[opcode_reg] = t1; else { @@ -1196,12 +1187,12 @@ void MCU_Opcode_ADD(uint8_t opcode, uint8_t opcode_reg) } } -void MCU_Opcode_SUB(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_SUB(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { int32_t t1 = mcu.r[opcode_reg]; - int32_t t2 = MCU_Operand_Read(); - t1 = MCU_SUB_Common(t1, t2, 0, operand_size); - if (operand_size) + int32_t t2 = MCU_Operand_Read(mcu); + t1 = MCU_SUB_Common(mcu, t1, t2, 0, mcu.operand_size); + if (mcu.operand_size) mcu.r[opcode_reg] = t1; else { @@ -1210,102 +1201,102 @@ void MCU_Opcode_SUB(uint8_t opcode, uint8_t opcode_reg) } } -void MCU_Opcode_SUBS(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_SUBS(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { int32_t t1 = mcu.r[opcode_reg]; - int32_t t2 = MCU_Operand_Read(); - if (operand_size) + int32_t t2 = MCU_Operand_Read(mcu); + if (mcu.operand_size) mcu.r[opcode_reg] = t1 - t2; else mcu.r[opcode_reg] = t1 - (int8_t)t2; } -void MCU_Opcode_AND(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_AND(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { uint32_t data = mcu.r[opcode_reg]; - data &= MCU_Operand_Read(); - if (operand_size) + data &= MCU_Operand_Read(mcu); + if (mcu.operand_size) mcu.r[opcode_reg] = data; else { mcu.r[opcode_reg] &= ~0xff; mcu.r[opcode_reg] |= data & 0xff; } - MCU_SetStatusCommon(mcu.r[opcode_reg], operand_size); + MCU_SetStatusCommon(mcu, mcu.r[opcode_reg], mcu.operand_size); } -void MCU_Opcode_SHLR(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_SHLR(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { - if (opcode_reg == 0x03 && operand_type != GENERAL_IMMEDIATE) // SHLR + if (opcode_reg == 0x03 && mcu.operand_type != GENERAL_IMMEDIATE) // SHLR { - uint32_t data = MCU_Operand_Read(); + uint32_t data = MCU_Operand_Read(mcu); uint32_t C = data & 1; data >>= 1; - MCU_Operand_Write(data); - MCU_SetStatus(C, STATUS_C); - MCU_SetStatusCommon(data, operand_size); + MCU_Operand_Write(mcu, data); + MCU_SetStatus(mcu, C, STATUS_C); + MCU_SetStatusCommon(mcu, data, mcu.operand_size); } - else if (opcode_reg == 0x02 && operand_type != GENERAL_IMMEDIATE) // SHLL + else if (opcode_reg == 0x02 && mcu.operand_type != GENERAL_IMMEDIATE) // SHLL { - uint32_t data = MCU_Operand_Read(); + uint32_t data = MCU_Operand_Read(mcu); uint32_t C; - if (operand_size) + if (mcu.operand_size) C = (data & 0x8000) != 0; else C = (data & 0x80) != 0; data <<= 1; - MCU_Operand_Write(data); - MCU_SetStatus(C, STATUS_C); - MCU_SetStatusCommon(data, operand_size); + MCU_Operand_Write(mcu, data); + MCU_SetStatus(mcu, C, STATUS_C); + MCU_SetStatusCommon(mcu, data, mcu.operand_size); } - else if (opcode_reg == 0x06 && operand_type != GENERAL_IMMEDIATE) // ROTXL + else if (opcode_reg == 0x06 && mcu.operand_type != GENERAL_IMMEDIATE) // ROTXL { - uint32_t data = MCU_Operand_Read(); + uint32_t data = MCU_Operand_Read(mcu); uint32_t bit = (mcu.sr & STATUS_C) != 0; uint32_t C; - if (operand_size) + if (mcu.operand_size) C = (data & 0x8000) != 0; else C = (data & 0x80) != 0; data <<= 1; data |= bit; - MCU_Operand_Write(data); - MCU_SetStatus(C, STATUS_C); - MCU_SetStatusCommon(data, operand_size); + MCU_Operand_Write(mcu, data); + MCU_SetStatus(mcu, C, STATUS_C); + MCU_SetStatusCommon(mcu, data, mcu.operand_size); } - else if (opcode_reg == 0x04 && operand_type != GENERAL_IMMEDIATE) // ROTL + else if (opcode_reg == 0x04 && mcu.operand_type != GENERAL_IMMEDIATE) // ROTL { - uint32_t data = MCU_Operand_Read(); + uint32_t data = MCU_Operand_Read(mcu); uint32_t C; - if (operand_size) + if (mcu.operand_size) C = (data & 0x8000) != 0; else C = (data & 0x80) != 0; data <<= 1; data |= C; - MCU_Operand_Write(data); - MCU_SetStatus(C, STATUS_C); - MCU_SetStatusCommon(data, operand_size); + MCU_Operand_Write(mcu, data); + MCU_SetStatus(mcu, C, STATUS_C); + MCU_SetStatusCommon(mcu, data, mcu.operand_size); } - else if (opcode_reg == 0x00 && operand_type != GENERAL_IMMEDIATE) // SHAL + else if (opcode_reg == 0x00 && mcu.operand_type != GENERAL_IMMEDIATE) // SHAL { - uint32_t data = MCU_Operand_Read(); + uint32_t data = MCU_Operand_Read(mcu); uint32_t C; - if (operand_size) + if (mcu.operand_size) C = (data & 0x8000) != 0; else C = (data & 0x80) != 0; data <<= 1; - MCU_Operand_Write(data); - MCU_SetStatus(C, STATUS_C); - MCU_SetStatusCommon(data, operand_size); + MCU_Operand_Write(mcu, data); + MCU_SetStatus(mcu, C, STATUS_C); + MCU_SetStatusCommon(mcu, data, mcu.operand_size); } - else if (opcode_reg == 0x01 && operand_type != GENERAL_IMMEDIATE) // SHAR + else if (opcode_reg == 0x01 && mcu.operand_type != GENERAL_IMMEDIATE) // SHAR { - uint32_t data = MCU_Operand_Read(); + uint32_t data = MCU_Operand_Read(mcu); uint32_t C = data & 0x1; uint32_t msb; - if (operand_size) + if (mcu.operand_size) { msb = data & 0x8000; data &= 0x7fff; @@ -1317,39 +1308,39 @@ void MCU_Opcode_SHLR(uint8_t opcode, uint8_t opcode_reg) } data >>= 1; data |= msb; - MCU_Operand_Write(data); - MCU_SetStatus(C, STATUS_C); - MCU_SetStatusCommon(data, operand_size); + MCU_Operand_Write(mcu, data); + MCU_SetStatus(mcu, C, STATUS_C); + MCU_SetStatusCommon(mcu, data, mcu.operand_size); } - else if (opcode_reg == 0x05 && operand_type != GENERAL_IMMEDIATE) // ROTR + else if (opcode_reg == 0x05 && mcu.operand_type != GENERAL_IMMEDIATE) // ROTR { - uint32_t data = MCU_Operand_Read(); + uint32_t data = MCU_Operand_Read(mcu); uint32_t C = (data & 0x1) != 0; data >>= 1; - if (operand_size) + if (mcu.operand_size) data |= C << 15; else data |= C << 7; - MCU_Operand_Write(data); - MCU_SetStatus(C, STATUS_C); - MCU_SetStatusCommon(data, operand_size); + MCU_Operand_Write(mcu, data); + MCU_SetStatus(mcu, C, STATUS_C); + MCU_SetStatusCommon(mcu, data, mcu.operand_size); } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } } -void MCU_Opcode_MULXU(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_MULXU(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { - uint32_t t1 = MCU_Operand_Read(); + uint32_t t1 = MCU_Operand_Read(mcu); uint32_t t2 = mcu.r[opcode_reg]; uint32_t N, Z; - if (!operand_size) + if (!mcu.operand_size) t2 &= 0xff; t1 *= t2; - if (operand_size) + if (mcu.operand_size) { opcode_reg &= ~1; mcu.r[opcode_reg | 0] = t1 >> 16; @@ -1363,29 +1354,29 @@ void MCU_Opcode_MULXU(uint8_t opcode, uint8_t opcode_reg) N = (t1 & 0x8000UL) != 0; // FIXME } Z = t1 == 0; - MCU_SetStatus(N, STATUS_N); - MCU_SetStatus(Z, STATUS_Z); - MCU_SetStatus(0, STATUS_V); - MCU_SetStatus(0, STATUS_C); + MCU_SetStatus(mcu, N, STATUS_N); + MCU_SetStatus(mcu, Z, STATUS_Z); + MCU_SetStatus(mcu, 0, STATUS_V); + MCU_SetStatus(mcu, 0, STATUS_C); } -void MCU_Opcode_DIVXU(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_DIVXU(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { - uint32_t t1 = MCU_Operand_Read(); + uint32_t t1 = MCU_Operand_Read(mcu); uint32_t t2; uint32_t R, Q; if (!t1) { - MCU_ErrorTrap(); // FIXME: implement proper exception - MCU_SetStatus(0, STATUS_N); - MCU_SetStatus(1, STATUS_Z); - MCU_SetStatus(0, STATUS_V); - MCU_SetStatus(0, STATUS_C); + MCU_ErrorTrap(mcu); // FIXME: implement proper exception + MCU_SetStatus(mcu, 0, STATUS_N); + MCU_SetStatus(mcu, 1, STATUS_Z); + MCU_SetStatus(mcu, 0, STATUS_V); + MCU_SetStatus(mcu, 0, STATUS_C); return; } - if (operand_size) + if (mcu.operand_size) { opcode_reg &= ~1; t2 = mcu.r[opcode_reg | 0] << 16; @@ -1396,17 +1387,17 @@ void MCU_Opcode_DIVXU(uint8_t opcode, uint8_t opcode_reg) if (Q > UINT16_MAX) { - MCU_SetStatus(0, STATUS_N); - MCU_SetStatus(0, STATUS_Z); - MCU_SetStatus(1, STATUS_V); - MCU_SetStatus(0, STATUS_C); + MCU_SetStatus(mcu, 0, STATUS_N); + MCU_SetStatus(mcu, 0, STATUS_Z); + MCU_SetStatus(mcu, 1, STATUS_V); + MCU_SetStatus(mcu, 0, STATUS_C); } else { mcu.r[opcode_reg | 0] = R; mcu.r[opcode_reg | 1] = Q; - MCU_SetStatusCommon(Q, OPERAND_WORD); - MCU_SetStatus(0, STATUS_C); + MCU_SetStatusCommon(mcu, Q, OPERAND_WORD); + MCU_SetStatus(mcu, 0, STATUS_C); } } else @@ -1418,48 +1409,48 @@ void MCU_Opcode_DIVXU(uint8_t opcode, uint8_t opcode_reg) if (Q > UINT8_MAX) { - MCU_SetStatus(0, STATUS_N); - MCU_SetStatus(0, STATUS_Z); - MCU_SetStatus(1, STATUS_V); - MCU_SetStatus(0, STATUS_C); + MCU_SetStatus(mcu, 0, STATUS_N); + MCU_SetStatus(mcu, 0, STATUS_Z); + MCU_SetStatus(mcu, 1, STATUS_V); + MCU_SetStatus(mcu, 0, STATUS_C); } else { R &= 0xff; Q &= 0xff; mcu.r[opcode_reg] = (R << 8) | Q; - MCU_SetStatusCommon(Q, OPERAND_BYTE); - MCU_SetStatus(0, STATUS_C); + MCU_SetStatusCommon(mcu, Q, OPERAND_BYTE); + MCU_SetStatus(mcu, 0, STATUS_C); } } } -void MCU_Opcode_ADDS(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_ADDS(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { - uint32_t data = MCU_Operand_Read(); - if (!operand_size) + uint32_t data = MCU_Operand_Read(mcu); + if (!mcu.operand_size) data = (int8_t)data; mcu.r[opcode_reg] += data; } -void MCU_Opcode_XOR(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_XOR(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { - uint32_t data = MCU_Operand_Read(); + uint32_t data = MCU_Operand_Read(mcu); mcu.r[opcode_reg] ^= data; - MCU_SetStatusCommon(mcu.r[opcode_reg], operand_size); + MCU_SetStatusCommon(mcu, mcu.r[opcode_reg], mcu.operand_size); } -void MCU_Opcode_ADDX(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_ADDX(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { int32_t t1 = mcu.r[opcode_reg]; - int32_t t2 = MCU_Operand_Read(); + int32_t t2 = MCU_Operand_Read(mcu); int32_t C = (mcu.sr & STATUS_C) != 0; int32_t Z = (mcu.sr & STATUS_Z) != 0; - t1 = MCU_ADD_Common(t1, t2, C, operand_size); + t1 = MCU_ADD_Common(mcu, t1, t2, C, mcu.operand_size); if (!Z) - MCU_SetStatus(0, STATUS_Z); + MCU_SetStatus(mcu, 0, STATUS_Z); - if (operand_size) + if (mcu.operand_size) mcu.r[opcode_reg] = t1; else { @@ -1468,13 +1459,13 @@ void MCU_Opcode_ADDX(uint8_t opcode, uint8_t opcode_reg) } } -void MCU_Opcode_SUBX(uint8_t opcode, uint8_t opcode_reg) +void MCU_Opcode_SUBX(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { int32_t t1 = mcu.r[opcode_reg]; - int32_t t2 = MCU_Operand_Read(); + int32_t t2 = MCU_Operand_Read(mcu); int32_t C = (mcu.sr & STATUS_C) != 0; - t1 = MCU_SUB_Common(t1, t2, C, operand_size); - if (operand_size) + t1 = MCU_SUB_Common(mcu, t1, t2, C, mcu.operand_size); + if (mcu.operand_size) mcu.r[opcode_reg] = t1; else { @@ -1483,7 +1474,7 @@ void MCU_Opcode_SUBX(uint8_t opcode, uint8_t opcode_reg) } } -void (*MCU_Operand_Table[256])(uint8_t operand) = { +void (*MCU_Operand_Table[256])(mcu_t& mcu, uint8_t operand) = { MCU_Operand_Nop, // 00 MCU_Jump_JMP, // 01 MCU_LDM, // 02 @@ -1742,7 +1733,7 @@ void (*MCU_Operand_Table[256])(uint8_t operand) = { MCU_Operand_General, // FF }; -void (*MCU_Opcode_Table[32])(uint8_t opcode, uint8_t opcode_reg) = { +void (*MCU_Opcode_Table[32])(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) = { MCU_Opcode_MOVG_Immediate, // 00 MCU_Opcode_ADDQ, // 01 MCU_Opcode_CLR, // 02 diff --git a/src/mcu_opcodes.h b/src/mcu_opcodes.h index 5b703002..14c169ca 100644 --- a/src/mcu_opcodes.h +++ b/src/mcu_opcodes.h @@ -35,5 +35,5 @@ #include -extern void (*MCU_Operand_Table[256])(uint8_t operand); -extern void (*MCU_Opcode_Table[32])(uint8_t opcode, uint8_t opcode_reg); +extern void (*MCU_Operand_Table[256])(mcu_t& mcu, uint8_t operand); +extern void (*MCU_Opcode_Table[32])(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg); diff --git a/src/mcu_timer.cpp b/src/mcu_timer.cpp index 3736c2a5..a447d402 100644 --- a/src/mcu_timer.cpp +++ b/src/mcu_timer.cpp @@ -36,12 +36,6 @@ #include "mcu.h" #include "mcu_timer.h" -uint64_t timer_cycles; -uint8_t timer_tempreg; - -frt_t frt[3]; -mcu_timer_t timer; - enum { REG_TCR = 0x00, REG_TCSR = 0x01, @@ -55,109 +49,107 @@ enum { REG_ICRL = 0x09, }; -void TIMER_Reset(void) +void TIMER_Init(mcu_timer_t& timer, mcu_t& mcu) { - timer_cycles = 0; - timer_tempreg = 0; - memset(frt, 0, sizeof(frt)); - memset(&timer, 0, sizeof(timer)); + memset(&timer, 0, sizeof(mcu_timer_t)); + timer.mcu = &mcu; } -void TIMER_Write(uint32_t address, uint8_t data) +void TIMER_Write(mcu_timer_t& timer, uint32_t address, uint8_t data) { uint32_t t = (address >> 4) - 1; if (t > 2) return; address &= 0x0f; - frt_t *timer = &frt[t]; + frt_t *ftimer = &timer.frt[t]; switch (address) { case REG_TCR: - timer->tcr = data; + ftimer->tcr = data; break; case REG_TCSR: - timer->tcsr &= ~0xf; - timer->tcsr |= data & 0xf; - if ((data & 0x10) == 0 && (timer->status_rd & 0x10) != 0) + ftimer->tcsr &= ~0xf; + ftimer->tcsr |= data & 0xf; + if ((data & 0x10) == 0 && (ftimer->status_rd & 0x10) != 0) { - timer->tcsr &= ~0x10; - timer->status_rd &= ~0x10; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_FRT0_FOVI + t * 4, 0); + ftimer->tcsr &= ~0x10; + ftimer->status_rd &= ~0x10; + MCU_Interrupt_SetRequest(*timer.mcu, INTERRUPT_SOURCE_FRT0_FOVI + t * 4, 0); } - if ((data & 0x20) == 0 && (timer->status_rd & 0x20) != 0) + if ((data & 0x20) == 0 && (ftimer->status_rd & 0x20) != 0) { - timer->tcsr &= ~0x20; - timer->status_rd &= ~0x20; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_FRT0_OCIA + t * 4, 0); + ftimer->tcsr &= ~0x20; + ftimer->status_rd &= ~0x20; + MCU_Interrupt_SetRequest(*timer.mcu, INTERRUPT_SOURCE_FRT0_OCIA + t * 4, 0); } - if ((data & 0x40) == 0 && (timer->status_rd & 0x40) != 0) + if ((data & 0x40) == 0 && (ftimer->status_rd & 0x40) != 0) { - timer->tcsr &= ~0x40; - timer->status_rd &= ~0x40; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_FRT0_OCIB + t * 4, 0); + ftimer->tcsr &= ~0x40; + ftimer->status_rd &= ~0x40; + MCU_Interrupt_SetRequest(*timer.mcu, INTERRUPT_SOURCE_FRT0_OCIB + t * 4, 0); } break; case REG_FRCH: case REG_OCRAH: case REG_OCRBH: case REG_ICRH: - timer_tempreg = data; + timer.timer_tempreg = data; break; case REG_FRCL: - timer->frc = (timer_tempreg << 8) | data; + ftimer->frc = (timer.timer_tempreg << 8) | data; break; case REG_OCRAL: - timer->ocra = (timer_tempreg << 8) | data; + ftimer->ocra = (timer.timer_tempreg << 8) | data; break; case REG_OCRBL: - timer->ocrb = (timer_tempreg << 8) | data; + ftimer->ocrb = (timer.timer_tempreg << 8) | data; break; case REG_ICRL: - timer->icr = (timer_tempreg << 8) | data; + ftimer->icr = (timer.timer_tempreg << 8) | data; break; } } -uint8_t TIMER_Read(uint32_t address) +uint8_t TIMER_Read(mcu_timer_t& timer, uint32_t address) { uint32_t t = (address >> 4) - 1; if (t > 2) return 0xff; address &= 0x0f; - frt_t *timer = &frt[t]; + frt_t *ftimer = &timer.frt[t]; switch (address) { case REG_TCR: - return timer->tcr; + return ftimer->tcr; case REG_TCSR: { - uint8_t ret = timer->tcsr; - timer->status_rd |= timer->tcsr & 0xf0; - //timer->status_rd |= 0xf0; + uint8_t ret = ftimer->tcsr; + ftimer->status_rd |= ftimer->tcsr & 0xf0; + //ftimer->status_rd |= 0xf0; return ret; } case REG_FRCH: - timer_tempreg = timer->frc & 0xff; - return timer->frc >> 8; + timer.timer_tempreg = ftimer->frc & 0xff; + return ftimer->frc >> 8; case REG_OCRAH: - timer_tempreg = timer->ocra & 0xff; - return timer->ocra >> 8; + timer.timer_tempreg = ftimer->ocra & 0xff; + return ftimer->ocra >> 8; case REG_OCRBH: - timer_tempreg = timer->ocrb & 0xff; - return timer->ocrb >> 8; + timer.timer_tempreg = ftimer->ocrb & 0xff; + return ftimer->ocrb >> 8; case REG_ICRH: - timer_tempreg = timer->icr & 0xff; - return timer->icr >> 8; + timer.timer_tempreg = ftimer->icr & 0xff; + return ftimer->icr >> 8; case REG_FRCL: case REG_OCRAL: case REG_OCRBL: case REG_ICRL: - return timer_tempreg; + return timer.timer_tempreg; } return 0xff; } -void TIMER2_Write(uint32_t address, uint8_t data) +void TIMER2_Write(mcu_timer_t& timer, uint32_t address, uint8_t data) { switch (address) { @@ -171,19 +163,19 @@ void TIMER2_Write(uint32_t address, uint8_t data) { timer.tcsr &= ~0x20; timer.status_rd &= ~0x20; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_TIMER_OVI, 0); + MCU_Interrupt_SetRequest(*timer.mcu, INTERRUPT_SOURCE_TIMER_OVI, 0); } if ((data & 0x40) == 0 && (timer.status_rd & 0x40) != 0) { timer.tcsr &= ~0x40; timer.status_rd &= ~0x40; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_TIMER_CMIA, 0); + MCU_Interrupt_SetRequest(*timer.mcu, INTERRUPT_SOURCE_TIMER_CMIA, 0); } if ((data & 0x80) == 0 && (timer.status_rd & 0x80) != 0) { timer.tcsr &= ~0x80; timer.status_rd &= ~0x80; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_TIMER_CMIB, 0); + MCU_Interrupt_SetRequest(*timer.mcu, INTERRUPT_SOURCE_TIMER_CMIB, 0); } break; case DEV_TMR_TCORA: @@ -197,7 +189,7 @@ void TIMER2_Write(uint32_t address, uint8_t data) break; } } -uint8_t TIMER_Read2(uint32_t address) +uint8_t TIMER_Read2(mcu_timer_t& timer, uint32_t address) { switch (address) { @@ -219,68 +211,68 @@ uint8_t TIMER_Read2(uint32_t address) return 0xff; } -void TIMER_Clock(uint64_t cycles) +void TIMER_Clock(mcu_timer_t& timer, uint64_t cycles) { uint32_t i; - while (timer_cycles*2 < cycles) // FIXME + while (timer.timer_cycles*2 < cycles) // FIXME { for (i = 0; i < 3; i++) { - frt_t *timer = &frt[i]; + frt_t *ftimer = &timer.frt[i]; uint32_t offset = 0x10 * i; - switch (timer->tcr & 3) + switch (ftimer->tcr & 3) { case 0: // o / 4 - if (timer_cycles & 3) + if (timer.timer_cycles & 3) continue; break; case 1: // o / 8 - if (timer_cycles & 7) + if (timer.timer_cycles & 7) continue; break; case 2: // o / 32 - if (timer_cycles & 31) + if (timer.timer_cycles & 31) continue; break; case 3: // ext (o / 2) - if (mcu_mk1) + if (timer.mcu->mcu_mk1) { - if (timer_cycles & 3) + if (timer.timer_cycles & 3) continue; } else { - if (timer_cycles & 1) + if (timer.timer_cycles & 1) continue; } break; } - uint32_t value = timer->frc; - uint32_t matcha = value == timer->ocra; - uint32_t matchb = value == timer->ocrb; - if ((timer->tcsr & 1) != 0 && matcha) // CCLRA + uint32_t value = ftimer->frc; + uint32_t matcha = value == ftimer->ocra; + uint32_t matchb = value == ftimer->ocrb; + if ((ftimer->tcsr & 1) != 0 && matcha) // CCLRA value = 0; else value++; uint32_t of = (value >> 16) & 1; value &= 0xffff; - timer->frc = value; + ftimer->frc = value; // flags if (of) - timer->tcsr |= 0x10; + ftimer->tcsr |= 0x10; if (matcha) - timer->tcsr |= 0x20; + ftimer->tcsr |= 0x20; if (matchb) - timer->tcsr |= 0x40; - if ((timer->tcr & 0x10) != 0 && (timer->tcsr & 0x10) != 0) - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_FRT0_FOVI + i * 4, 1); - if ((timer->tcr & 0x20) != 0 && (timer->tcsr & 0x20) != 0) - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_FRT0_OCIA + i * 4, 1); - if ((timer->tcr & 0x40) != 0 && (timer->tcsr & 0x40) != 0) - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_FRT0_OCIB + i * 4, 1); + ftimer->tcsr |= 0x40; + if ((ftimer->tcr & 0x10) != 0 && (ftimer->tcsr & 0x10) != 0) + MCU_Interrupt_SetRequest(*timer.mcu, INTERRUPT_SOURCE_FRT0_FOVI + i * 4, 1); + if ((ftimer->tcr & 0x20) != 0 && (ftimer->tcsr & 0x20) != 0) + MCU_Interrupt_SetRequest(*timer.mcu, INTERRUPT_SOURCE_FRT0_OCIA + i * 4, 1); + if ((ftimer->tcr & 0x40) != 0 && (ftimer->tcsr & 0x40) != 0) + MCU_Interrupt_SetRequest(*timer.mcu, INTERRUPT_SOURCE_FRT0_OCIB + i * 4, 1); } int32_t timer_step = 0; @@ -291,28 +283,28 @@ void TIMER_Clock(uint64_t cycles) case 4: break; case 1: // o / 8 - if ((timer_cycles & 7) == 0) + if ((timer.timer_cycles & 7) == 0) timer_step = 1; break; case 2: // o / 64 - if ((timer_cycles & 63) == 0) + if ((timer.timer_cycles & 63) == 0) timer_step = 1; break; case 3: // o / 1024 - if ((timer_cycles & 1023) == 0) + if ((timer.timer_cycles & 1023) == 0) timer_step = 1; break; case 5: case 6: case 7: // ext (o / 2) - if (mcu_mk1) + if (timer.mcu->mcu_mk1) { - if ((timer_cycles & 3) == 0) + if ((timer.timer_cycles & 3) == 0) timer_step = 1; } else { - if ((timer_cycles & 1) == 0) + if ((timer.timer_cycles & 1) == 0) timer_step = 1; } break; @@ -340,13 +332,13 @@ void TIMER_Clock(uint64_t cycles) if (matchb) timer.tcsr |= 0x80; if ((timer.tcr & 0x20) != 0 && (timer.tcsr & 0x20) != 0) - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_TIMER_OVI, 1); + MCU_Interrupt_SetRequest(*timer.mcu, INTERRUPT_SOURCE_TIMER_OVI, 1); if ((timer.tcr & 0x40) != 0 && (timer.tcsr & 0x40) != 0) - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_TIMER_CMIA, 1); + MCU_Interrupt_SetRequest(*timer.mcu, INTERRUPT_SOURCE_TIMER_CMIA, 1); if ((timer.tcr & 0x80) != 0 && (timer.tcsr & 0x80) != 0) - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_TIMER_CMIB, 1); + MCU_Interrupt_SetRequest(*timer.mcu, INTERRUPT_SOURCE_TIMER_CMIB, 1); } - timer_cycles++; + timer.timer_cycles++; } } diff --git a/src/mcu_timer.h b/src/mcu_timer.h index 41e0eb1d..9a76f340 100644 --- a/src/mcu_timer.h +++ b/src/mcu_timer.h @@ -34,6 +34,8 @@ #pragma once #include +struct mcu_t; + struct frt_t { uint8_t tcr; uint8_t tcsr; @@ -51,12 +53,20 @@ struct mcu_timer_t { uint8_t tcorb; uint8_t tcnt; uint8_t status_rd; + + mcu_t* mcu; + + uint64_t timer_cycles; + uint8_t timer_tempreg; + + frt_t frt[3]; }; -void TIMER_Write(uint32_t address, uint8_t data); -uint8_t TIMER_Read(uint32_t address); -void TIMER_Clock(uint64_t cycles); +void TIMER_Init(mcu_timer_t& timer, mcu_t& mcu); +void TIMER_Write(mcu_timer_t& timer, uint32_t address, uint8_t data); +uint8_t TIMER_Read(mcu_timer_t& timer, uint32_t address); +void TIMER_Clock(mcu_timer_t& timer, uint64_t cycles); -void TIMER2_Write(uint32_t address, uint8_t data); -uint8_t TIMER_Read2(uint32_t address); +void TIMER2_Write(mcu_timer_t& timer, uint32_t address, uint8_t data); +uint8_t TIMER_Read2(mcu_timer_t& timer, uint32_t address); diff --git a/src/midi.h b/src/midi.h index 94366205..da7f68d1 100644 --- a/src/midi.h +++ b/src/midi.h @@ -33,6 +33,8 @@ */ #pragma once -int MIDI_Init(int port); +struct frontend_t; + +int MIDI_Init(frontend_t& fe, int port); void MIDI_Quit(void); diff --git a/src/midi_rtmidi.cpp b/src/midi_rtmidi.cpp index d16036bc..757b2703 100644 --- a/src/midi_rtmidi.cpp +++ b/src/midi_rtmidi.cpp @@ -1,18 +1,20 @@ #include #include "mcu.h" +#include "emu.h" #include "midi.h" #include static RtMidiIn *s_midi_in = nullptr; +static frontend_t* midi_frontend = nullptr; + +void FE_RouteMIDI(frontend_t& fe, uint8_t* first, uint8_t* last); static void MidiOnReceive(double, std::vector *message, void *) { uint8_t *beg = message->data(); uint8_t *end = message->data() + message->size(); - - while(beg < end) - MCU_PostUART(*beg++); + FE_RouteMIDI(*midi_frontend, beg, end); } static void MidiOnError(RtMidiError::Type, const std::string &errorText, void *) @@ -21,7 +23,7 @@ static void MidiOnError(RtMidiError::Type, const std::string &errorText, void *) fflush(stderr); } -int MIDI_Init(int port) +int MIDI_Init(frontend_t& frontend, int port) { if (s_midi_in) { @@ -29,6 +31,8 @@ int MIDI_Init(int port) return 0; // Already running } + midi_frontend = &frontend; + s_midi_in = new RtMidiIn(RtMidi::UNSPECIFIED, "Nuked SC55", 1024); s_midi_in->ignoreTypes(false, false, false); // SysEx disabled by default s_midi_in->setCallback(&MidiOnReceive, nullptr); // FIXME: (local bug) Fix the linking error @@ -62,5 +66,6 @@ void MIDI_Quit() s_midi_in->closePort(); delete s_midi_in; s_midi_in = nullptr; + midi_frontend = nullptr; } } diff --git a/src/midi_win32.cpp b/src/midi_win32.cpp index c453aea1..21e2c0ad 100644 --- a/src/midi_win32.cpp +++ b/src/midi_win32.cpp @@ -43,6 +43,10 @@ static MIDIHDR midi_buffer; static char midi_in_buffer[1024]; +static frontend_t* midi_frontend = nullptr; + +void FE_RouteMIDI(frontend_t& fe, uint8_t* first, uint8_t* last); + void CALLBACK MIDI_Callback( HMIDIIN hMidiIn, UINT wMsg, @@ -65,14 +69,24 @@ void CALLBACK MIDI_Callback( case 0xa0: case 0xb0: case 0xe0: - MCU_PostUART(b1); - MCU_PostUART((dwParam1 >> 8) & 0xff); - MCU_PostUART((dwParam1 >> 16) & 0xff); + { + uint8_t buf[3] = { + (uint8_t)b1, + (uint8_t)((dwParam1 >> 8) & 0xff), + (uint8_t)((dwParam1 >> 16) & 0xff), + }; + FE_RouteMIDI(*midi_frontend, (uint8_t*)buf, (uint8_t*)buf + sizeof(buf)); + } break; case 0xc0: case 0xd0: - MCU_PostUART(b1); - MCU_PostUART((dwParam1 >> 8) & 0xff); + { + uint8_t buf[2] = { + (uint8_t)b1, + (uint8_t)((dwParam1 >> 8) & 0xff), + }; + FE_RouteMIDI(*midi_frontend, (uint8_t*)buf, (uint8_t*)buf + sizeof(buf)); + } break; } break; @@ -80,14 +94,23 @@ void CALLBACK MIDI_Callback( case MIM_LONGDATA: case MIM_LONGERROR: { - midiInUnprepareHeader(midi_handle, &midi_buffer, sizeof(MIDIHDR)); + MMRESULT result = midiInUnprepareHeader(midi_handle, &midi_buffer, sizeof(MIDIHDR)); + if (result == MMSYSERR_INVALHANDLE) + { + // If this happens, the frontend probably called MIDI_Quit and + // midi_frontend is no longer valid. We got here because this + // callback is running in a separate thread and might be called + // after MIDI_Quit. + break; + } if (wMsg == MIM_LONGDATA) { - for (int i = 0; i < midi_buffer.dwBytesRecorded; i++) - { - MCU_PostUART(midi_in_buffer[i]); - } + FE_RouteMIDI( + *midi_frontend, + (uint8_t*)midi_in_buffer, + (uint8_t*)midi_in_buffer + midi_buffer.dwBytesRecorded + ); } midiInPrepareHeader(midi_handle, &midi_buffer, sizeof(MIDIHDR)); @@ -101,8 +124,10 @@ void CALLBACK MIDI_Callback( } } -int MIDI_Init(int port) +int MIDI_Init(frontend_t& frontend, int port) { + midi_frontend = &frontend; + int num = midiInGetNumDevs(); if (num == 0) @@ -149,4 +174,5 @@ void MIDI_Quit() midiInClose(midi_handle); midi_handle = 0; } + midi_frontend = nullptr; } diff --git a/src/pcm.cpp b/src/pcm.cpp index cb05f90a..ac0f0500 100644 --- a/src/pcm.cpp +++ b/src/pcm.cpp @@ -38,13 +38,7 @@ #include "mcu_interrupt.h" #include "pcm.h" -pcm_t pcm; -uint8_t waverom1[0x200000]; -uint8_t waverom2[0x200000]; -uint8_t waverom3[0x100000]; -uint8_t waverom_exp[0x800000]; - -uint8_t PCM_ReadROM(uint32_t address) +uint8_t PCM_ReadROM(pcm_t& pcm, uint32_t address) { int bank; if (pcm.config_reg_3d & 0x20) @@ -54,31 +48,31 @@ uint8_t PCM_ReadROM(uint32_t address) switch (bank) { case 0: - if (mcu_mk1) - return waverom1[address & 0xfffff]; + if (pcm.mcu->mcu_mk1) + return pcm.waverom1[address & 0xfffff]; else - return waverom1[address & 0x1fffff]; + return pcm.waverom1[address & 0x1fffff]; case 1: - if (!mcu_jv880) - return waverom2[address & 0xfffff]; + if (!pcm.mcu->mcu_jv880) + return pcm.waverom2[address & 0xfffff]; else - return waverom2[address & 0x1fffff]; + return pcm.waverom2[address & 0x1fffff]; case 2: - if (mcu_jv880) return 0; - return waverom3[address & 0xfffff]; + if (pcm.mcu->mcu_jv880) return 0; + return pcm.waverom3[address & 0xfffff]; case 3: case 4: case 5: case 6: - if (mcu_jv880) - return waverom_exp[(address & 0x1fffff) + (bank - 3) * 0x200000]; + if (pcm.mcu->mcu_jv880) + return pcm.waverom_exp[(address & 0x1fffff) + (bank - 3) * 0x200000]; default: break; } return 0; } -void PCM_Write(uint32_t address, uint8_t data) +void PCM_Write(pcm_t& pcm, uint32_t address, uint8_t data) { address &= 0x3f; if (address < 0x4) // voice enable @@ -119,7 +113,7 @@ void PCM_Write(uint32_t address, uint8_t data) case 3: pcm.wave_read_address &= ~0xff; pcm.wave_read_address |= (data & 0xff) << 0; - pcm.wave_byte_latch = PCM_ReadROM(pcm.wave_read_address); + pcm.wave_byte_latch = PCM_ReadROM(pcm, pcm.wave_read_address); break; } } @@ -192,7 +186,7 @@ void PCM_Write(uint32_t address, uint8_t data) // rv: [30][2], [30][3] // ch: [31][2], [31][5] -uint8_t PCM_Read(uint32_t address) +uint8_t PCM_Read(pcm_t& pcm, uint32_t address) { address &= 0x3f; //printf("PCM Read: %.2x\n", address); @@ -209,10 +203,10 @@ uint8_t PCM_Read(uint32_t address) if (address == 0x3e && pcm.irq_assert) { pcm.irq_assert = 0; - if (mcu_jv880) - MCU_GA_SetGAInt(5, 0); + if (pcm.mcu->mcu_jv880) + MCU_GA_SetGAInt(*pcm.mcu, 5, 0); else - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_IRQ0, 0); + MCU_Interrupt_SetRequest(*pcm.mcu, INTERRUPT_SOURCE_IRQ0, 0); } status |= pcm.irq_channel; @@ -267,9 +261,10 @@ uint8_t PCM_Read(uint32_t address) return 0; } -void PCM_Reset(void) +void PCM_Init(pcm_t& pcm, mcu_t& mcu) { memset(&pcm, 0, sizeof(pcm)); + pcm.mcu = &mcu; } inline uint32_t addclip20(uint32_t add1, uint32_t add2, uint32_t cin) @@ -326,7 +321,7 @@ static const int interp_lut[3][128] = { 484, 497, 510, 523, 536, 549, 563, 577, 591, 605, 619, 634, 648, 663, 679, 694, }; -inline void calc_tv(int e, int adjust, uint16_t *levelcur, int active, int *volmul) +inline void calc_tv(pcm_t& pcm, int e, int adjust, uint16_t *levelcur, int active, int *volmul) { // int adjust = ram2[3+e]; // int levelcur = ram2[9+e] & 0x7fff; @@ -490,7 +485,7 @@ inline void calc_tv(int e, int adjust, uint16_t *levelcur, int active, int *volm } } -inline int eram_unpack(int addr, int type = 0) +inline int eram_unpack(pcm_t& pcm, int addr, int type = 0) { addr &= 0x3fff; int data = pcm.eram[addr]; @@ -501,7 +496,7 @@ inline int eram_unpack(int addr, int type = 0) return val >> (18 - sh * 2 + type); } -inline void eram_pack(int addr, int val) +inline void eram_pack(pcm_t& pcm, int addr, int val) { addr &= 0x3fff; int sh = 0; @@ -522,7 +517,7 @@ inline void eram_pack(int addr, int val) pcm.eram[addr] = data; } -void PCM_Update(uint64_t cycles) +void PCM_Update(pcm_t& pcm, uint64_t cycles) { int reg_slots = (pcm.config_reg_3d & 31) + 1; int voice_active = pcm.voice_mask & pcm.voice_mask_pending; @@ -611,7 +606,7 @@ void PCM_Update(uint64_t cycles) tt[0] = (int)((pcm.ram1[30][2] & ~write_mask) << 12); tt[1] = (int)((pcm.ram1[30][4] & ~write_mask) << 12); - MCU_PostSample(tt); + MCU_PostSample(*pcm.mcu, tt); xr = ((shifter >> 0) ^ (shifter >> 1) ^ (shifter >> 7) ^ (shifter >> 12)) & 1; shifter = (shifter >> 1) | (xr << 15); @@ -636,7 +631,7 @@ void PCM_Update(uint64_t cycles) tt[0] = (int)((pcm.ram1[30][3] & ~write_mask) << 12); tt[1] = (int)((pcm.ram1[30][5] & ~write_mask) << 12); - MCU_PostSample(tt); + MCU_PostSample(*pcm.mcu, tt); } } @@ -677,7 +672,7 @@ void PCM_Update(uint64_t cycles) int key = 1; int active = okey && key; int u = 0; - calc_tv(1, pcm.ram2[30][0], &pcm.ram2[30][9], active, &u); + calc_tv(pcm, 1, pcm.ram2[30][0], &pcm.ram2[30][9], active, &u); } { @@ -697,8 +692,8 @@ void PCM_Update(uint64_t cycles) int v1 = pcm.ram2[30][4]; int m1 = multi(pcm.ram1[29][0], (v1 >> 8)) >> 6; int v2 = 0; - int s1 = eram_unpack(pcm.ram2[28][1] + pcm.tv_counter, 1); - int s2 = eram_unpack(pcm.ram2[28][1] + pcm.tv_counter); + int s1 = eram_unpack(pcm, pcm.ram2[28][1] + pcm.tv_counter, 1); + int s2 = eram_unpack(pcm, pcm.ram2[28][1] + pcm.tv_counter); if ((v1 & 0x30) != 0) { v2 = s1; @@ -712,8 +707,8 @@ void PCM_Update(uint64_t cycles) // 2 int v1 = pcm.ram2[30][4]; int v2 = 0; - int s1 = eram_unpack(pcm.ram2[28][2] + pcm.tv_counter, 1); - int s2 = eram_unpack(pcm.ram2[28][2] + pcm.tv_counter); + int s1 = eram_unpack(pcm, pcm.ram2[28][2] + pcm.tv_counter, 1); + int s2 = eram_unpack(pcm, pcm.ram2[28][2] + pcm.tv_counter); if ((v1 & 0x30) != 0) { v2 = s1; @@ -727,8 +722,8 @@ void PCM_Update(uint64_t cycles) // 3 int v1 = pcm.ram2[30][4]; int v2 = 0; - int s1 = eram_unpack(pcm.ram2[28][3] + pcm.tv_counter, 1); - int s2 = eram_unpack(pcm.ram2[28][3] + pcm.tv_counter); + int s1 = eram_unpack(pcm, pcm.ram2[28][3] + pcm.tv_counter, 1); + int s2 = eram_unpack(pcm, pcm.ram2[28][3] + pcm.tv_counter); if ((v1 & 0x30) != 0) { v2 = s1; @@ -739,14 +734,14 @@ void PCM_Update(uint64_t cycles) pcm.ram1[28][1] = addclip20(m2 >> 1, s2, m2 & 1); - pcm.ram1[28][2] = eram_unpack(pcm.ram2[28][5] + pcm.tv_counter); + pcm.ram1[28][2] = eram_unpack(pcm, pcm.ram2[28][5] + pcm.tv_counter); } { // 4 int v1 = pcm.ram2[30][5]; int v2 = 0; - int s1 = eram_unpack(pcm.ram2[28][4] + pcm.tv_counter, 1); - int s2 = eram_unpack(pcm.ram2[28][4] + pcm.tv_counter); + int s1 = eram_unpack(pcm, pcm.ram2[28][4] + pcm.tv_counter, 1); + int s2 = eram_unpack(pcm, pcm.ram2[28][4] + pcm.tv_counter); if ((v1 & 0x30) != 0) { v2 = s1; @@ -757,31 +752,31 @@ void PCM_Update(uint64_t cycles) pcm.ram1[28][3] = addclip20(m2 >> 1, s2, m2 & 1); - pcm.ram1[28][4] = eram_unpack(pcm.ram2[29][1] + pcm.tv_counter); + pcm.ram1[28][4] = eram_unpack(pcm, pcm.ram2[29][1] + pcm.tv_counter); } { // 5 int v1 = pcm.ram2[30][7]; int m1 = multi(pcm.ram1[29][2], (v1 >> 8)) >> 5; - int s1 = eram_unpack(pcm.ram2[29][0] + pcm.tv_counter); + int s1 = eram_unpack(pcm, pcm.ram2[29][0] + pcm.tv_counter); int m2 = multi(s1, v1 & 255) >> 5; pcm.ram1[29][2] = addclip20(m1 >> 1, m2 >> 1, (m1 | m2) & 1); - eram_pack(pcm.ram2[28][0] + pcm.tv_counter, pcm.ram1[29][4]); + eram_pack(pcm, pcm.ram2[28][0] + pcm.tv_counter, pcm.ram1[29][4]); } { // 6 int v1 = pcm.ram2[30][8]; int m1 = multi(pcm.ram1[29][3], (v1 >> 8)) >> 5; - int s1 = eram_unpack(pcm.ram2[29][8] + pcm.tv_counter); + int s1 = eram_unpack(pcm, pcm.ram2[29][8] + pcm.tv_counter); int m2 = multi(s1, v1 & 255) >> 5; pcm.ram1[29][3] = addclip20(m1 >> 1, m2 >> 1, (m1 | m2) & 1); - eram_pack(pcm.ram2[28][1] + pcm.tv_counter, pcm.ram1[29][5]); + eram_pack(pcm, pcm.ram2[28][1] + pcm.tv_counter, pcm.ram1[29][5]); - eram_pack(pcm.ram2[28][2] + pcm.tv_counter, pcm.ram1[28][0]); + eram_pack(pcm, pcm.ram2[28][2] + pcm.tv_counter, pcm.ram1[28][0]); } { // 7 @@ -793,7 +788,7 @@ void PCM_Update(uint64_t cycles) pcm.ram1[28][3] = addclip20(v2, m1 >> 1, m1 & 1); pcm.ram1[28][5] = addclip20(v2, m2 >> 1, m2 & 1); - eram_pack(pcm.ram2[28][3] + pcm.tv_counter, pcm.ram1[28][1]); + eram_pack(pcm, pcm.ram2[28][3] + pcm.tv_counter, pcm.ram1[28][1]); } { // 8 @@ -807,7 +802,7 @@ void PCM_Update(uint64_t cycles) pcm.ram1[28][2] = addclip20(pcm.ram1[28][2], m2 >> 1, m2 & 1); - pcm.ram1[28][1] = eram_unpack(pcm.ram2[28][9] + pcm.tv_counter); + pcm.ram1[28][1] = eram_unpack(pcm, pcm.ram2[28][9] + pcm.tv_counter); } { // 9 @@ -821,7 +816,7 @@ void PCM_Update(uint64_t cycles) pcm.ram1[28][4] = addclip20(pcm.ram1[28][4], m2 >> 1, m2 & 1); - pcm.ram1[29][4] = eram_unpack(pcm.ram2[29][5] + pcm.tv_counter); + pcm.ram1[29][4] = eram_unpack(pcm, pcm.ram2[29][5] + pcm.tv_counter); } { // 10 @@ -829,13 +824,13 @@ void PCM_Update(uint64_t cycles) int v1 = pcm.ram2[30][6]; int v2 = pcm.ram1[28][1]; int m1 = multi(v2, v1 >> 8) >> 5; - int s1 = eram_unpack(pcm.ram2[28][8] + pcm.tv_counter); + int s1 = eram_unpack(pcm, pcm.ram2[28][8] + pcm.tv_counter); int v3 = addclip20(m1 >> 1, s1, m1 & 1); pcm.ram1[28][1] = v3; int m2 = multi(v3, v1 & 255) >> 5; pcm.ram1[29][5] = addclip20(m2 >> 1, v2, m2 & 1); - eram_pack(pcm.ram2[28][4] + pcm.tv_counter, pcm.ram1[28][3]); + eram_pack(pcm, pcm.ram2[28][4] + pcm.tv_counter, pcm.ram1[28][3]); } { // 11 @@ -843,63 +838,63 @@ void PCM_Update(uint64_t cycles) int v1 = pcm.ram2[30][6]; int v2 = pcm.ram1[29][4]; int m1 = multi(v2, v1 >> 8) >> 5; - int s1 = eram_unpack(pcm.ram2[29][4] + pcm.tv_counter); + int s1 = eram_unpack(pcm, pcm.ram2[29][4] + pcm.tv_counter); int v3 = addclip20(m1 >> 1, s1, m1 & 1); pcm.ram1[29][4] = v3; int m2 = multi(v3, v1 & 255) >> 5; pcm.ram1[28][0] = addclip20(m2 >> 1, v2, m2 & 1); - eram_pack(pcm.ram2[28][5] + pcm.tv_counter, pcm.ram1[28][2]); + eram_pack(pcm, pcm.ram2[28][5] + pcm.tv_counter, pcm.ram1[28][2]); - eram_pack(pcm.ram2[29][0] + pcm.tv_counter, pcm.ram1[28][5]); + eram_pack(pcm, pcm.ram2[29][0] + pcm.tv_counter, pcm.ram1[28][5]); } { // 12 - pcm.ram1[28][5] = eram_unpack(pcm.ram2[28][6] + pcm.tv_counter); + pcm.ram1[28][5] = eram_unpack(pcm, pcm.ram2[28][6] + pcm.tv_counter); } { // 13 - int s1 = eram_unpack(pcm.ram2[28][10] + pcm.tv_counter); + int s1 = eram_unpack(pcm, pcm.ram2[28][10] + pcm.tv_counter); pcm.ram1[28][5] = addclip20(pcm.ram1[28][5], s1, 0); - pcm.ram1[28][2] = eram_unpack(pcm.ram2[29][2] + pcm.tv_counter); + pcm.ram1[28][2] = eram_unpack(pcm, pcm.ram2[29][2] + pcm.tv_counter); } { // 14 - int s1 = eram_unpack(pcm.ram2[29][6] + pcm.tv_counter); + int s1 = eram_unpack(pcm, pcm.ram2[29][6] + pcm.tv_counter); int t1 = addclip20(s1, pcm.ram1[28][2], 0); // 6 pcm.ram1[28][5] = addclip20(t1, pcm.ram1[28][5], 0); - pcm.ram1[28][2] = eram_unpack(pcm.ram2[28][7] + pcm.tv_counter); + pcm.ram1[28][2] = eram_unpack(pcm, pcm.ram2[28][7] + pcm.tv_counter); } { // 15 - int s1 = eram_unpack(pcm.ram2[28][11] + pcm.tv_counter); + int s1 = eram_unpack(pcm, pcm.ram2[28][11] + pcm.tv_counter); pcm.ram1[28][2] = addclip20(pcm.ram1[28][2], s1, 0); - pcm.ram1[28][3] = eram_unpack(pcm.ram2[29][3] + pcm.tv_counter); + pcm.ram1[28][3] = eram_unpack(pcm, pcm.ram2[29][3] + pcm.tv_counter); } { // 16 - int s1 = eram_unpack(pcm.ram2[29][7] + pcm.tv_counter); + int s1 = eram_unpack(pcm, pcm.ram2[29][7] + pcm.tv_counter); int t1 = addclip20(s1, pcm.ram1[28][2], 0); pcm.ram1[28][2] = addclip20(t1, pcm.ram1[28][3], 0); - eram_pack(pcm.ram2[29][1] + pcm.tv_counter, pcm.ram1[28][4]); + eram_pack(pcm, pcm.ram2[29][1] + pcm.tv_counter, pcm.ram1[28][4]); - eram_pack(pcm.ram2[28][8] + pcm.tv_counter, pcm.ram1[28][1]); + eram_pack(pcm, pcm.ram2[28][8] + pcm.tv_counter, pcm.ram1[28][1]); } { @@ -913,8 +908,8 @@ void PCM_Update(uint64_t cycles) rcadd2[0] = multi(v2, v1 & 255) >> 5; - int t1 = eram_unpack(pcm.ram2[29][10] + pcm.tv_counter + 1); //? 3a6e - eram_pack(pcm.ram2[28][9] + pcm.tv_counter, pcm.ram1[29][5]); + int t1 = eram_unpack(pcm, pcm.ram2[29][10] + pcm.tv_counter + 1); //? 3a6e + eram_pack(pcm, pcm.ram2[28][9] + pcm.tv_counter, pcm.ram1[29][5]); pcm.ram1[29][5] = t1; } @@ -929,16 +924,16 @@ void PCM_Update(uint64_t cycles) rcadd2[1] = multi(v2, v1 & 255) >> 5; - pcm.ram1[28][1] = eram_unpack(pcm.ram2[29][11] + pcm.tv_counter + 1); //? 3a1e + pcm.ram1[28][1] = eram_unpack(pcm, pcm.ram2[29][11] + pcm.tv_counter + 1); //? 3a1e } { // 19 int v1 = pcm.ram2[31][9]; - int s1 = eram_unpack(pcm.ram2[29][10] + pcm.tv_counter); //? 3a6d + int s1 = eram_unpack(pcm, pcm.ram2[29][10] + pcm.tv_counter); //? 3a6d - eram_pack(pcm.ram2[29][4] + pcm.tv_counter, pcm.ram1[29][4]); + eram_pack(pcm, pcm.ram2[29][4] + pcm.tv_counter, pcm.ram1[29][4]); int m1 = multi(s1, v1 >> 8) >> 5; int m2 = multi(pcm.ram1[29][5], v1 >> 8) >> 5; @@ -952,9 +947,9 @@ void PCM_Update(uint64_t cycles) int v1 = pcm.ram2[31][10]; - int s1 = eram_unpack(pcm.ram2[29][11] + pcm.tv_counter); //? 3a1d + int s1 = eram_unpack(pcm, pcm.ram2[29][11] + pcm.tv_counter); //? 3a1d - eram_pack(pcm.ram2[29][5] + pcm.tv_counter, pcm.ram1[28][0]); + eram_pack(pcm, pcm.ram2[29][5] + pcm.tv_counter, pcm.ram1[28][0]); int m1 = multi(s1, v1 >> 8) >> 5; int m2 = multi(pcm.ram1[28][1], v1 >> 8) >> 5; @@ -963,7 +958,7 @@ void PCM_Update(uint64_t cycles) pcm.ram1[28][1] = addclip20(t2, m2 >> 1, m2 & 1); - eram_pack(pcm.ram2[29][9] + pcm.tv_counter, pcm.ram1[29][1]); + eram_pack(pcm, pcm.ram2[29][9] + pcm.tv_counter, pcm.ram1[29][1]); } { // 21 @@ -1147,7 +1142,7 @@ void PCM_Update(uint64_t cycles) wave_address += nibble_add - nibble_subtract; wave_address &= 0xfffff; - int newnibble = PCM_ReadROM((hiaddr << 20) | wave_address); + int newnibble = PCM_ReadROM(pcm, (hiaddr << 20) | wave_address); int newnibble_sel = address_b4 ^ ((b6 || !nibble_cmp1) && okey); if (newnibble_sel) newnibble = (newnibble >> 4) & 15; @@ -1167,7 +1162,7 @@ void PCM_Update(uint64_t cycles) // address 0 int address_cnt = address; - int samp0 = (int8_t)PCM_ReadROM((hiaddr << 20) | address_cnt); // 18 + int samp0 = (int8_t)PCM_ReadROM(pcm, (hiaddr << 20) | address_cnt); // 18 cmp1 = address; cmp2 = address_cnt; @@ -1193,7 +1188,7 @@ void PCM_Update(uint64_t cycles) address_cnt = address_cnt2 & 0xfffff; // 11 b15 = b6 && (b15 ^ address_cmp); // 11 - int samp1 = (int8_t)PCM_ReadROM((hiaddr << 20) | address_cnt); // 20 + int samp1 = (int8_t)PCM_ReadROM(pcm, (hiaddr << 20) | address_cnt); // 20 cmp1 = address; cmp2 = address_cnt; @@ -1222,7 +1217,7 @@ void PCM_Update(uint64_t cycles) address_cnt = address_cnt2 & 0xfffff; // 15 b15 = b6 && (b15 ^ address_cmp); // 15 - int samp2 = (int8_t)PCM_ReadROM((hiaddr << 20) | address_cnt); // 1 + int samp2 = (int8_t)PCM_ReadROM(pcm, (hiaddr << 20) | address_cnt); // 1 cmp1 = address; cmp2 = address_cnt; @@ -1251,7 +1246,7 @@ void PCM_Update(uint64_t cycles) address_cnt = address_cnt2 & 0xfffff; // 19 b15 = b6 && (b15 ^ address_cmp); // 19 - int samp3 = (int8_t)PCM_ReadROM((hiaddr << 20) | address_cnt); // 5 + int samp3 = (int8_t)PCM_ReadROM(pcm, (hiaddr << 20) | address_cnt); // 5 cmp1 = address; cmp2 = address_cnt; @@ -1375,7 +1370,7 @@ void PCM_Update(uint64_t cycles) int filter = ram2[11]; int v3; - if (mcu_mk1) + if (pcm.mcu->mcu_mk1) { int mult1 = multi(reg1, filter >> 8); // 8 int mult2 = multi(reg1, (filter >> 1) & 127); // 9 @@ -1433,18 +1428,18 @@ void PCM_Update(uint64_t cycles) ram2[8] |= 0x4000; pcm.irq_assert = 1; pcm.irq_channel = slot; - if (mcu_jv880) - MCU_GA_SetGAInt(5, 1); + if (pcm.mcu->mcu_jv880) + MCU_GA_SetGAInt(*pcm.mcu, 5, 1); else - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_IRQ0, 1); + MCU_Interrupt_SetRequest(*pcm.mcu, INTERRUPT_SOURCE_IRQ0, 1); } int volmul1 = 0; int volmul2 = 0; - calc_tv(0, ram2[3], &ram2[9], active, &volmul1); - calc_tv(1, ram2[4], &ram2[10], active, &volmul2); - calc_tv(2, ram2[5], &ram2[11], active, NULL); + calc_tv(pcm, 0, ram2[3], &ram2[9], active, &volmul1); + calc_tv(pcm, 1, ram2[4], &ram2[10], active, &volmul2); + calc_tv(pcm, 2, ram2[5], &ram2[11], active, NULL); // if (volmul1 && volmul2) // volmul1 += 0; @@ -1569,6 +1564,6 @@ void PCM_Update(uint64_t cycles) int cycles = (reg_slots + 1) * 25; - pcm.cycles += mcu_jv880 ? (cycles * 25) / 29 : cycles; + pcm.cycles += pcm.mcu->mcu_jv880 ? (cycles * 25) / 29 : cycles; } } diff --git a/src/pcm.h b/src/pcm.h index 0e53da83..ad894732 100644 --- a/src/pcm.h +++ b/src/pcm.h @@ -34,6 +34,8 @@ #pragma once #include +struct mcu_t; + struct pcm_t { uint32_t ram1[32][8]; uint16_t ram2[32][16]; @@ -61,15 +63,16 @@ struct pcm_t { int accum_l; int accum_r; int rcsum[2]; -}; -extern pcm_t pcm; -extern uint8_t waverom1[]; -extern uint8_t waverom2[]; -extern uint8_t waverom3[]; -extern uint8_t waverom_exp[]; + mcu_t* mcu; + + uint8_t waverom1[0x200000]; + uint8_t waverom2[0x200000]; + uint8_t waverom3[0x100000]; + uint8_t waverom_exp[0x800000]; +}; -void PCM_Write(uint32_t address, uint8_t data); -uint8_t PCM_Read(uint32_t address); -void PCM_Reset(void); -void PCM_Update(uint64_t cycles); +void PCM_Write(pcm_t& pcm, uint32_t address, uint8_t data); +uint8_t PCM_Read(pcm_t& pcm, uint32_t address); +void PCM_Init(pcm_t& pcm, mcu_t& mcu); +void PCM_Update(pcm_t& pcm, uint64_t cycles); diff --git a/src/ringbuffer.h b/src/ringbuffer.h new file mode 100644 index 00000000..a51b9beb --- /dev/null +++ b/src/ringbuffer.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2021, 2024 nukeykt + * + * Redistribution and use of this code or any derivative works are permitted + * provided that the following conditions are met: + * + * - Redistributions may not be sold, nor may they be used in a commercial + * product or activity. + * + * - Redistributions that are modified from the original source must include the + * complete source code, including the source code for all components used by a + * binary built from the modified sources. However, as a special exception, the + * source code distributed need not include anything that is normally distributed + * (in either source or binary form) with the major components (compiler, kernel, + * and so on) of the operating system on which the executable runs, unless that + * component itself accompanies the executable. + * + * - Redistributions must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#pragma once + +#include +#include +#include +#include "math_util.h" + +struct audio_frame_t { + int16_t left; + int16_t right; +}; + +struct ringbuffer_t { + audio_frame_t* frames; + size_t frame_count; + size_t read_head; + size_t write_head; + bool oversampling; +}; + +inline bool RB_Init(ringbuffer_t& rb, size_t frame_count) +{ + rb.frames = (audio_frame_t*)calloc(frame_count, sizeof(audio_frame_t)); + if (!rb.frames) + { + return false; + } + rb.frame_count = frame_count; + rb.read_head = 0; + rb.write_head = 0; + rb.oversampling = false; + return true; +} + +inline void RB_Free(ringbuffer_t& rb) +{ + free(rb.frames); +} + +inline void RB_SetOversamplingEnabled(ringbuffer_t& rb, bool enabled) +{ + rb.oversampling = enabled; + if (rb.oversampling) + { + rb.write_head &= ~1; + } +} + +inline bool RB_IsFull(ringbuffer_t& rb) +{ + if (rb.oversampling) + { + return ((rb.write_head + 2) % rb.frame_count) == rb.read_head; + } + else + { + return ((rb.write_head + 1) % rb.frame_count) == rb.read_head; + } +} + +inline void RB_Write(ringbuffer_t& rb, const audio_frame_t& frame) +{ + rb.frames[rb.write_head] = frame; + rb.write_head = (rb.write_head + 1) % rb.frame_count; +} + +inline size_t RB_ReadableFrameCount(ringbuffer_t& rb) +{ + if (rb.read_head <= rb.write_head) + { + return rb.write_head - rb.read_head; + } + else + { + return rb.frame_count - (rb.read_head - rb.write_head); + } +} + +// Reads up to `frame_count` frames and returns the number of frames actually +// read. +inline size_t RB_Read(ringbuffer_t& rb, audio_frame_t* dest, size_t frame_count) +{ + const size_t have_count = RB_ReadableFrameCount(rb); + const size_t read_count = min(have_count, frame_count); + size_t read_head = rb.read_head; + // TODO make this one or two memcpys + for (size_t i = 0; i < read_count; ++i) + { + *dest = rb.frames[read_head]; + ++dest; + read_head = (read_head + 1) % rb.frame_count; + } + rb.read_head = read_head; + return read_count; +} + +// Reads up to `frame_count` frames and returns the number of frames actually +// read. Mixes samples into dest by adding and clipping. +inline size_t RB_ReadMix(ringbuffer_t& rb, audio_frame_t* dest, size_t frame_count) +{ + const size_t have_count = RB_ReadableFrameCount(rb); + const size_t read_count = min(have_count, frame_count); + size_t read_head = rb.read_head; + for (size_t i = 0; i < read_count; ++i) + { + dest[i].left = saturating_add(dest[i].left, rb.frames[read_head].left); + dest[i].right = saturating_add(dest[i].right, rb.frames[read_head].right); + read_head = (read_head + 1) % rb.frame_count; + } + rb.read_head = read_head; + return read_count; +} + diff --git a/src/submcu.cpp b/src/submcu.cpp index 557b18e7..e26350e4 100644 --- a/src/submcu.cpp +++ b/src/submcu.cpp @@ -78,46 +78,25 @@ enum { SM_DEV_TIMER_CTRL = 0x1f }; -uint8_t sm_rom[4096]; -uint8_t sm_ram[128]; -uint8_t sm_shared_ram[192]; -uint8_t sm_access[0x18]; - -uint8_t sm_p0_dir; -uint8_t sm_p1_dir; - -uint8_t sm_device_mode[32]; -uint8_t sm_cts; - -uint64_t sm_timer_cycles; -uint8_t sm_timer_prescaler; -uint8_t sm_timer_counter; - -submcu_t sm; - -static uint8_t uart_rx_gotbyte; -static uint8_t uart_rx_byte; -static uint64_t uart_rx_delay; - -void SM_ErrorTrap(void) +void SM_ErrorTrap(submcu_t& sm) { printf("%.4x\n", sm.pc); } -uint8_t SM_Read(uint16_t address) +uint8_t SM_Read(submcu_t& sm, uint16_t address) { address &= 0x1fff; if (address & 0x1000) { - return sm_rom[address & 0xfff]; + return sm.sm_rom[address & 0xfff]; } else if (address < 0x80) { - return sm_ram[address]; + return sm.sm_ram[address]; } else if (address >= 0xc0 && address < 0xd8) { - return sm_access[address & 0x1f]; + return sm.sm_access[address & 0x1f]; } else if (address >= 0xe0 && address < 0x100) { @@ -126,8 +105,8 @@ uint8_t SM_Read(uint16_t address) { case SM_DEV_UART2_DATA: { - uart_rx_gotbyte = 0; - return uart_rx_byte; + sm.uart_rx_gotbyte = 0; + return sm.mcu->uart_rx_byte; } case SM_DEV_UART1_MODE_STATUS: { @@ -137,7 +116,7 @@ uint8_t SM_Read(uint16_t address) } case SM_DEV_UART2_MODE_STATUS: { - uint8_t ret = uart_rx_gotbyte << 1; + uint8_t ret = sm.uart_rx_gotbyte << 1; ret |= 5; return ret; } @@ -148,22 +127,22 @@ uint8_t SM_Read(uint16_t address) return ret; } case SM_DEV_P1_DATA: - return MCU_ReadP1(); + return MCU_ReadP1(*sm.mcu); case SM_DEV_P1_DIR: - return sm_p1_dir; + return sm.sm_p1_dir; case SM_DEV_PRESCALER: - return sm_timer_prescaler; + return sm.sm_timer_prescaler; case SM_DEV_TIMER: - return sm_timer_counter; + return sm.sm_timer_counter; } - return sm_device_mode[address]; + return sm.sm_device_mode[address]; } else if (address >= 0x200 && address < 0x2c0) { address &= 0xff; - if (sm_device_mode[SM_DEV_RAM_DIR] & (1<<(address>>5))) - sm_access[address>>3] &= ~(1<<(address&7)); - return sm_shared_ram[address]; + if (sm.sm_device_mode[SM_DEV_RAM_DIR] & (1<<(address>>5))) + sm.sm_access[address>>3] &= ~(1<<(address&7)); + return sm.sm_shared_ram[address]; } else { @@ -172,12 +151,12 @@ uint8_t SM_Read(uint16_t address) } } -void SM_Write(uint16_t address, uint8_t data) +void SM_Write(submcu_t& sm, uint16_t address, uint8_t data) { address &= 0x1fff; if (address < 0x80) { - sm_ram[address] = data; + sm.sm_ram[address] = data; } else if (address >= 0xe0 && address < 0x100) { @@ -185,45 +164,45 @@ void SM_Write(uint16_t address, uint8_t data) switch (address) { case SM_DEV_P1_DATA: - MCU_WriteP1(data); + MCU_WriteP1(*sm.mcu, data); break; case SM_DEV_P1_DIR: - sm_p1_dir = data; + sm.sm_p1_dir = data; break; case SM_DEV_IPCM0: case SM_DEV_IPCM1: case SM_DEV_IPCM2: case SM_DEV_IPCM3: - sm_device_mode[address] = data; + sm.sm_device_mode[address] = data; break; case SM_DEV_IPCE0: case SM_DEV_IPCE1: case SM_DEV_IPCE2: case SM_DEV_IPCE3: - sm_device_mode[address] = data; + sm.sm_device_mode[address] = data; break; case SM_DEV_INT_REQUEST: - sm_device_mode[SM_DEV_INT_REQUEST] &= data; + sm.sm_device_mode[SM_DEV_INT_REQUEST] &= data; break; case SM_DEV_COLLISION: - sm_device_mode[SM_DEV_COLLISION] &= ~0x7f; - sm_device_mode[SM_DEV_COLLISION] |= data & 0x7f; + sm.sm_device_mode[SM_DEV_COLLISION] &= ~0x7f; + sm.sm_device_mode[SM_DEV_COLLISION] |= data & 0x7f; if ((data & 0x80) == 0) - sm_device_mode[SM_DEV_COLLISION] &= ~0x80; + sm.sm_device_mode[SM_DEV_COLLISION] &= ~0x80; break; default: - sm_device_mode[address] = data; + sm.sm_device_mode[address] = data; break; } if (address == SM_DEV_UART3_MODE_STATUS || address == SM_DEV_UART3_CTRL) - MCU_GA_SetGAInt(5, (sm_device_mode[SM_DEV_UART3_MODE_STATUS] & 0x80) != 0 - && (sm_device_mode[SM_DEV_UART3_CTRL] & 0x20) == 0); + MCU_GA_SetGAInt(*sm.mcu, 5, (sm.sm_device_mode[SM_DEV_UART3_MODE_STATUS] & 0x80) != 0 + && (sm.sm_device_mode[SM_DEV_UART3_CTRL] & 0x20) == 0); } else if (address >= 0x200 && address < 0x2c0) { address &= 0xff; - sm_access[address>>3] |= 1<<(address&7); - sm_shared_ram[address] = data; + sm.sm_access[address>>3] |= 1<<(address&7); + sm.sm_shared_ram[address] = data; } else { @@ -231,40 +210,40 @@ void SM_Write(uint16_t address, uint8_t data) } } -void SM_SysWrite(uint32_t address, uint8_t data) +void SM_SysWrite(submcu_t& sm, uint32_t address, uint8_t data) { address &= 0xff; if (address < 0xc0) { address &= 0xff; - sm_access[address>>3] |= 1<<(address&7); - sm_shared_ram[address] = data; + sm.sm_access[address>>3] |= 1<<(address&7); + sm.sm_shared_ram[address] = data; } else if (address >= 0xf8 && address < 0xfc) { - sm_device_mode[SM_DEV_IPCM0 + (address & 3)] = data; + sm.sm_device_mode[SM_DEV_IPCM0 + (address & 3)] = data; if ((address & 3) == 0) { - sm_device_mode[SM_DEV_INT_REQUEST] |= 0x10; - sm_device_mode[SM_DEV_SEMAPHORE] &= ~0x80; + sm.sm_device_mode[SM_DEV_INT_REQUEST] |= 0x10; + sm.sm_device_mode[SM_DEV_SEMAPHORE] &= ~0x80; } } else if (address == 0xff) { - sm_device_mode[SM_DEV_SEMAPHORE] &= ~0x1f; - sm_device_mode[SM_DEV_SEMAPHORE] |= data & 0x1f; + sm.sm_device_mode[SM_DEV_SEMAPHORE] &= ~0x1f; + sm.sm_device_mode[SM_DEV_SEMAPHORE] |= data & 0x1f; } else if (address == 0xf5) { - MCU_WriteP1(data); + MCU_WriteP1(*sm.mcu, data); } else if (address == 0xf6) { - MCU_WriteP0(data); + MCU_WriteP0(*sm.mcu, data); } else if (address == 0xf7) { - sm_p0_dir = data; + sm.sm_p0_dir = data; } else { @@ -272,40 +251,40 @@ void SM_SysWrite(uint32_t address, uint8_t data) } } -uint8_t SM_SysRead(uint32_t address) +uint8_t SM_SysRead(submcu_t& sm, uint32_t address) { address &= 0xff; if (address < 0xc0) { - if ((sm_device_mode[SM_DEV_RAM_DIR] & (1<<(address>>5))) == 0) - sm_access[address>>3] &= ~(1<<(address&7)); - return sm_shared_ram[address]; + if ((sm.sm_device_mode[SM_DEV_RAM_DIR] & (1<<(address>>5))) == 0) + sm.sm_access[address>>3] &= ~(1<<(address&7)); + return sm.sm_shared_ram[address]; } else if (address >= 0xf8 && address < 0xfc) { if ((address & 3) == 0) { - sm_device_mode[SM_DEV_INT_REQUEST] |= 0x10; + sm.sm_device_mode[SM_DEV_INT_REQUEST] |= 0x10; } - uint8_t val = sm_device_mode[SM_DEV_IPCE0 + (address & 3)]; - sm_device_mode[SM_DEV_IPCE0 + (address & 3)] = 0; // FIXME + uint8_t val = sm.sm_device_mode[SM_DEV_IPCE0 + (address & 3)]; + sm.sm_device_mode[SM_DEV_IPCE0 + (address & 3)] = 0; // FIXME return val; } else if (address == 0xff) { - return sm_device_mode[SM_DEV_SEMAPHORE]; + return sm.sm_device_mode[SM_DEV_SEMAPHORE]; } else if (address == 0xf5) { - return MCU_ReadP1(); + return MCU_ReadP1(*sm.mcu); } else if (address == 0xf6) { - return MCU_ReadP0(); + return MCU_ReadP0(*sm.mcu); } else if (address == 0xf7) { - return sm_p0_dir; + return sm.sm_p0_dir; } else { @@ -314,14 +293,14 @@ uint8_t SM_SysRead(uint32_t address) } } -uint16_t SM_GetVectorAddress(uint32_t vector) +uint16_t SM_GetVectorAddress(submcu_t& sm, uint32_t vector) { - uint16_t pc = SM_Read(0x1fec + vector * 2); - pc |= SM_Read(0x1fec + vector * 2 + 1) << 8; + uint16_t pc = SM_Read(sm, 0x1fec + vector * 2); + pc |= SM_Read(sm, 0x1fec + vector * 2 + 1) << 8; return pc; } -void SM_SetStatus(uint32_t condition, uint32_t mask) +void SM_SetStatus(submcu_t& sm, uint32_t condition, uint32_t mask) { if (condition) sm.sr |= mask; @@ -329,176 +308,188 @@ void SM_SetStatus(uint32_t condition, uint32_t mask) sm.sr &= ~mask; } -void SM_Reset(void) +void SM_Init(submcu_t& sm, mcu_t& mcu) { - memset(&sm, 0, sizeof(sm)); - sm.pc = SM_GetVectorAddress(SM_VECTOR_RESET); + memset(&sm, 0, sizeof(submcu_t)); + sm.mcu = &mcu; } -uint8_t SM_ReadAdvance(void) +void SM_Reset(submcu_t& sm) { - uint8_t byte = SM_Read(sm.pc); + sm.pc = SM_GetVectorAddress(sm, SM_VECTOR_RESET); + sm.a = 0; + sm.x = 0; + sm.y = 0; + sm.s = 0; + sm.sr = 0; + sm.cycles = 0; + sm.sleep = 0; +} + +uint8_t SM_ReadAdvance(submcu_t& sm) +{ + uint8_t byte = SM_Read(sm, sm.pc); sm.pc++; return byte; } -uint16_t SM_ReadAdvance16(void) +uint16_t SM_ReadAdvance16(submcu_t& sm) { - uint16_t word = SM_ReadAdvance(); - word |= SM_ReadAdvance() << 8; + uint16_t word = SM_ReadAdvance(sm); + word |= SM_ReadAdvance(sm) << 8; return word; } -uint16_t SM_Read16(uint16_t address) +uint16_t SM_Read16(submcu_t& sm, uint16_t address) { - uint16_t word = SM_Read(address); - word |= SM_Read(address) << 8; + uint16_t word = SM_Read(sm, address); + word |= SM_Read(sm, address) << 8; return word; } -void SM_Update_NZ(uint8_t val) +void SM_Update_NZ(submcu_t& sm, uint8_t val) { - SM_SetStatus(val == 0, SM_STATUS_Z); - SM_SetStatus(val & 0x80, SM_STATUS_N); + SM_SetStatus(sm, val == 0, SM_STATUS_Z); + SM_SetStatus(sm, val & 0x80, SM_STATUS_N); } -void SM_PushStack(uint8_t data) +void SM_PushStack(submcu_t& sm, uint8_t data) { - SM_Write(sm.s, data); + SM_Write(sm, sm.s, data); sm.s--; } -uint8_t SM_PopStack(void) +uint8_t SM_PopStack(submcu_t& sm) { sm.s++; - return SM_Read(sm.s); + return SM_Read(sm, sm.s); } -void SM_Opcode_NotImplemented(uint8_t opcode) +void SM_Opcode_NotImplemented(submcu_t& sm, uint8_t opcode) { - SM_ErrorTrap(); + SM_ErrorTrap(sm); } -void SM_Opcode_SEI(uint8_t opcode) // 78 +void SM_Opcode_SEI(submcu_t& sm, uint8_t opcode) // 78 { - SM_SetStatus(1, SM_STATUS_I); + SM_SetStatus(sm, 1, SM_STATUS_I); } -void SM_Opcode_CLD(uint8_t opcode) // d8 +void SM_Opcode_CLD(submcu_t& sm, uint8_t opcode) // d8 { - SM_SetStatus(0, SM_STATUS_D); + SM_SetStatus(sm, 0, SM_STATUS_D); } -void SM_Opcode_CLT(uint8_t opcode) // 12 +void SM_Opcode_CLT(submcu_t& sm, uint8_t opcode) // 12 { - SM_SetStatus(0, SM_STATUS_T); + SM_SetStatus(sm, 0, SM_STATUS_T); } -void SM_Opcode_LDX(uint8_t opcode) // a2, a6, ae, b6, be +void SM_Opcode_LDX(submcu_t& sm, uint8_t opcode) // a2, a6, ae, b6, be { uint8_t val = 0; switch (opcode) { case 0xa2: - val = SM_ReadAdvance(); + val = SM_ReadAdvance(sm); break; case 0xa6: - val = SM_Read(SM_ReadAdvance()); + val = SM_Read(sm, SM_ReadAdvance(sm)); break; case 0xb6: - val = SM_Read((SM_ReadAdvance() + sm.y) & 0xff); + val = SM_Read(sm, (SM_ReadAdvance(sm) + sm.y) & 0xff); break; case 0xae: - val = SM_Read(SM_ReadAdvance16()); + val = SM_Read(sm, SM_ReadAdvance16(sm)); break; case 0xbe: - val = SM_Read(SM_ReadAdvance16() + sm.y); + val = SM_Read(sm, SM_ReadAdvance16(sm) + sm.y); break; } sm.x = val; - SM_Update_NZ(sm.x); + SM_Update_NZ(sm, sm.x); } -void SM_Opcode_LDY(uint8_t opcode) // a0, a4, ac, b4, bc +void SM_Opcode_LDY(submcu_t& sm, uint8_t opcode) // a0, a4, ac, b4, bc { uint8_t val = 0; switch (opcode) { case 0xa0: - val = SM_ReadAdvance(); + val = SM_ReadAdvance(sm); break; case 0xa4: - val = SM_Read(SM_ReadAdvance()); + val = SM_Read(sm, SM_ReadAdvance(sm)); break; case 0xac: - val = SM_Read(SM_ReadAdvance16()); + val = SM_Read(sm, SM_ReadAdvance16(sm)); break; case 0xb4: - val = SM_Read((SM_ReadAdvance() + sm.x) & 0xff); + val = SM_Read(sm, (SM_ReadAdvance(sm) + sm.x) & 0xff); break; case 0xbc: - val = SM_Read(SM_ReadAdvance16() + sm.x); + val = SM_Read(sm, SM_ReadAdvance16(sm) + sm.x); break; } sm.y = val; - SM_Update_NZ(sm.y); + SM_Update_NZ(sm, sm.y); } -void SM_Opcode_TXS(uint8_t opcode) // 9a +void SM_Opcode_TXS(submcu_t& sm, uint8_t opcode) // 9a { sm.s = sm.x; } -void SM_Opcode_TXA(uint8_t opcode) // 8a +void SM_Opcode_TXA(submcu_t& sm, uint8_t opcode) // 8a { sm.a = sm.x; - SM_Update_NZ(sm.a); + SM_Update_NZ(sm, sm.a); } -void SM_Opcode_STA(uint8_t opcode) // 85, 95, 8d, 9d, 99, 81, 91 +void SM_Opcode_STA(submcu_t& sm, uint8_t opcode) // 85, 95, 8d, 9d, 99, 81, 91 { uint16_t dest = 0; switch (opcode) { case 0x85: - dest = SM_ReadAdvance(); + dest = SM_ReadAdvance(sm); break; case 0x95: - dest = SM_ReadAdvance() + sm.x; + dest = SM_ReadAdvance(sm) + sm.x; break; case 0x8d: - dest = SM_ReadAdvance16(); + dest = SM_ReadAdvance16(sm); break; case 0x9d: - dest = SM_ReadAdvance16() + sm.x; + dest = SM_ReadAdvance16(sm) + sm.x; break; case 0x99: - dest = SM_ReadAdvance16() + sm.y; + dest = SM_ReadAdvance16(sm) + sm.y; break; case 0x81: - dest = SM_Read16((SM_ReadAdvance() + sm.x) & 0xff); + dest = SM_Read16(sm, (SM_ReadAdvance(sm) + sm.x) & 0xff); break; case 0x91: - dest = SM_Read16(SM_ReadAdvance()) + sm.y; + dest = SM_Read16(sm, SM_ReadAdvance(sm)) + sm.y; break; } - SM_Write(dest, sm.a); + SM_Write(sm, dest, sm.a); } -void SM_Opcode_INX(uint8_t opcode) // e8 +void SM_Opcode_INX(submcu_t& sm, uint8_t opcode) // e8 { sm.x++; - SM_Update_NZ(sm.x); + SM_Update_NZ(sm, sm.x); } -void SM_Opcode_INY(uint8_t opcode) // c8 +void SM_Opcode_INY(submcu_t& sm, uint8_t opcode) // c8 { sm.y++; - SM_Update_NZ(sm.y); + SM_Update_NZ(sm, sm.y); } -void SM_Opcode_BBC_BBS(uint8_t opcode) +void SM_Opcode_BBC_BBS(submcu_t& sm, uint8_t opcode) { int32_t zp = (opcode & 4) != 0; int32_t bit = (opcode >> 5) & 7; @@ -511,10 +502,10 @@ void SM_Opcode_BBC_BBS(uint8_t opcode) } else { - val = SM_Read(SM_ReadAdvance()); + val = SM_Read(sm, SM_ReadAdvance(sm)); } - int8_t diff = SM_ReadAdvance(); + int8_t diff = SM_ReadAdvance(sm); int32_t set = (val >> bit) & 1; @@ -522,132 +513,132 @@ void SM_Opcode_BBC_BBS(uint8_t opcode) sm.pc += diff; } -void SM_Opcode_CPX(uint8_t opcode) // e0, e4, ec +void SM_Opcode_CPX(submcu_t& sm, uint8_t opcode) // e0, e4, ec { uint8_t operand = 0; switch (opcode) { case 0xe0: - operand = SM_ReadAdvance(); + operand = SM_ReadAdvance(sm); break; case 0xe4: - operand = SM_Read(SM_ReadAdvance()); + operand = SM_Read(sm, SM_ReadAdvance(sm)); break; case 0xec: - operand = SM_Read(SM_ReadAdvance16()); + operand = SM_Read(sm, SM_ReadAdvance16(sm)); break; } int diff = sm.x - operand; - SM_SetStatus((diff & 0x100) == 0, SM_STATUS_C); - SM_Update_NZ(diff & 0xff); + SM_SetStatus(sm, (diff & 0x100) == 0, SM_STATUS_C); + SM_Update_NZ(sm, diff & 0xff); } -void SM_Opcode_CPY(uint8_t opcode) // c0, c4, cc +void SM_Opcode_CPY(submcu_t& sm, uint8_t opcode) // c0, c4, cc { uint8_t operand = 0; switch (opcode) { case 0xc0: - operand = SM_ReadAdvance(); + operand = SM_ReadAdvance(sm); break; case 0xc4: - operand = SM_Read(SM_ReadAdvance()); + operand = SM_Read(sm, SM_ReadAdvance(sm)); break; case 0xcc: - operand = SM_Read(SM_ReadAdvance16()); + operand = SM_Read(sm, SM_ReadAdvance16(sm)); break; } int diff = sm.y - operand; - SM_SetStatus((diff & 0x100) == 0, SM_STATUS_C); - SM_Update_NZ(diff & 0xff); + SM_SetStatus(sm, (diff & 0x100) == 0, SM_STATUS_C); + SM_Update_NZ(sm, diff & 0xff); } -void SM_Opcode_BEQ(uint8_t opcode) // f0 +void SM_Opcode_BEQ(submcu_t& sm, uint8_t opcode) // f0 { - int8_t diff = SM_ReadAdvance(); + int8_t diff = SM_ReadAdvance(sm); if ((sm.sr & SM_STATUS_Z) != 0) sm.pc += diff; } -void SM_Opcode_BCC(uint8_t opcode) // 90 +void SM_Opcode_BCC(submcu_t& sm, uint8_t opcode) // 90 { - int8_t diff = SM_ReadAdvance(); + int8_t diff = SM_ReadAdvance(sm); if ((sm.sr & SM_STATUS_C) == 0) sm.pc += diff; } -void SM_Opcode_BCS(uint8_t opcode) // b0 +void SM_Opcode_BCS(submcu_t& sm, uint8_t opcode) // b0 { - int8_t diff = SM_ReadAdvance(); + int8_t diff = SM_ReadAdvance(sm); if ((sm.sr & SM_STATUS_C) != 0) sm.pc += diff; } -void SM_Opcode_LDM(uint8_t opcode) // 3c +void SM_Opcode_LDM(submcu_t& sm, uint8_t opcode) // 3c { - uint8_t val = SM_ReadAdvance(); - SM_Write(SM_ReadAdvance(), val); + uint8_t val = SM_ReadAdvance(sm); + SM_Write(sm, SM_ReadAdvance(sm), val); } -void SM_Opcode_LDA(uint8_t opcode) // a9, a5, b5, ad, bd, b9, a1, b1 +void SM_Opcode_LDA(submcu_t& sm, uint8_t opcode) // a9, a5, b5, ad, bd, b9, a1, b1 { uint8_t val = 0; switch (opcode) { case 0xa9: - val = SM_ReadAdvance(); + val = SM_ReadAdvance(sm); break; case 0xa5: - val = SM_Read(SM_ReadAdvance()); + val = SM_Read(sm, SM_ReadAdvance(sm)); break; case 0xb5: - val = SM_Read((SM_ReadAdvance() + sm.x) & 0xff); + val = SM_Read(sm, (SM_ReadAdvance(sm) + sm.x) & 0xff); break; case 0xad: - val = SM_Read(SM_ReadAdvance16()); + val = SM_Read(sm, SM_ReadAdvance16(sm)); break; case 0xbd: - val = SM_Read(SM_ReadAdvance16() + sm.x); + val = SM_Read(sm, SM_ReadAdvance16(sm) + sm.x); break; case 0xb9: - val = SM_Read(SM_ReadAdvance16() + sm.y); + val = SM_Read(sm, SM_ReadAdvance16(sm) + sm.y); break; case 0xa1: - val = SM_Read(SM_Read16((SM_ReadAdvance() + sm.x) & 0xff)); + val = SM_Read(sm, SM_Read16(sm, (SM_ReadAdvance(sm) + sm.x) & 0xff)); break; case 0xb1: - val = SM_Read(SM_Read16(SM_ReadAdvance()) + sm.y); + val = SM_Read(sm, SM_Read16(sm, SM_ReadAdvance(sm)) + sm.y); break; } if ((sm.sr & SM_STATUS_T) == 0) { sm.a = val; - SM_Update_NZ(val); + SM_Update_NZ(sm, val); } else { // FIXME - SM_Write(sm.x, val); + SM_Write(sm, sm.x, val); } } -void SM_Opcode_CLI(uint8_t opcode) // 58 +void SM_Opcode_CLI(submcu_t& sm, uint8_t opcode) // 58 { - SM_SetStatus(0, SM_STATUS_I); + SM_SetStatus(sm, 0, SM_STATUS_I); } -void SM_Opcode_STP(uint8_t opcode) // 42 +void SM_Opcode_STP(submcu_t& sm, uint8_t opcode) // 42 { sm.sleep = 1; } -void SM_Opcode_PHA(uint8_t opcode) // 48 +void SM_Opcode_PHA(submcu_t& sm, uint8_t opcode) // 48 { - SM_PushStack(sm.a); + SM_PushStack(sm, sm.a); } -void SM_Opcode_SEB_CLB(uint8_t opcode) +void SM_Opcode_SEB_CLB(submcu_t& sm, uint8_t opcode) { int32_t zp = (opcode & 4) != 0; int32_t bit = (opcode >> 5) & 7; @@ -661,8 +652,8 @@ void SM_Opcode_SEB_CLB(uint8_t opcode) } else { - dest = SM_ReadAdvance(); - val = SM_Read(dest); + dest = SM_ReadAdvance(sm); + val = SM_Read(sm, dest); } if (type) @@ -676,115 +667,115 @@ void SM_Opcode_SEB_CLB(uint8_t opcode) } else { - SM_Write(dest, val); + SM_Write(sm, dest, val); } } -void SM_Opcode_RTI(uint8_t opcode) // 40 +void SM_Opcode_RTI(submcu_t& sm, uint8_t opcode) // 40 { - sm.sr = SM_PopStack(); - sm.pc = SM_PopStack(); - sm.pc |= SM_PopStack() << 8; + sm.sr = SM_PopStack(sm); + sm.pc = SM_PopStack(sm); + sm.pc |= SM_PopStack(sm) << 8; } -void SM_Opcode_PLA(uint8_t opcode) // 68 +void SM_Opcode_PLA(submcu_t& sm, uint8_t opcode) // 68 { - sm.a = SM_PopStack(); - SM_Update_NZ(sm.a); + sm.a = SM_PopStack(sm); + SM_Update_NZ(sm, sm.a); } -void SM_Opcode_BRA(uint8_t opcode) // 80 +void SM_Opcode_BRA(submcu_t& sm, uint8_t opcode) // 80 { - int8_t disp = SM_ReadAdvance(); + int8_t disp = SM_ReadAdvance(sm); sm.pc += disp; } -void SM_Opcode_JSR(uint8_t opcode) // 20, 02, 22 +void SM_Opcode_JSR(submcu_t& sm, uint8_t opcode) // 20, 02, 22 { uint16_t newpc = 0; switch (opcode) { case 0x20: - newpc = SM_ReadAdvance16(); + newpc = SM_ReadAdvance16(sm); break; case 0x02: - newpc = SM_Read16(SM_ReadAdvance()); + newpc = SM_Read16(sm, SM_ReadAdvance(sm)); break; case 0x22: - newpc = 0xff00 | SM_ReadAdvance(); + newpc = 0xff00 | SM_ReadAdvance(sm); break; } - SM_PushStack(sm.pc >> 8); - SM_PushStack(sm.pc & 0xff); + SM_PushStack(sm, sm.pc >> 8); + SM_PushStack(sm, sm.pc & 0xff); sm.pc = newpc; } -void SM_Opcode_CMP(uint8_t opcode) // c9, c5, d5, cd, dd, d9, c1, d1 +void SM_Opcode_CMP(submcu_t& sm, uint8_t opcode) // c9, c5, d5, cd, dd, d9, c1, d1 { uint8_t operand = 0; switch (opcode) { case 0xc9: - operand = SM_ReadAdvance(); + operand = SM_ReadAdvance(sm); break; case 0xc5: - operand = SM_Read(SM_ReadAdvance()); + operand = SM_Read(sm, SM_ReadAdvance(sm)); break; case 0xd5: - operand = SM_Read((SM_ReadAdvance()+sm.x)&0xff); + operand = SM_Read(sm, (SM_ReadAdvance(sm)+sm.x)&0xff); break; case 0xcd: - operand = SM_Read(SM_ReadAdvance16()); + operand = SM_Read(sm, SM_ReadAdvance16(sm)); break; case 0xdd: - operand = SM_Read(SM_ReadAdvance16() + sm.x); + operand = SM_Read(sm, SM_ReadAdvance16(sm) + sm.x); break; case 0xd9: - operand = SM_Read(SM_ReadAdvance16() + sm.y); + operand = SM_Read(sm, SM_ReadAdvance16(sm) + sm.y); break; case 0xc1: - operand = SM_Read(SM_Read16((SM_ReadAdvance() + sm.x) & 0xff)); + operand = SM_Read(sm, SM_Read16(sm, (SM_ReadAdvance(sm) + sm.x) & 0xff)); break; case 0xd1: - operand = SM_Read(SM_Read16(SM_ReadAdvance()) + sm.y); + operand = SM_Read(sm, SM_Read16(sm, SM_ReadAdvance(sm)) + sm.y); break; } int diff = sm.a - operand; - SM_SetStatus((diff & 0x100) == 0, SM_STATUS_C); - SM_Update_NZ(diff & 0xff); + SM_SetStatus(sm, (diff & 0x100) == 0, SM_STATUS_C); + SM_Update_NZ(sm, diff & 0xff); } -void SM_Opcode_BNE(uint8_t opcode) // d0 +void SM_Opcode_BNE(submcu_t& sm, uint8_t opcode) // d0 { - int8_t diff = SM_ReadAdvance(); + int8_t diff = SM_ReadAdvance(sm); if ((sm.sr & SM_STATUS_Z) == 0) sm.pc += diff; } -void SM_Opcode_RTS(uint8_t opcode) // 60 +void SM_Opcode_RTS(submcu_t& sm, uint8_t opcode) // 60 { - sm.pc = SM_PopStack(); - sm.pc |= SM_PopStack() << 8; + sm.pc = SM_PopStack(sm); + sm.pc |= SM_PopStack(sm) << 8; } -void SM_Opcode_JMP(uint8_t opcode) // 4c, 6c, b2 +void SM_Opcode_JMP(submcu_t& sm, uint8_t opcode) // 4c, 6c, b2 { switch (opcode) { case 0x4c: - sm.pc = SM_ReadAdvance16(); + sm.pc = SM_ReadAdvance16(sm); break; case 0x6c: - sm.pc = SM_Read16(SM_ReadAdvance16()); + sm.pc = SM_Read16(sm, SM_ReadAdvance16(sm)); break; case 0xb2: - sm.pc = SM_Read16(SM_ReadAdvance()); + sm.pc = SM_Read16(sm, SM_ReadAdvance(sm)); break; } } -void SM_Opcode_ORA(uint8_t opcode) // 09, 05, 15, 0d, 1d, 01, 11 +void SM_Opcode_ORA(submcu_t& sm, uint8_t opcode) // 09, 05, 15, 0d, 1d, 01, 11 { uint8_t val = 0; uint8_t val2 = 0; @@ -796,34 +787,34 @@ void SM_Opcode_ORA(uint8_t opcode) // 09, 05, 15, 0d, 1d, 01, 11 else { // FIXME - val = SM_Read(sm.x); + val = SM_Read(sm, sm.x); } switch (opcode) { case 0x09: - val2 = SM_ReadAdvance(); + val2 = SM_ReadAdvance(sm); break; case 0x05: - val2 = SM_Read(SM_ReadAdvance()); + val2 = SM_Read(sm, SM_ReadAdvance(sm)); break; case 0x15: - val2 = SM_Read((SM_ReadAdvance() + sm.x) & 0xff); + val2 = SM_Read(sm, (SM_ReadAdvance(sm) + sm.x) & 0xff); break; case 0x0d: - val2 = SM_Read(SM_ReadAdvance16()); + val2 = SM_Read(sm, SM_ReadAdvance16(sm)); break; case 0x1d: - val2 = SM_Read(SM_ReadAdvance16() + sm.x); + val2 = SM_Read(sm, SM_ReadAdvance16(sm) + sm.x); break; case 0x19: - val2 = SM_Read(SM_ReadAdvance16() + sm.y); + val2 = SM_Read(sm, SM_ReadAdvance16(sm) + sm.y); break; case 0x01: - val2 = SM_Read(SM_Read16((SM_ReadAdvance() + sm.x) & 0xff)); + val2 = SM_Read(sm, SM_Read16(sm, (SM_ReadAdvance(sm) + sm.x) & 0xff)); break; case 0x11: - val2 = SM_Read(SM_Read16(SM_ReadAdvance()) + sm.y); + val2 = SM_Read(sm, SM_Read16(sm, SM_ReadAdvance(sm)) + sm.y); break; } @@ -833,16 +824,16 @@ void SM_Opcode_ORA(uint8_t opcode) // 09, 05, 15, 0d, 1d, 01, 11 { sm.a = val; - SM_Update_NZ(val); + SM_Update_NZ(sm, val); } else { // FIXME - SM_Write(sm.x, val); + SM_Write(sm, sm.x, val); } } -void SM_Opcode_DEC(uint8_t opcode) // 1a, c6, d6, ce, de +void SM_Opcode_DEC(submcu_t& sm, uint8_t opcode) // 1a, c6, d6, ce, de { uint8_t val = 0; uint16_t dest = 0; @@ -850,93 +841,93 @@ void SM_Opcode_DEC(uint8_t opcode) // 1a, c6, d6, ce, de { case 0x1a: sm.a--; - SM_Update_NZ(sm.a); + SM_Update_NZ(sm, sm.a); return; case 0xc6: - dest = SM_ReadAdvance(); + dest = SM_ReadAdvance(sm); break; case 0xd6: - dest = (SM_ReadAdvance() + sm.x) & 0xff; + dest = (SM_ReadAdvance(sm) + sm.x) & 0xff; break; case 0xce: - dest = SM_ReadAdvance16(); + dest = SM_ReadAdvance16(sm); break; case 0xde: - dest = SM_ReadAdvance16() + sm.x; + dest = SM_ReadAdvance16(sm) + sm.x; break; } - val = SM_Read(dest); + val = SM_Read(sm, dest); val--; - SM_Write(dest, val); - SM_Update_NZ(val); + SM_Write(sm, dest, val); + SM_Update_NZ(sm, val); } -void SM_Opcode_TAX(uint8_t opcode) // aa +void SM_Opcode_TAX(submcu_t& sm, uint8_t opcode) // aa { sm.x = sm.a; - SM_Update_NZ(sm.x); + SM_Update_NZ(sm, sm.x); } -void SM_Opcode_STX(uint8_t opcode) // 86 96 8e +void SM_Opcode_STX(submcu_t& sm, uint8_t opcode) // 86 96 8e { uint16_t dest = 0; switch (opcode) { case 0x86: - dest = SM_ReadAdvance(); + dest = SM_ReadAdvance(sm); break; case 0x96: - dest = SM_ReadAdvance() + sm.x; + dest = SM_ReadAdvance(sm) + sm.x; break; case 0x8e: - dest = SM_ReadAdvance16(); + dest = SM_ReadAdvance16(sm); break; } - SM_Write(dest, sm.x); + SM_Write(sm, dest, sm.x); } -void SM_Opcode_STY(uint8_t opcode) // 84 8c 94 +void SM_Opcode_STY(submcu_t& sm, uint8_t opcode) // 84 8c 94 { uint16_t dest = 0; switch (opcode) { case 0x84: - dest = SM_ReadAdvance(); + dest = SM_ReadAdvance(sm); break; case 0x94: - dest = (SM_ReadAdvance() + sm.x) & 0xff; + dest = (SM_ReadAdvance(sm) + sm.x) & 0xff; break; case 0x8c: - dest = SM_ReadAdvance16(); + dest = SM_ReadAdvance16(sm); break; } - SM_Write(dest, sm.y); + SM_Write(sm, dest, sm.y); } -void SM_Opcode_SEC(uint8_t opcode) // 38 +void SM_Opcode_SEC(submcu_t& sm, uint8_t opcode) // 38 { - SM_SetStatus(1, SM_STATUS_C); + SM_SetStatus(sm, 1, SM_STATUS_C); } -void SM_Opcode_NOP(uint8_t opcode) // EA +void SM_Opcode_NOP(submcu_t& sm, uint8_t opcode) // EA { } -void SM_Opcode_BPL(uint8_t opcode) // 10 +void SM_Opcode_BPL(submcu_t& sm, uint8_t opcode) // 10 { - int8_t diff = SM_ReadAdvance(); + int8_t diff = SM_ReadAdvance(sm); if ((sm.sr & SM_STATUS_N) == 0) sm.pc += diff; } -void SM_Opcode_CLC(uint8_t opcode) // 18 +void SM_Opcode_CLC(submcu_t& sm, uint8_t opcode) // 18 { - SM_SetStatus(0, SM_STATUS_C); + SM_SetStatus(sm, 0, SM_STATUS_C); } -void SM_Opcode_AND(uint8_t opcode) // 29, 25, 35, 2d, 3d, 21, 31 +void SM_Opcode_AND(submcu_t& sm, uint8_t opcode) // 29, 25, 35, 2d, 3d, 21, 31 { uint8_t val = 0; uint8_t val2 = 0; @@ -948,34 +939,34 @@ void SM_Opcode_AND(uint8_t opcode) // 29, 25, 35, 2d, 3d, 21, 31 else { // FIXME - val = SM_Read(sm.x); + val = SM_Read(sm, sm.x); } switch (opcode) { case 0x29: - val2 = SM_ReadAdvance(); + val2 = SM_ReadAdvance(sm); break; case 0x25: - val2 = SM_Read(SM_ReadAdvance()); + val2 = SM_Read(sm, SM_ReadAdvance(sm)); break; case 0x35: - val2 = SM_Read((SM_ReadAdvance() + sm.x) & 0xff); + val2 = SM_Read(sm, (SM_ReadAdvance(sm) + sm.x) & 0xff); break; case 0x2d: - val2 = SM_Read(SM_ReadAdvance16()); + val2 = SM_Read(sm, SM_ReadAdvance16(sm)); break; case 0x3d: - val2 = SM_Read(SM_ReadAdvance16() + sm.x); + val2 = SM_Read(sm, SM_ReadAdvance16(sm) + sm.x); break; case 0x39: - val2 = SM_Read(SM_ReadAdvance16() + sm.y); + val2 = SM_Read(sm, SM_ReadAdvance16(sm) + sm.y); break; case 0x21: - val2 = SM_Read(SM_Read16((SM_ReadAdvance() + sm.x) & 0xff)); + val2 = SM_Read(sm, SM_Read16(sm, (SM_ReadAdvance(sm) + sm.x) & 0xff)); break; case 0x31: - val2 = SM_Read(SM_Read16(SM_ReadAdvance()) + sm.y); + val2 = SM_Read(sm, SM_Read16(sm, SM_ReadAdvance(sm)) + sm.y); break; } @@ -985,16 +976,16 @@ void SM_Opcode_AND(uint8_t opcode) // 29, 25, 35, 2d, 3d, 21, 31 { sm.a = val; - SM_Update_NZ(val); + SM_Update_NZ(sm, val); } else { // FIXME - SM_Write(sm.x, val); + SM_Write(sm, sm.x, val); } } -void SM_Opcode_INC(uint8_t opcode) // 3a, e6, f6, ee, fe +void SM_Opcode_INC(submcu_t& sm, uint8_t opcode) // 3a, e6, f6, ee, fe { uint8_t val = 0; uint16_t dest = 0; @@ -1002,28 +993,28 @@ void SM_Opcode_INC(uint8_t opcode) // 3a, e6, f6, ee, fe { case 0x3a: sm.a++; - SM_Update_NZ(sm.a); + SM_Update_NZ(sm, sm.a); return; case 0xe6: - dest = SM_ReadAdvance(); + dest = SM_ReadAdvance(sm); break; case 0xf6: - dest = (SM_ReadAdvance() + sm.x) & 0xff; + dest = (SM_ReadAdvance(sm) + sm.x) & 0xff; break; case 0xee: - dest = SM_ReadAdvance16(); + dest = SM_ReadAdvance16(sm); break; case 0xfe: - dest = SM_ReadAdvance16() + sm.x; + dest = SM_ReadAdvance16(sm) + sm.x; break; } - val = SM_Read(dest); + val = SM_Read(sm, dest); val++; - SM_Write(dest, val); - SM_Update_NZ(val); + SM_Write(sm, dest, val); + SM_Update_NZ(sm, val); } -void (*SM_Opcode_Table[256])(uint8_t opcode) +void (*SM_Opcode_Table[256])(submcu_t& sm, uint8_t opcode) { SM_Opcode_NotImplemented, // 00 SM_Opcode_ORA, // 01 @@ -1283,160 +1274,162 @@ void (*SM_Opcode_Table[256])(uint8_t opcode) SM_Opcode_SEB_CLB, // ff }; -void SM_StartVector(uint32_t vector) +void SM_StartVector(submcu_t& sm, uint32_t vector) { - SM_PushStack(sm.pc >> 8); - SM_PushStack(sm.pc & 0xff); - SM_PushStack(sm.sr); + SM_PushStack(sm, sm.pc >> 8); + SM_PushStack(sm, sm.pc & 0xff); + SM_PushStack(sm, sm.sr); sm.sr |= SM_STATUS_I; sm.sleep = 0; - sm.pc = SM_GetVectorAddress(vector); + sm.pc = SM_GetVectorAddress(sm, vector); } -void SM_HandleInterrupt(void) +void SM_HandleInterrupt(submcu_t& sm) { if (sm.sr & SM_STATUS_I) return; - if ((sm_device_mode[SM_DEV_UART1_CTRL] & 0x8) != 0 - && (sm_device_mode[SM_DEV_INT_ENABLE] & 0x80) != 0 - && (sm_device_mode[SM_DEV_INT_REQUEST] & 0x80) != 0) + if ((sm.sm_device_mode[SM_DEV_UART1_CTRL] & 0x8) != 0 + && (sm.sm_device_mode[SM_DEV_INT_ENABLE] & 0x80) != 0 + && (sm.sm_device_mode[SM_DEV_INT_REQUEST] & 0x80) != 0) { - sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x80; - SM_StartVector(SM_VECTOR_UART1_RX); + sm.sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x80; + SM_StartVector(sm, SM_VECTOR_UART1_RX); return; } - if ((sm_device_mode[SM_DEV_UART2_CTRL] & 0x8) != 0 - && (sm_device_mode[SM_DEV_INT_ENABLE] & 0x40) != 0 - && (sm_device_mode[SM_DEV_INT_REQUEST] & 0x40) != 0) + if ((sm.sm_device_mode[SM_DEV_UART2_CTRL] & 0x8) != 0 + && (sm.sm_device_mode[SM_DEV_INT_ENABLE] & 0x40) != 0 + && (sm.sm_device_mode[SM_DEV_INT_REQUEST] & 0x40) != 0) { - sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x40; - SM_StartVector(SM_VECTOR_UART2_RX); + sm.sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x40; + SM_StartVector(sm, SM_VECTOR_UART2_RX); return; } - if ((sm_device_mode[SM_DEV_UART3_CTRL] & 0x8) != 0 - && (sm_device_mode[SM_DEV_INT_ENABLE] & 0x20) != 0 - && (sm_device_mode[SM_DEV_INT_REQUEST] & 0x20) != 0) + if ((sm.sm_device_mode[SM_DEV_UART3_CTRL] & 0x8) != 0 + && (sm.sm_device_mode[SM_DEV_INT_ENABLE] & 0x20) != 0 + && (sm.sm_device_mode[SM_DEV_INT_REQUEST] & 0x20) != 0) { - sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x20; - SM_StartVector(SM_VECTOR_UART3_RX); + sm.sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x20; + SM_StartVector(sm, SM_VECTOR_UART3_RX); return; } - if ((sm_device_mode[SM_DEV_TIMER_CTRL] & 0x80) != 0 - && (sm_device_mode[SM_DEV_INT_ENABLE] & 0x10) != 0 - && (sm_device_mode[SM_DEV_INT_REQUEST] & 0x10) != 0) + if ((sm.sm_device_mode[SM_DEV_TIMER_CTRL] & 0x80) != 0 + && (sm.sm_device_mode[SM_DEV_INT_ENABLE] & 0x10) != 0 + && (sm.sm_device_mode[SM_DEV_INT_REQUEST] & 0x10) != 0) { - sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x10; - SM_StartVector(SM_VECTOR_IPCM0); + sm.sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x10; + SM_StartVector(sm, SM_VECTOR_IPCM0); return; } - if ((sm_device_mode[SM_DEV_TIMER_CTRL] & 0x40) != 0 - && (sm_device_mode[SM_DEV_INT_ENABLE] & 0x8) != 0 - && (sm_device_mode[SM_DEV_INT_REQUEST] & 0x8) != 0) + if ((sm.sm_device_mode[SM_DEV_TIMER_CTRL] & 0x40) != 0 + && (sm.sm_device_mode[SM_DEV_INT_ENABLE] & 0x8) != 0 + && (sm.sm_device_mode[SM_DEV_INT_REQUEST] & 0x8) != 0) { - sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x8; - SM_StartVector(SM_VECTOR_TIMER_X); + sm.sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x8; + SM_StartVector(sm, SM_VECTOR_TIMER_X); return; } - if ((sm_device_mode[SM_DEV_COLLISION] & 0xc0) == 0xc0) + if ((sm.sm_device_mode[SM_DEV_COLLISION] & 0xc0) == 0xc0) { - sm_device_mode[SM_DEV_COLLISION] &= ~0x80; - SM_StartVector(SM_VECTOR_COLLISION); + sm.sm_device_mode[SM_DEV_COLLISION] &= ~0x80; + SM_StartVector(sm, SM_VECTOR_COLLISION); return; } - if (((sm_device_mode[SM_DEV_UART1_CTRL] & 0x10) == 0 - || (sm_cts & 1) != 0) - && (sm_device_mode[SM_DEV_INT_ENABLE] & 0x4) != 0 - && (sm_device_mode[SM_DEV_INT_REQUEST] & 0x4) != 0) + if (((sm.sm_device_mode[SM_DEV_UART1_CTRL] & 0x10) == 0 + || (sm.sm_cts & 1) != 0) + && (sm.sm_device_mode[SM_DEV_INT_ENABLE] & 0x4) != 0 + && (sm.sm_device_mode[SM_DEV_INT_REQUEST] & 0x4) != 0) { - sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x4; - SM_StartVector(SM_VECTOR_UART1_TX); + sm.sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x4; + SM_StartVector(sm, SM_VECTOR_UART1_TX); return; } - if (((sm_device_mode[SM_DEV_UART2_CTRL] & 0x10) == 0 - || (sm_cts & 2) != 0) - && (sm_device_mode[SM_DEV_INT_ENABLE] & 0x2) != 0 - && (sm_device_mode[SM_DEV_INT_REQUEST] & 0x2) != 0) + if (((sm.sm_device_mode[SM_DEV_UART2_CTRL] & 0x10) == 0 + || (sm.sm_cts & 2) != 0) + && (sm.sm_device_mode[SM_DEV_INT_ENABLE] & 0x2) != 0 + && (sm.sm_device_mode[SM_DEV_INT_REQUEST] & 0x2) != 0) { - sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x2; - SM_StartVector(SM_VECTOR_UART2_TX); + sm.sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x2; + SM_StartVector(sm, SM_VECTOR_UART2_TX); return; } - if (((sm_device_mode[SM_DEV_UART3_CTRL] & 0x10) == 0 - || (sm_cts & 4) != 0) - && (sm_device_mode[SM_DEV_INT_ENABLE] & 0x1) != 0 - && (sm_device_mode[SM_DEV_INT_REQUEST] & 0x1) != 0) + if (((sm.sm_device_mode[SM_DEV_UART3_CTRL] & 0x10) == 0 + || (sm.sm_cts & 4) != 0) + && (sm.sm_device_mode[SM_DEV_INT_ENABLE] & 0x1) != 0 + && (sm.sm_device_mode[SM_DEV_INT_REQUEST] & 0x1) != 0) { - sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x1; - SM_StartVector(SM_VECTOR_UART3_TX); + sm.sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x1; + SM_StartVector(sm, SM_VECTOR_UART3_TX); return; } } -void SM_UpdateTimer(void) +void SM_UpdateTimer(submcu_t& sm) { - while (sm_timer_cycles < sm.cycles) + while (sm.sm_timer_cycles < sm.cycles) { - if ((sm_device_mode[SM_DEV_TIMER_CTRL] & 0x20) == 0 && !sm.sleep) + if ((sm.sm_device_mode[SM_DEV_TIMER_CTRL] & 0x20) == 0 && !sm.sleep) { - if (sm_timer_prescaler == 0) + if (sm.sm_timer_prescaler == 0) { - sm_timer_prescaler = sm_device_mode[SM_DEV_PRESCALER]; + sm.sm_timer_prescaler = sm.sm_device_mode[SM_DEV_PRESCALER]; - if (sm_timer_counter == 0) + if (sm.sm_timer_counter == 0) { - sm_timer_counter = sm_device_mode[SM_DEV_TIMER]; - sm_device_mode[SM_DEV_INT_REQUEST] |= 0x8; + sm.sm_timer_counter = sm.sm_device_mode[SM_DEV_TIMER]; + sm.sm_device_mode[SM_DEV_INT_REQUEST] |= 0x8; } else - sm_timer_counter--; + sm.sm_timer_counter--; } else - sm_timer_prescaler--; + sm.sm_timer_prescaler--; } - sm_timer_cycles += 16; + sm.sm_timer_cycles += 16; } } -void SM_UpdateUART(void) +void SM_UpdateUART(submcu_t& sm) { - if ((sm_device_mode[SM_DEV_UART1_CTRL] & 4) == 0) // RX disabled + mcu_t& mcu = *sm.mcu; + + if ((sm.sm_device_mode[SM_DEV_UART1_CTRL] & 4) == 0) // RX disabled return; - if (uart_write_ptr == uart_read_ptr) // no byte + if (mcu.uart_write_ptr == mcu.uart_read_ptr) // no byte return; - if (uart_rx_gotbyte) + if (sm.uart_rx_gotbyte) return; - if (sm.cycles < uart_rx_delay) + if (sm.cycles < mcu.uart_rx_delay) return; - uart_rx_byte = uart_buffer[uart_read_ptr]; - uart_read_ptr = (uart_read_ptr + 1) % uart_buffer_size; - uart_rx_gotbyte = 1; - sm_device_mode[SM_DEV_INT_REQUEST] |= 0x40; + mcu.uart_rx_byte = mcu.uart_buffer[mcu.uart_read_ptr]; + mcu.uart_read_ptr = (mcu.uart_read_ptr + 1) % uart_buffer_size; + sm.uart_rx_gotbyte = 1; + sm.sm_device_mode[SM_DEV_INT_REQUEST] |= 0x40; - uart_rx_delay = sm.cycles + 3000 * 4; + mcu.uart_rx_delay = sm.cycles + 3000 * 4; } -void SM_Update(uint64_t cycles) +void SM_Update(submcu_t& sm, uint64_t cycles) { while (sm.cycles < cycles * 5) { - SM_HandleInterrupt(); + SM_HandleInterrupt(sm); if (!sm.sleep) { - uint8_t opcode = SM_ReadAdvance(); + uint8_t opcode = SM_ReadAdvance(sm); - SM_Opcode_Table[opcode](opcode); + SM_Opcode_Table[opcode](sm, opcode); } sm.cycles += 12 * 4; // FIXME - SM_UpdateTimer(); - SM_UpdateUART(); + SM_UpdateTimer(sm); + SM_UpdateUART(sm); } } diff --git a/src/submcu.h b/src/submcu.h index d6c7feeb..eaf86a81 100644 --- a/src/submcu.h +++ b/src/submcu.h @@ -34,6 +34,8 @@ #pragma once #include +struct mcu_t; + enum { SM_STATUS_C = 1, SM_STATUS_Z = 2, @@ -54,14 +56,29 @@ struct submcu_t { uint8_t sr; uint64_t cycles; uint8_t sleep; -}; + mcu_t* mcu; + uint8_t sm_rom[4096]; + + uint8_t sm_ram[128]; + uint8_t sm_shared_ram[192]; + uint8_t sm_access[0x18]; -extern submcu_t sm; + uint8_t sm_p0_dir; + uint8_t sm_p1_dir; -extern uint8_t sm_rom[4096]; + uint8_t sm_device_mode[32]; + uint8_t sm_cts; + + uint64_t sm_timer_cycles; + uint8_t sm_timer_prescaler; + uint8_t sm_timer_counter; + + uint8_t uart_rx_gotbyte; +}; -void SM_Reset(void); -void SM_Update(uint64_t cycles); -void SM_SysWrite(uint32_t address, uint8_t data); -uint8_t SM_SysRead(uint32_t address); -void SM_PostUART(uint8_t data); +void SM_Init(submcu_t& sm, mcu_t& mcu); +void SM_Reset(submcu_t& sm); +void SM_Update(submcu_t& sm, uint64_t cycles); +void SM_SysWrite(submcu_t& sm, uint32_t address, uint8_t data); +uint8_t SM_SysRead(submcu_t& sm, uint32_t address); +void SM_PostUART(submcu_t& sm, uint8_t data);