diff --git a/.gitmodules b/.gitmodules index d3346f2..f3a76a4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "3rdparty/rtmidi"] - path = 3rdparty/rtmidi - url = https://github.com/Wohlstand/rtmidi.git +[submodule "3rdparty/portmidi"] + path = 3rdparty/portmidi + url = https://github.com/PortMidi/portmidi.git diff --git a/3rdparty/portmidi b/3rdparty/portmidi new file mode 160000 index 0000000..3920301 --- /dev/null +++ b/3rdparty/portmidi @@ -0,0 +1 @@ +Subproject commit 3920301ce1234031007550cd0b99b4d6649e3283 diff --git a/3rdparty/rtmidi b/3rdparty/rtmidi deleted file mode 160000 index 7227033..0000000 --- a/3rdparty/rtmidi +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7227033bcc0df36d4815c9ab57500bb320bf8171 diff --git a/CMakeLists.txt b/CMakeLists.txt index 34a53bf..870b2bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -172,18 +172,14 @@ endif() include(3rdparty/Utf8Main/utf8main.cmake) if(NOT WIN32 AND PKG_CONFIG_FOUND) - set(USE_RTMIDI TRUE) - option(USE_SYSTEM_RTMIDI "Use system libraries for RtMidi" OFF) + set(USE_PORTMIDI TRUE) + option(USE_SYSTEM_PORTMIDI "Use system libraries for PortMidi" OFF) endif() find_package(SDL2 REQUIRED) -if(USE_RTMIDI) - if(USE_SYSTEM_RTMIDI) - pkg_check_modules(SYSTEM_RTMIDI rtmidi REQUIRED) - else() - include(RtMidi) - endif() +if(USE_PORTMIDI) + add_subdirectory(3rdparty/portmidi) endif() @@ -200,8 +196,8 @@ set(SC55_SRC src/utils/files.cpp src/utils/files.h ) -if(USE_RTMIDI) - list(APPEND SC55_SRC src/midi_rtmidi.cpp) +if(USE_PORTMIDI) + list(APPEND SC55_SRC src/midi_portmidi.cpp) elseif(WIN32) list(APPEND SC55_SRC src/midi_win32.cpp) endif() @@ -217,14 +213,8 @@ else() target_link_libraries(nuked-sc55 PRIVATE ${SDL2_LIBRARIES}) endif() -if(USE_RTMIDI) - if(USE_SYSTEM_RTMIDI) - target_compile_options(nuked-sc55 PRIVATE ${SYSTEM_RTMIDI_CFLAGS}) - target_include_directories(nuked-sc55 PRIVATE ${SYSTEM_RTMIDI_INCLUDE_DIRS}) - target_link_libraries(nuked-sc55 PRIVATE ${SYSTEM_RTMIDI_LIBRARIES}) - else() - target_link_libraries(nuked-sc55 PRIVATE RtMidi) - endif() +if(USE_PORTMIDI) + target_link_libraries(nuked-sc55 PRIVATE portmidi) endif() if(WIN32) diff --git a/cmake/RtMidi.cmake b/cmake/RtMidi.cmake deleted file mode 100644 index 02ba8c5..0000000 --- a/cmake/RtMidi.cmake +++ /dev/null @@ -1,16 +0,0 @@ -add_library(RtMidi STATIC EXCLUDE_FROM_ALL "3rdparty/rtmidi/RtMidi.cpp") -target_include_directories(RtMidi PUBLIC "3rdparty/rtmidi") - -if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - target_compile_definitions(RtMidi PUBLIC "__LINUX_ALSA__") - target_link_libraries(RtMidi PUBLIC "asound") - target_link_libraries(RtMidi PUBLIC "pthread") -elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") - target_compile_definitions(RtMidi PUBLIC "__WINDOWS_MM__") - target_link_libraries(RtMidi PUBLIC "winmm") -elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") - target_compile_definitions(RtMidi PUBLIC "__MACOSX_CORE__") - find_library(COREMIDI_LIBRARY "CoreMIDI") - find_library(FOUNDATION_LIBRARY "Foundation") - target_link_libraries(RtMidi PUBLIC "${COREMIDI_LIBRARY}" "${FOUNDATION_LIBRARY}") -endif() diff --git a/src/lcd.cpp b/src/lcd.cpp index 0448727..8d7dd25 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -82,7 +82,7 @@ void LCD_Write(uint32_t address, uint8_t data) else if ((data & 0xff) == 0x01) { LCD_DD_RAM = 0; - LCD_ID = 0; + LCD_ID = 1; memset(LCD_Data, 0x20, sizeof(LCD_Data)); } else if ((data & 0xff) == 0x02) @@ -162,20 +162,22 @@ void LCD_Write(uint32_t address, uint8_t data) // printf("\n"); } -static const int lcd_width = 741; -static const int lcd_height = 268; +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][lcd_width]; -static uint32_t lcd_background[lcd_height][lcd_width]; +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[][2] = +const int button_map_sc55[][2] = { SDL_SCANCODE_Q, MCU_BUTTON_POWER, SDL_SCANCODE_W, MCU_BUTTON_INST_ALL, @@ -197,7 +199,25 @@ const int button_map[][2] = SDL_SCANCODE_J, MCU_BUTTON_CHORUS_L, SDL_SCANCODE_K, MCU_BUTTON_CHORUS_R, SDL_SCANCODE_LEFT, MCU_BUTTON_PART_L, - SDL_SCANCODE_RIGHT, MCU_BUTTON_PART_R + SDL_SCANCODE_RIGHT, MCU_BUTTON_PART_R, +}; + +const int button_map_jv880[][2] = +{ + SDL_SCANCODE_P, MCU_BUTTON_PREVIEW, + SDL_SCANCODE_LEFT, MCU_BUTTON_CURSOR_L, + SDL_SCANCODE_RIGHT, MCU_BUTTON_CURSOR_R, + SDL_SCANCODE_TAB, MCU_BUTTON_DATA, + SDL_SCANCODE_Q, MCU_BUTTON_TONE_SELECT, + SDL_SCANCODE_A, MCU_BUTTON_PATCH_PERFORM, + SDL_SCANCODE_W, MCU_BUTTON_EDIT, + SDL_SCANCODE_E, MCU_BUTTON_SYSTEM, + SDL_SCANCODE_R, MCU_BUTTON_RHYTHM, + SDL_SCANCODE_T, MCU_BUTTON_UTILITY, + SDL_SCANCODE_S, MCU_BUTTON_MUTE, + SDL_SCANCODE_D, MCU_BUTTON_MONITOR, + SDL_SCANCODE_F, MCU_BUTTON_COMPARE, + SDL_SCANCODE_G, MCU_BUTTON_ENTER, }; @@ -326,22 +346,37 @@ void LCD_Update(void) { MCU_WorkThread_Lock(); - if (!lcd_enable) + if (!lcd_enable && !mcu_jv880) { memset(lcd_buffer, 0, sizeof(lcd_buffer)); } else { - memcpy(lcd_buffer, lcd_background, sizeof(lcd_buffer)); + if (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; + } + } + } + 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]; + } + } + } - if (0) + if (mcu_jv880) { - for (int i = 0; i < 4; i++) + for (int i = 0; i < 2; i++) { - for (int j = 0; j < 20; j++) + for (int j = 0; j < 24; j++) { - uint8_t ch = LCD_Data[i * 20 + j]; - LCD_FontRenderStandard(i * 50, j * 34, ch); + uint8_t ch = LCD_Data[i * 40 + j]; + LCD_FontRenderStandard(4 + i * 50, 4 + j * 34, ch); } } } @@ -401,7 +436,7 @@ void LCD_Update(void) MCU_WorkThread_Unlock(); - SDL_UpdateTexture(texture, NULL, lcd_buffer, lcd_width * 4); + SDL_UpdateTexture(texture, NULL, lcd_buffer, lcd_width_max * 4); SDL_RenderCopy(renderer, texture, NULL, NULL); SDL_RenderPresent(renderer); } @@ -409,6 +444,14 @@ void LCD_Update(void) SDL_Event sdl_event; while (SDL_PollEvent(&sdl_event)) { + 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); + } + switch (sdl_event.type) { case SDL_QUIT: @@ -420,11 +463,13 @@ void LCD_Update(void) { if (sdl_event.key.repeat) continue; - + int mask = 0; uint32_t button_pressed = (uint32_t)SDL_AtomicGet(&mcu_button_pressed); - for (size_t i = 0; i < sizeof(button_map) / sizeof(button_map[0]); i++) + 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]); + for (size_t i = 0; i < button_size; i++) { if (button_map[i][0] == sdl_event.key.keysym.scancode) mask |= (1 << button_map[i][1]); diff --git a/src/lcd.h b/src/lcd.h index 173cf7b..a9982a8 100644 --- a/src/lcd.h +++ b/src/lcd.h @@ -36,6 +36,9 @@ #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); diff --git a/src/mcu.cpp b/src/mcu.cpp index e116259..1779057 100644 --- a/src/mcu.cpp +++ b/src/mcu.cpp @@ -55,7 +55,8 @@ const char* rs_name[ROM_SET_COUNT] = { "SC-55mk2", "SC-55st", "SC-55mk1", - "CM-300/SCC-1" + "CM-300/SCC-1", + "JV880" }; const char* roms[ROM_SET_COUNT][5] = @@ -83,6 +84,12 @@ const char* roms[ROM_SET_COUNT][5] = "cm300_waverom1.bin", "cm300_waverom2.bin", "cm300_waverom3.bin", + + "jv880_rom1.bin", + "jv880_rom2.bin", + "jv880_waverom1.bin", + "jv880_waverom2.bin", + "SR-JV80-01 Pop - CS 0x3F1CF705.bin", }; int romset = ROM_SET_MK2; @@ -91,6 +98,8 @@ 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; @@ -112,6 +121,7 @@ void MCU_ErrorTrap(void) 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 static int ga_int[8]; static int ga_int_enable = 0; @@ -356,6 +366,23 @@ uint8_t MCU_DeviceRead(uint32_t address) return uart_rx_byte; case 0x00: return 0xff; + case DEV_P7DR: + { + if (!mcu_jv880) return 0xff; + + uint8_t data = 0xff; + uint32_t button_pressed = (uint32_t)SDL_AtomicGet(&mcu_button_pressed); + + if (io_sd == 0b11111011) + data &= ((button_pressed >> 0) & 0b11111) ^ 0xFF; + if (io_sd == 0b11110111) + data &= ((button_pressed >> 5) & 0b11111) ^ 0xFF; + if (io_sd == 0b11101111) + data &= ((button_pressed >> 10) & 0b1111) ^ 0xFF; + + data |= 0b10000000; + return data; + } case DEV_P9DR: { int cfg = 0; @@ -369,6 +396,8 @@ uint8_t MCU_DeviceRead(uint32_t address) return val; } case DEV_SCR: + case DEV_TDR: + case DEV_SMR: return dev_register[address]; case DEV_IPRC: case DEV_IPRD: @@ -434,13 +463,15 @@ 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) { uint32_t address_rom = address & 0x3ffff; - if (address & 0x80000) + if (address & 0x80000 && !mcu_jv880) address_rom |= 0x40000; uint8_t page = (address >> 16) & 0xf; address &= 0xffff; @@ -454,7 +485,7 @@ uint8_t MCU_Read(uint32_t address) { if (!mcu_mk1) { - if (address >= 0xe000 && address < 0xe400) + if (mcu_jv880 ? (address >= 0xf000 && address < 0xf400) : (address >= 0xe000 && address < 0xe400)) { ret = PCM_Read(address & 0x3f); } @@ -473,11 +504,11 @@ uint8_t MCU_Read(uint32_t address) { ret = sram[address & 0x7fff]; } - else if (address == 0xe402) + else if (mcu_jv880 ? (address == 0xf402) : (address == 0xe402)) { ret = ga_int_trigger; ga_int_trigger = 0; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_IRQ1, 0); + MCU_Interrupt_SetRequest(mcu_jv880 ? INTERRUPT_SOURCE_IRQ0 : INTERRUPT_SOURCE_IRQ1, 0); } else { @@ -571,23 +602,38 @@ uint8_t MCU_Read(uint32_t address) ret = rom2[address_rom & rom2_mask]; break; case 8: - ret = rom2[address_rom & rom2_mask]; + if (!mcu_jv880) + ret = rom2[address_rom & rom2_mask]; + else + ret = 0xff; break; case 9: - ret = rom2[address_rom & rom2_mask]; + if (!mcu_jv880) + ret = rom2[address_rom & rom2_mask]; + else + ret = 0xff; break; case 14: - ret = rom2[address_rom & rom2_mask]; - break; case 15: - ret = rom2[address_rom & rom2_mask]; + if (!mcu_jv880) + ret = rom2[address_rom & rom2_mask]; + else + ret = cardram[address & 0x7fff]; // FIXME break; case 10: + case 11: if (!mcu_mk1) ret = sram[address & 0x7fff]; // FIXME else ret = 0xff; break; + case 12: + case 13: + if (mcu_jv880) + ret = nvram[address & 0x7fff]; // FIXME + else + ret = 0xff; + break; case 5: if (mcu_mk1) ret = sram[address & 0x7fff]; // FIXME @@ -631,16 +677,17 @@ void MCU_Write(uint32_t address, uint8_t value) { if (!mcu_mk1) { - if (address >= 0xe400 && address < 0xe800) + uint16_t base = mcu_jv880 ? 0xf000 : 0xe000; + if (address >= (base | 0x400) && address < (base | 0x800)) { - if (address == 0xe404 || address == 0xe405) + if (address == (base | 0x404) || address == (base | 0x405)) LCD_Write(address & 1, value); - else if (address == 0xe401) + else if (address == (base | 0x401)) { io_sd = value; LCD_Enable((value & 1) == 0); } - else if (address == 0xe402) + else if (address == (base | 0x402)) ga_int_enable = (value << 1); else printf("Unknown write %x %x\n", address, value); @@ -655,7 +702,7 @@ void MCU_Write(uint32_t address, uint8_t value) // e407: 0, e406 continuation? // } - else if (address >= 0xe000 && address < 0xe400) + else if (address >= (base | 0x000) && address < (base | 0x400)) { PCM_Write(address & 0x3f, value); } @@ -738,6 +785,14 @@ void MCU_Write(uint32_t address, uint8_t value) { sram[address & 0x7fff] = value; // FIXME } + else if (page == 12 && mcu_jv880) + { + nvram[address & 0x7fff] = value; // FIXME + } + else if (page == 14 && mcu_jv880) + { + cardram[address & 0x7fff] = value; // FIXME + } else { printf("Unknown write %x %x\n", (page << 16) | address, value); @@ -898,7 +953,7 @@ int SDLCALL work_thread(void* data) TIMER_Clock(mcu.cycles); - if (!mcu_mk1) + if (!mcu_mk1 && !mcu_jv880) SM_Update(mcu.cycles); else { @@ -920,6 +975,8 @@ int SDLCALL work_thread(void* data) } } } + + MIDI_Update(); } MCU_WorkThread_Unlock(); @@ -988,7 +1045,7 @@ void MCU_WriteP1(uint8_t data) mcu_p1_data = data; } -uint8_t tempbuf[0x200000]; +uint8_t tempbuf[0x800000]; void unscramble(uint8_t *src, uint8_t *dst, int len) { @@ -1060,7 +1117,7 @@ int MCU_OpenAudio(void) SDL_AudioSpec spec_actual = {}; spec.format = AUDIO_S16SYS; - spec.freq = mcu_mk1 ? 64000: 66207; + spec.freq = (mcu_mk1 || mcu_jv880) ? 64000 : 66207; spec.channels = 2; spec.callback = audio_callback; spec.samples = audio_page_size / 4; @@ -1121,7 +1178,17 @@ void MCU_GA_SetGAInt(int line, int value) ga_int_trigger = line; ga_int[line] = value; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_IRQ1, ga_int_trigger != 0); + if (mcu_jv880) + MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_IRQ0, 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); } @@ -1182,6 +1249,12 @@ int main(int argc, char *argv[]) romset = ROM_SET_CM300; autodetect = false; } + else if (!strcmp(argv[i], "-jv880")) + { + romset = ROM_SET_JV880; + autodetect = false; + break; + } } } @@ -1226,23 +1299,36 @@ int main(int argc, char *argv[]) } printf("ROM set autodetect: %s\n", rs_name[romset]); } - - mcu_mk1 = false; - mcu_cm300 = false; + + mcu_mk1 = false; + mcu_cm300 = false; mcu_st = false; - switch (romset) - { - case ROM_SET_ST: - mcu_st = true; - break; - case ROM_SET_MK1: - mcu_mk1 = true; - mcu_st = false; - break; - case ROM_SET_CM300: - mcu_mk1 = true; - mcu_cm300 = true; - break; + mcu_jv880 = false; + switch (romset) + { + case ROM_SET_ST: + mcu_st = true; + break; + case ROM_SET_MK1: + mcu_mk1 = true; + mcu_st = false; + 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; + FILE *f = fopen("nvram.bin", "rb"); + if (f) + { + fread(nvram, NVRAM_SIZE, 1, f); + fclose(f); + } + break; } std::string rpaths[5] = @@ -1337,6 +1423,38 @@ int main(int argc, char *argv[]) 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 (fread(tempbuf, 1, 0x800000, s_rf[4]) != 0x800000) + { + fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom EXP.\n"); + fflush(stderr); + closeAllR(); + return 1; + } + + unscramble(tempbuf, waverom_exp, 0x800000); + } else { if (fread(tempbuf, 1, 0x200000, s_rf[2]) != 0x200000) @@ -1405,5 +1523,9 @@ int main(int argc, char *argv[]) LCD_UnInit(); SDL_Quit(); + FILE *f = fopen("nvram.bin", "wb"); + fwrite(nvram, NVRAM_SIZE, 1, f); + fclose(f); + return 0; } diff --git a/src/mcu.h b/src/mcu.h index 84c4a1f..514887b 100644 --- a/src/mcu.h +++ b/src/mcu.h @@ -373,6 +373,7 @@ inline uint16_t MCU_PopStack(void) } enum { + // SC55 MCU_BUTTON_POWER = 0, MCU_BUTTON_INST_L = 3, MCU_BUTTON_INST_R = 4, @@ -391,7 +392,23 @@ enum { MCU_BUTTON_REVERB_R = 17, MCU_BUTTON_LEVEL_L = 18, MCU_BUTTON_LEVEL_R = 19, - MCU_BUTTON_PART_L = 20 + MCU_BUTTON_PART_L = 20, + + // JV880 + MCU_BUTTON_CURSOR_L = 0, + MCU_BUTTON_CURSOR_R = 1, + MCU_BUTTON_TONE_SELECT = 2, + MCU_BUTTON_MUTE = 3, + MCU_BUTTON_DATA = 4, + MCU_BUTTON_MONITOR = 5, + MCU_BUTTON_COMPARE = 6, + MCU_BUTTON_ENTER = 7, + MCU_BUTTON_UTILITY = 8, + MCU_BUTTON_PREVIEW = 9, + MCU_BUTTON_PATCH_PERFORM = 10, + MCU_BUTTON_EDIT = 11, + MCU_BUTTON_SYSTEM = 12, + MCU_BUTTON_RHYTHM = 13, }; @@ -400,6 +417,7 @@ enum { ROM_SET_ST, ROM_SET_MK1, ROM_SET_CM300, + ROM_SET_JV880, ROM_SET_COUNT }; @@ -410,6 +428,7 @@ extern int romset; extern int mcu_mk1; extern int mcu_cm300; extern int mcu_st; +extern int mcu_jv880; extern SDL_atomic_t mcu_button_pressed; @@ -424,6 +443,8 @@ void MCU_WriteP0(uint8_t data); void MCU_WriteP1(uint8_t data); void MCU_GA_SetGAInt(int line, int value); +void MCU_EncoderTrigger(int dir); + void MCU_PostSample(int *sample); void MCU_PostUART(uint8_t data); diff --git a/src/mcu_opcodes.cpp b/src/mcu_opcodes.cpp index 7951359..88b58a4 100644 --- a/src/mcu_opcodes.cpp +++ b/src/mcu_opcodes.cpp @@ -330,6 +330,23 @@ void MCU_Jump_RTS(uint8_t operand) mcu.pc = MCU_PopStack(); } +void MCU_Jump_RTD(uint8_t operand) +{ + int16_t imm = (int8_t)MCU_ReadCodeAdvance(); + mcu.pc = MCU_PopStack(); + + if (operand == 0x14) + { + mcu.r[7] += imm; + if (mcu.r[7] & 1) + MCU_ErrorTrap(); + } + else if (operand == 0x1c) + { + MCU_ErrorTrap(); + } +} + void MCU_Jump_JMP(uint8_t operand) { if (operand == 0x11) @@ -342,6 +359,13 @@ void MCU_Jump_JMP(uint8_t operand) mcu.cp = (uint8_t)MCU_PopStack(); mcu.pc = MCU_PopStack(); } + else if (opcode_h == 0x19) + { + MCU_PushStack(mcu.pc); + MCU_PushStack(mcu.cp); + mcu.cp = mcu.r[opcode_l] & 0xff; + mcu.pc = mcu.r[opcode_l + 1]; + } else if (opcode_h == 0x1a) { mcu.pc = mcu.r[opcode_l]; @@ -1096,6 +1120,22 @@ void MCU_Opcode_BTSTI(uint8_t opcode, uint8_t opcode_reg) } } +void MCU_Opcode_BNOTI(uint8_t opcode, uint8_t opcode_reg) +{ + if (operand_type != GENERAL_IMMEDIATE) + { + uint32_t data = MCU_Operand_Read(); + uint32_t bit = opcode_reg | ((opcode & 1) << 3); + MCU_SetStatus((data & (1 << bit)) == 0, STATUS_Z); + data ^= (1 << bit); + MCU_Operand_Write(data); + } + else + { + MCU_ErrorTrap(); + } +} + void MCU_Opcode_OR(uint8_t opcode, uint8_t opcode_reg) { uint32_t data = MCU_Operand_Read(); @@ -1254,6 +1294,15 @@ void MCU_Opcode_SHLR(uint8_t opcode, uint8_t opcode_reg) MCU_SetStatus(C, STATUS_C); MCU_SetStatusCommon(data, operand_size); } + else if (opcode_reg == 0x01 && operand_type != GENERAL_IMMEDIATE) // SHAR + { + uint32_t data = MCU_Operand_Read(); + uint32_t C = data & 0x1; + data >>= 1; + MCU_Operand_Write(data); + MCU_SetStatus(C, STATUS_C); + MCU_SetStatusCommon(data, operand_size); + } else if (opcode_reg == 0x05 && operand_type != GENERAL_IMMEDIATE) // ROTR { uint32_t data = MCU_Operand_Read(); @@ -1437,7 +1486,7 @@ void (*MCU_Operand_Table[256])(uint8_t operand) = { MCU_Jump_JMP, // 11 MCU_STM, // 12 MCU_Jump_PJMP, // 13 - MCU_Operand_NotImplemented, // 14 + MCU_Jump_RTD, // 14 MCU_Operand_General, // 15 MCU_Operand_NotImplemented, // 16 MCU_Operand_NotImplemented, // 17 @@ -1445,7 +1494,7 @@ void (*MCU_Operand_Table[256])(uint8_t operand) = { MCU_Jump_RTS, // 19 MCU_Operand_Sleep, // 1A MCU_Operand_NotImplemented, // 1B - MCU_Operand_NotImplemented, // 1C + MCU_Jump_RTD, // 1C MCU_Operand_General, // 1D MCU_Jump_BSR, // 1E MCU_Operand_NotImplemented, // 1F @@ -1704,8 +1753,8 @@ void (*MCU_Opcode_Table[32])(uint8_t opcode, uint8_t opcode_reg) = { MCU_Opcode_BSET, // 19 MCU_Opcode_BCLR, // 1A MCU_Opcode_BCLR, // 1B - MCU_Opcode_NotImplemented, // 1C - MCU_Opcode_NotImplemented, // 1D + MCU_Opcode_BNOTI, // 1C + MCU_Opcode_BNOTI, // 1D MCU_Opcode_BTSTI, // 1E MCU_Opcode_BTSTI, // 1F }; diff --git a/src/midi.h b/src/midi.h index 9436620..7a6dbac 100644 --- a/src/midi.h +++ b/src/midi.h @@ -35,4 +35,5 @@ int MIDI_Init(int port); void MIDI_Quit(void); +void MIDI_Update(void); diff --git a/src/midi_portmidi.cpp b/src/midi_portmidi.cpp new file mode 100644 index 0000000..3787abc --- /dev/null +++ b/src/midi_portmidi.cpp @@ -0,0 +1,67 @@ +#include +#include "mcu.h" +#include "submcu.h" +#include "midi.h" +#include + +static PmStream *midiInStream; +static bool sysExMode = false; + +void MIDI_Update() +{ + PmEvent event; + while (Pm_Read(midiInStream, &event, 1)) { + uint8_t command = (Pm_MessageStatus(event.message) >> 4); + + MCU_PostUART(Pm_MessageStatus(event.message)); + + if (sysExMode && Pm_MessageStatus(event.message) == 0xF7) { + sysExMode = false; + } else if (sysExMode || Pm_MessageStatus(event.message) == 0xF0) { + sysExMode = true; + MCU_PostUART(Pm_MessageData1(event.message)); + if (Pm_MessageData1(event.message) == 0xF7) { + sysExMode = false; + return; + } + MCU_PostUART(Pm_MessageData2(event.message)); + if (Pm_MessageData2(event.message) == 0xF7) { + sysExMode = false; + return; + } + MCU_PostUART((((event.message) >> 24) & 0xFF)); + if ((((event.message) >> 24) & 0xFF) == 0xF7) { + sysExMode = false; + return; + } + } else if (command == 0xC || command == 0xD || Pm_MessageStatus(event.message) == 0xF3) { + MCU_PostUART(Pm_MessageData1(event.message)); + } else if (command == 0x8 || command == 0x9 || command == 0xA || command == 0xB || command == 0xE){ + MCU_PostUART(Pm_MessageData1(event.message)); + MCU_PostUART(Pm_MessageData2(event.message)); + } + } +} + +int MIDI_Init(int port) +{ + Pm_Initialize(); + + int in_id = Pm_CreateVirtualInput("Virtual SC55", NULL, NULL); + + Pm_OpenInput(&midiInStream, in_id, NULL, 0, NULL, NULL); + Pm_SetFilter(midiInStream, PM_FILT_ACTIVE | PM_FILT_CLOCK); + + // Empty the buffer, just in case anything got through + PmEvent receiveBuffer[1]; + while (Pm_Poll(midiInStream)) { + Pm_Read(midiInStream, receiveBuffer, 1); + } + + return 1; +} + +void MIDI_Quit() +{ + Pm_Terminate(); +} diff --git a/src/midi_rtmidi.cpp b/src/midi_rtmidi.cpp deleted file mode 100644 index d16036b..0000000 --- a/src/midi_rtmidi.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include "mcu.h" -#include "midi.h" -#include - -static RtMidiIn *s_midi_in = nullptr; - - -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++); -} - -static void MidiOnError(RtMidiError::Type, const std::string &errorText, void *) -{ - fprintf(stderr, "RtMidi: Error has occured: %s\n", errorText.c_str()); - fflush(stderr); -} - -int MIDI_Init(int port) -{ - if (s_midi_in) - { - printf("MIDI already running\n"); - return 0; // Already running - } - - 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 - s_midi_in->setErrorCallback(&MidiOnError, nullptr); - - unsigned count = s_midi_in->getPortCount(); - - if (count == 0) - { - printf("No midi input\n"); - delete s_midi_in; - s_midi_in = nullptr; - return 0; - } - - if (port < 0 || port >= count) - { - printf("Out of range midi port is requested. Defaulting to port 0\n"); - port = 0; - } - - s_midi_in->openPort(port, "Nuked SC55"); - - return 1; -} - -void MIDI_Quit() -{ - if (s_midi_in) - { - s_midi_in->closePort(); - delete s_midi_in; - s_midi_in = nullptr; - } -} diff --git a/src/midi_win32.cpp b/src/midi_win32.cpp index c453aea..9ddd9c3 100644 --- a/src/midi_win32.cpp +++ b/src/midi_win32.cpp @@ -150,3 +150,7 @@ void MIDI_Quit() midi_handle = 0; } } + +void MIDI_Update() +{ +} diff --git a/src/pcm.cpp b/src/pcm.cpp index bcb3ec5..ad16347 100644 --- a/src/pcm.cpp +++ b/src/pcm.cpp @@ -40,8 +40,9 @@ pcm_t pcm; uint8_t waverom1[0x200000]; -uint8_t waverom2[0x100000]; +uint8_t waverom2[0x200000]; uint8_t waverom3[0x100000]; +uint8_t waverom_exp[0x800000]; uint8_t PCM_ReadROM(uint32_t address) { @@ -58,9 +59,19 @@ uint8_t PCM_ReadROM(uint32_t address) else return waverom1[address & 0x1fffff]; case 1: - return waverom2[address & 0xfffff]; + if (!mcu_jv880) + return waverom2[address & 0xfffff]; + else + return waverom2[address & 0x1fffff]; case 2: + if (mcu_jv880) return 0; return waverom3[address & 0xfffff]; + case 3: + case 4: + case 5: + case 6: + if (mcu_jv880) + return waverom_exp[(address & 0x1fffff) + (bank - 3) * 0x200000]; default: break; } @@ -198,7 +209,10 @@ uint8_t PCM_Read(uint32_t address) if (address == 0x3e && pcm.irq_assert) { pcm.irq_assert = 0; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_IRQ0, 0); + if (mcu_jv880) + MCU_GA_SetGAInt(5, 0); + else + MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_IRQ0, 0); } status |= pcm.irq_channel; @@ -1416,7 +1430,10 @@ void PCM_Update(uint64_t cycles) ram2[8] |= 0x4000; pcm.irq_assert = 1; pcm.irq_channel = slot; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_IRQ0, 1); + if (mcu_jv880) + MCU_GA_SetGAInt(5, 1); + else + MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_IRQ0, 1); } int volmul1 = 0; @@ -1547,6 +1564,6 @@ void PCM_Update(uint64_t cycles) pcm.nfs = 1; - pcm.cycles += (reg_slots + 1) * 25; + pcm.cycles += (reg_slots + 1) * (mcu_jv880 ? (25 * 200 / 232) : 25); } } diff --git a/src/pcm.h b/src/pcm.h index 7f136c8..0e53da8 100644 --- a/src/pcm.h +++ b/src/pcm.h @@ -45,7 +45,7 @@ struct pcm_t { uint32_t wave_read_address; uint8_t wave_byte_latch; uint32_t read_latch; - uint8_t config_reg_3c; + uint8_t config_reg_3c; // SC55:c3 JV880:c0 uint8_t config_reg_3d; uint32_t irq_channel; uint32_t irq_assert; @@ -67,6 +67,7 @@ extern pcm_t pcm; extern uint8_t waverom1[]; extern uint8_t waverom2[]; extern uint8_t waverom3[]; +extern uint8_t waverom_exp[]; void PCM_Write(uint32_t address, uint8_t data); uint8_t PCM_Read(uint32_t address);