From 580a9da594d8b5e12ba9655172901350e124658a Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Tue, 23 Apr 2024 20:59:07 -0400 Subject: [PATCH 01/35] WIP: Remove global mcu --- src/lcd.cpp | 10 +- src/lcd.h | 10 +- src/mcu.cpp | 132 ++++----- src/mcu.h | 60 ++-- src/mcu_interrupt.cpp | 34 +-- src/mcu_interrupt.h | 12 +- src/mcu_opcodes.cpp | 670 +++++++++++++++++++++--------------------- src/mcu_opcodes.h | 4 +- src/mcu_timer.cpp | 30 +- src/mcu_timer.h | 8 +- src/pcm.cpp | 12 +- src/pcm.h | 4 +- src/submcu.cpp | 5 +- src/submcu.h | 5 +- 14 files changed, 505 insertions(+), 491 deletions(-) diff --git a/src/lcd.cpp b/src/lcd.cpp index 5667db73..20fec4e1 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -226,13 +226,15 @@ void LCD_SetBackPath(const std::string &path) m_back_path = path; } -void LCD_Init(void) +void LCD_Init(lcd_t& lcd, mcu_t& mcu) { FILE *raw; if(lcd_init) return; + lcd.mcu = &mcu; + lcd_quit_requested = false; std::string title = "Nuked SC-55: "; @@ -407,7 +409,7 @@ void LCD_FontRenderLR(uint8_t ch) } } -void LCD_Update(void) +void LCD_Update(lcd_t& lcd) { if (!lcd_init) return; @@ -525,9 +527,9 @@ void LCD_Update(void) if (sdl_event.type == SDL_KEYDOWN) { if (sdl_event.key.keysym.scancode == SDL_SCANCODE_COMMA) - MCU_EncoderTrigger(0); + MCU_EncoderTrigger(*lcd.mcu, 0); if (sdl_event.key.keysym.scancode == SDL_SCANCODE_PERIOD) - MCU_EncoderTrigger(1); + MCU_EncoderTrigger(*lcd.mcu, 1); } switch (sdl_event.type) diff --git a/src/lcd.h b/src/lcd.h index a9982a87..29c81e8a 100644 --- a/src/lcd.h +++ b/src/lcd.h @@ -36,14 +36,20 @@ #include #include +struct mcu_t; + +struct lcd_t { + mcu_t* mcu; +}; + extern int lcd_width; extern int lcd_height; void LCD_SetBackPath(const std::string &path); -void LCD_Init(void); +void LCD_Init(lcd_t& lcd, mcu_t& mcu); void LCD_UnInit(void); void LCD_Write(uint32_t address, uint8_t data); void LCD_Enable(uint32_t enable); bool LCD_QuitRequested(); void LCD_Sync(void); -void LCD_Update(void); +void LCD_Update(lcd_t& lcd); diff --git a/src/mcu.cpp b/src/mcu.cpp index e4105594..d2e7ecc5 100644 --- a/src/mcu.cpp +++ b/src/mcu.cpp @@ -140,7 +140,7 @@ 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); } @@ -293,17 +293,17 @@ 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, address, data); return; } if (address >= 0x50 && address < 0x55) { - TIMER2_Write(address, data); + TIMER2_Write(mcu, address, data); return; } switch (address) @@ -377,10 +377,10 @@ void MCU_DeviceWrite(uint32_t address, uint8_t data) if ((data & 0x80) == 0 && adf_rd) { dev_register[address] &= ~0x80; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_ANALOG, 0); + 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: @@ -389,13 +389,13 @@ void MCU_DeviceWrite(uint32_t address, uint8_t data) { dev_register[address] &= ~0x80; uart_tx_delay = mcu.cycles + 3000; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_UART_TX, 0); + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_UART_TX, 0); } if ((data & 0x40) == 0 && (ssr_rd & 0x40) != 0) { uart_rx_delay = mcu.cycles + 3000; dev_register[address] &= ~0x40; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_UART_RX, 0); + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_UART_RX, 0); } if ((data & 0x20) == 0 && (ssr_rd & 0x20) != 0) { @@ -504,7 +504,7 @@ void MCU_DeviceReset(void) 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 isscan = (ctrl & 16) != 0; @@ -530,15 +530,13 @@ void MCU_UpdateAnalog(uint64_t cycles) } 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_t mcu; - uint8_t rom1[ROM1_SIZE]; uint8_t rom2[ROM2_SIZE]; uint8_t ram[RAM_SIZE]; @@ -548,7 +546,7 @@ 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) @@ -568,7 +566,7 @@ uint8_t MCU_Read(uint32_t address) uint16_t base = mcu_jv880 ? 0xf000 : 0xe000; if (address >= base && address < (base | 0x400)) { - ret = PCM_Read(address & 0x3f); + ret = PCM_Read(mcu, address & 0x3f); } else if (!mcu_scb55 && address >= 0xec00 && address < 0xf000) { @@ -589,7 +587,7 @@ uint8_t MCU_Read(uint32_t address) { ret = ga_int_trigger; ga_int_trigger = 0; - MCU_Interrupt_SetRequest(mcu_jv880 ? INTERRUPT_SOURCE_IRQ0 : INTERRUPT_SOURCE_IRQ1, 0); + MCU_Interrupt_SetRequest(mcu, mcu_jv880 ? INTERRUPT_SOURCE_IRQ0 : INTERRUPT_SOURCE_IRQ1, 0); } else { @@ -604,7 +602,7 @@ uint8_t MCU_Read(uint32_t address) { if (address >= 0xe000 && address < 0xe040) { - ret = PCM_Read(address & 0x3f); + ret = PCM_Read(mcu, address & 0x3f); } else if (address >= 0xff80) { @@ -645,7 +643,7 @@ uint8_t MCU_Read(uint32_t address) { ret = ga_int_trigger; ga_int_trigger = 0; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_IRQ1, 0); + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_IRQ1, 0); } else { @@ -730,27 +728,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; @@ -795,7 +793,7 @@ void MCU_Write(uint32_t address, uint8_t 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) @@ -819,7 +817,7 @@ void MCU_Write(uint32_t address, uint8_t 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) @@ -882,31 +880,31 @@ 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_Init(mcu_t& mcu) { memset(&mcu, 0, sizeof(mcu_t)); } -void MCU_Reset(void) +void MCU_Reset(mcu_t& mcu) { mcu.r[0] = 0; mcu.r[1] = 0; @@ -927,7 +925,7 @@ 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; @@ -947,7 +945,7 @@ void MCU_PostUART(uint8_t data) uart_write_ptr = (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 return; @@ -963,11 +961,11 @@ void MCU_UpdateUART_RX(void) 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_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_UART_RX, (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 return; @@ -979,7 +977,7 @@ void MCU_UpdateUART_TX(void) return; dev_register[DEV_SSR] |= 0x80; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_UART_TX, (dev_register[DEV_SCR] & 0x80) != 0); + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_UART_TX, (dev_register[DEV_SCR] & 0x80) != 0); // printf("tx:%x\n", dev_register[DEV_TDR]); } @@ -1000,6 +998,7 @@ void MCU_WorkThread_Unlock(void) int SDLCALL work_thread(void* data) { + mcu_t& mcu = *(mcu_t*)data; work_thread_lock = SDL_CreateMutex(); MCU_WorkThread_Lock(); @@ -1020,31 +1019,31 @@ int SDLCALL work_thread(void* data) } if (!mcu.ex_ignore) - MCU_Interrupt_Handle(); + MCU_Interrupt_Handle(mcu); else mcu.ex_ignore = 0; if (!mcu.sleep) - MCU_ReadInstruction(); + MCU_ReadInstruction(mcu); mcu.cycles += 12; // FIXME: assume 12 cycles per instruction // if (mcu.cycles % 24000000 == 0) // printf("seconds: %i\n", (int)(mcu.cycles / 24000000)); - PCM_Update(mcu.cycles); + PCM_Update(mcu, mcu.cycles); - TIMER_Clock(mcu.cycles); + TIMER_Clock(mcu, mcu.cycles); if (!mcu_mk1 && !mcu_jv880 && !mcu_scb55) SM_Update(mcu.cycles); else { - MCU_UpdateUART_RX(); - MCU_UpdateUART_TX(); + MCU_UpdateUART_RX(mcu); + MCU_UpdateUART_TX(mcu); } - MCU_UpdateAnalog(mcu.cycles); + MCU_UpdateAnalog(mcu, mcu.cycles); if (mcu_mk1) { @@ -1053,8 +1052,8 @@ int SDLCALL work_thread(void* data) 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); } } } @@ -1066,19 +1065,19 @@ int SDLCALL work_thread(void* data) return 0; } -static void MCU_Run() +static void MCU_Run(mcu_t& mcu, lcd_t& lcd) { bool working = true; work_thread_run = true; - SDL_Thread *thread = SDL_CreateThread(work_thread, "work thread", 0); + SDL_Thread *thread = SDL_CreateThread(work_thread, "work thread", &mcu); while (working) { if(LCD_QuitRequested()) working = false; - LCD_Update(); + LCD_Update(lcd); SDL_Delay(15); } @@ -1281,7 +1280,7 @@ void MCU_PostSample(int *sample) sample_write_ptr = (sample_write_ptr + 2) % audio_buffer_size; } -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) @@ -1289,16 +1288,16 @@ void MCU_GA_SetGAInt(int line, int value) ga_int[line] = value; if (mcu_jv880) - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_IRQ0, ga_int_trigger != 0); + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_IRQ0, ga_int_trigger != 0); else - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_IRQ1, ga_int_trigger != 0); + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_IRQ1, ga_int_trigger != 0); } -void MCU_EncoderTrigger(int dir) +void MCU_EncoderTrigger(mcu_t& mcu, int dir) { if (!mcu_jv880) return; - MCU_GA_SetGAInt(dir == 0 ? 3 : 4, 0); - MCU_GA_SetGAInt(dir == 0 ? 3 : 4, 1); + MCU_GA_SetGAInt(mcu, dir == 0 ? 3 : 4, 0); + MCU_GA_SetGAInt(mcu, dir == 0 ? 3 : 4, 1); } @@ -1593,8 +1592,9 @@ int main(int argc, char *argv[]) LCD_SetBackPath(basePath + "/back.data"); + mcu_t mcu; memset(&mcu, 0, sizeof(mcu_t)); - + lcd_t lcd; if (fread(rom1, 1, ROM1_SIZE, s_rf[0]) != ROM1_SIZE) { @@ -1734,16 +1734,16 @@ int main(int argc, char *argv[]) fflush(stderr); } - LCD_Init(); - MCU_Init(); + LCD_Init(lcd, mcu); + MCU_Init(mcu); MCU_PatchROM(); - MCU_Reset(); - SM_Reset(); + MCU_Reset(mcu); + SM_Reset(mcu); PCM_Reset(); if (resetType != ResetType::NONE) MIDI_Reset(resetType); - MCU_Run(); + MCU_Run(mcu, lcd); MCU_CloseAudio(); MIDI_Quit(); diff --git a/src/mcu.h b/src/mcu.h index ba490678..d321abea 100644 --- a/src/mcu.h +++ b/src/mcu.h @@ -188,41 +188,39 @@ struct mcu_t { uint64_t cycles; }; -extern mcu_t mcu; +void MCU_ErrorTrap(mcu_t& mcu); -void MCU_ErrorTrap(void); - -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 +229,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 +252,7 @@ inline void MCU_ControlRegisterWrite(uint32_t reg, uint32_t siz, uint32_t data) } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } } else @@ -283,12 +281,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 +309,7 @@ inline uint32_t MCU_ControlRegisterRead(uint32_t reg, uint32_t siz) } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } ret &= 0xffff; } @@ -339,14 +337,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 +352,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; } @@ -464,9 +462,9 @@ 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); +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); diff --git a/src/mcu_interrupt.cpp b/src/mcu_interrupt.cpp index edb517ed..6ae82ca2 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,12 +49,12 @@ 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) @@ -65,20 +65,20 @@ void MCU_Interrupt_Exception(uint32_t exception) 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; @@ -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..9c1cac92 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,38 +455,38 @@ 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; } @@ -500,7 +500,7 @@ 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) { @@ -514,18 +514,18 @@ uint32_t MCU_Operand_Read(void) { if (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(operand_ep, operand_ea)); } - return MCU_Read(MCU_GetAddress(operand_ep, operand_ea)); + return MCU_Read(mcu, MCU_GetAddress(operand_ep, operand_ea)); case GENERAL_IMMEDIATE: return operand_data; } return 0; } -void MCU_Operand_Write(uint32_t data) +void MCU_Operand_Write(mcu_t& mcu, uint32_t data) { switch (operand_type) { @@ -544,20 +544,20 @@ void MCU_Operand_Write(uint32_t data) { if (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(operand_ep, operand_ea), data); } else - MCU_Write(MCU_GetAddress(operand_ep, operand_ea), data); + MCU_Write(mcu, MCU_GetAddress(operand_ep, 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 +587,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 +608,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 +626,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 +660,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,11 +669,11 @@ void MCU_Operand_General(uint8_t operand) ep = addrpage & 0xff; } - opcode = MCU_ReadCodeAdvance(); + opcode = MCU_ReadCodeAdvance(mcu); opcode_extended = opcode == 0x00; if (opcode_extended) { - opcode = MCU_ReadCodeAdvance(); + opcode = MCU_ReadCodeAdvance(mcu); } opcode_reg = opcode & 0x07; opcode >>= 3; @@ -686,52 +686,52 @@ void MCU_Operand_General(uint8_t operand) operand_data = data; 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 +739,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,224 +757,224 @@ 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)) { - 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, operand_size); } else if (opcode_reg == 7 && (operand_type == GENERAL_INDIRECT || 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, operand_size); } else if (opcode_reg == 4 && (operand_type == GENERAL_INDIRECT || operand_type == GENERAL_ABSOLUTE) && 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 { - 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) { 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 { 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 { - 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, operand_size); val |= data; - MCU_ControlRegisterWrite(opcode_reg, operand_size, val); + MCU_ControlRegisterWrite(mcu, opcode_reg, operand_size, val); if (opcode_reg >= 2) { - MCU_SetStatusCommon(val, operand_size); + MCU_SetStatusCommon(mcu, val, 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 { - 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, operand_size); val &= data; - MCU_ControlRegisterWrite(opcode_reg, operand_size, val); + MCU_ControlRegisterWrite(mcu, opcode_reg, operand_size, val); if (opcode_reg >= 2) { - MCU_SetStatusCommon(val, operand_size); + MCU_SetStatusCommon(mcu, val, 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) { - 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 { - 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 { - 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, operand_size); + MCU_SetStatus(mcu, 0, STATUS_C); } else if (opcode_reg == 2 && operand_type == GENERAL_DIRECT && 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); + 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 { @@ -983,91 +983,91 @@ void MCU_Opcode_CLR(uint8_t opcode, uint8_t opcode_reg) 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_SetStatusCommon(mcu, data, OPERAND_BYTE); // FIXME: might be WORD??? //MCU_SetStatusCommon(data, OPERAND_WORD); } else if (opcode_reg == 5 && 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, operand_size); } else if (opcode_reg == 4 && 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, operand_size); + MCU_Operand_Write(mcu, data); } else if (opcode_reg == 1 && operand_type == GENERAL_DIRECT && operand_size == 0) // EXTS { uint32_t data = mcu.r[operand_reg]; mcu.r[operand_reg] = (int8_t)data; - MCU_SetStatusCommon(data, OPERAND_WORD); + 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, 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, 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) { - 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) { - 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 (opcode == 0x12) { // FIXME - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } else { - MCU_ErrorTrap(); + MCU_ErrorTrap(mcu); } } else @@ -1087,19 +1087,19 @@ void MCU_Opcode_MOVG(uint8_t opcode, uint8_t opcode_reg) } 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, operand_size); } } else { - data = MCU_Operand_Read(); + data = MCU_Operand_Read(mcu); if (operand_size) mcu.r[opcode_reg] = data; else @@ -1107,58 +1107,58 @@ void MCU_Opcode_MOVG(uint8_t opcode, uint8_t opcode_reg) mcu.r[opcode_reg] &= ~0xff; mcu.r[opcode_reg] |= data & 0xff; } - MCU_SetStatusCommon(data, operand_size); + MCU_SetStatusCommon(mcu, data, 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) { - 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) { - 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], 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, 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,18 +1175,18 @@ 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, 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); + int32_t t2 = MCU_Operand_Read(mcu); + t1 = MCU_ADD_Common(mcu, t1, t2, 0, operand_size); if (operand_size) mcu.r[opcode_reg] = t1; else @@ -1196,11 +1196,11 @@ 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); + int32_t t2 = MCU_Operand_Read(mcu); + t1 = MCU_SUB_Common(mcu, t1, t2, 0, operand_size); if (operand_size) mcu.r[opcode_reg] = t1; else @@ -1210,20 +1210,20 @@ 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(); + int32_t t2 = MCU_Operand_Read(mcu); if (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(); + data &= MCU_Operand_Read(mcu); if (operand_size) mcu.r[opcode_reg] = data; else @@ -1231,36 +1231,36 @@ void MCU_Opcode_AND(uint8_t opcode, uint8_t opcode_reg) 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], 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 { - 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, operand_size); } else if (opcode_reg == 0x02 && operand_type != GENERAL_IMMEDIATE) // SHLL { - uint32_t data = MCU_Operand_Read(); + uint32_t data = MCU_Operand_Read(mcu); uint32_t C; if (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, operand_size); } else if (opcode_reg == 0x06 && 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) @@ -1269,13 +1269,13 @@ void MCU_Opcode_SHLR(uint8_t opcode, uint8_t opcode_reg) 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, operand_size); } else if (opcode_reg == 0x04 && operand_type != GENERAL_IMMEDIATE) // ROTL { - uint32_t data = MCU_Operand_Read(); + uint32_t data = MCU_Operand_Read(mcu); uint32_t C; if (operand_size) C = (data & 0x8000) != 0; @@ -1283,26 +1283,26 @@ void MCU_Opcode_SHLR(uint8_t opcode, uint8_t opcode_reg) 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, operand_size); } else if (opcode_reg == 0x00 && operand_type != GENERAL_IMMEDIATE) // SHAL { - uint32_t data = MCU_Operand_Read(); + uint32_t data = MCU_Operand_Read(mcu); uint32_t C; if (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, operand_size); } else if (opcode_reg == 0x01 && 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) @@ -1317,32 +1317,32 @@ 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, operand_size); } else if (opcode_reg == 0x05 && 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) 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, 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) @@ -1363,25 +1363,25 @@ 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; } @@ -1396,17 +1396,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,46 +1418,46 @@ 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(); + uint32_t data = MCU_Operand_Read(mcu); if (!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], 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, operand_size); if (!Z) - MCU_SetStatus(0, STATUS_Z); + MCU_SetStatus(mcu, 0, STATUS_Z); if (operand_size) mcu.r[opcode_reg] = t1; @@ -1468,12 +1468,12 @@ 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); + t1 = MCU_SUB_Common(mcu, t1, t2, C, operand_size); if (operand_size) mcu.r[opcode_reg] = t1; else @@ -1483,7 +1483,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 +1742,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..bb18ae44 100644 --- a/src/mcu_timer.cpp +++ b/src/mcu_timer.cpp @@ -63,7 +63,7 @@ void TIMER_Reset(void) memset(&timer, 0, sizeof(timer)); } -void TIMER_Write(uint32_t address, uint8_t data) +void TIMER_Write(mcu_t& mcu, uint32_t address, uint8_t data) { uint32_t t = (address >> 4) - 1; if (t > 2) @@ -82,19 +82,19 @@ void TIMER_Write(uint32_t address, uint8_t data) { timer->tcsr &= ~0x10; timer->status_rd &= ~0x10; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_FRT0_FOVI + t * 4, 0); + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_FRT0_FOVI + t * 4, 0); } if ((data & 0x20) == 0 && (timer->status_rd & 0x20) != 0) { timer->tcsr &= ~0x20; timer->status_rd &= ~0x20; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_FRT0_OCIA + t * 4, 0); + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_FRT0_OCIA + t * 4, 0); } if ((data & 0x40) == 0 && (timer->status_rd & 0x40) != 0) { timer->tcsr &= ~0x40; timer->status_rd &= ~0x40; - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_FRT0_OCIB + t * 4, 0); + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_FRT0_OCIB + t * 4, 0); } break; case REG_FRCH: @@ -157,7 +157,7 @@ uint8_t TIMER_Read(uint32_t address) return 0xff; } -void TIMER2_Write(uint32_t address, uint8_t data) +void TIMER2_Write(mcu_t& mcu, uint32_t address, uint8_t data) { switch (address) { @@ -171,19 +171,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(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(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(mcu, INTERRUPT_SOURCE_TIMER_CMIB, 0); } break; case DEV_TMR_TCORA: @@ -219,7 +219,7 @@ uint8_t TIMER_Read2(uint32_t address) return 0xff; } -void TIMER_Clock(uint64_t cycles) +void TIMER_Clock(mcu_t& mcu, uint64_t cycles) { uint32_t i; while (timer_cycles*2 < cycles) // FIXME @@ -276,11 +276,11 @@ void TIMER_Clock(uint64_t cycles) if (matchb) timer->tcsr |= 0x40; if ((timer->tcr & 0x10) != 0 && (timer->tcsr & 0x10) != 0) - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_FRT0_FOVI + i * 4, 1); + MCU_Interrupt_SetRequest(mcu, 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); + MCU_Interrupt_SetRequest(mcu, 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); + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_FRT0_OCIB + i * 4, 1); } int32_t timer_step = 0; @@ -340,11 +340,11 @@ 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(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(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(mcu, INTERRUPT_SOURCE_TIMER_CMIB, 1); } timer_cycles++; diff --git a/src/mcu_timer.h b/src/mcu_timer.h index 41e0eb1d..211b84a1 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; @@ -53,10 +55,10 @@ struct mcu_timer_t { uint8_t status_rd; }; -void TIMER_Write(uint32_t address, uint8_t data); +void TIMER_Write(mcu_t& mcu, uint32_t address, uint8_t data); uint8_t TIMER_Read(uint32_t address); -void TIMER_Clock(uint64_t cycles); +void TIMER_Clock(mcu_t& mcu, uint64_t cycles); -void TIMER2_Write(uint32_t address, uint8_t data); +void TIMER2_Write(mcu_t& mcu, uint32_t address, uint8_t data); uint8_t TIMER_Read2(uint32_t address); diff --git a/src/pcm.cpp b/src/pcm.cpp index cb05f90a..c6a37c9a 100644 --- a/src/pcm.cpp +++ b/src/pcm.cpp @@ -192,7 +192,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(mcu_t& mcu, uint32_t address) { address &= 0x3f; //printf("PCM Read: %.2x\n", address); @@ -210,9 +210,9 @@ uint8_t PCM_Read(uint32_t address) { pcm.irq_assert = 0; if (mcu_jv880) - MCU_GA_SetGAInt(5, 0); + MCU_GA_SetGAInt(mcu, 5, 0); else - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_IRQ0, 0); + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_IRQ0, 0); } status |= pcm.irq_channel; @@ -522,7 +522,7 @@ inline void eram_pack(int addr, int val) pcm.eram[addr] = data; } -void PCM_Update(uint64_t cycles) +void PCM_Update(mcu_t& mcu, uint64_t cycles) { int reg_slots = (pcm.config_reg_3d & 31) + 1; int voice_active = pcm.voice_mask & pcm.voice_mask_pending; @@ -1434,9 +1434,9 @@ void PCM_Update(uint64_t cycles) pcm.irq_assert = 1; pcm.irq_channel = slot; if (mcu_jv880) - MCU_GA_SetGAInt(5, 1); + MCU_GA_SetGAInt(mcu, 5, 1); else - MCU_Interrupt_SetRequest(INTERRUPT_SOURCE_IRQ0, 1); + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_IRQ0, 1); } int volmul1 = 0; diff --git a/src/pcm.h b/src/pcm.h index 0e53da83..a0aae9e4 100644 --- a/src/pcm.h +++ b/src/pcm.h @@ -70,6 +70,6 @@ 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); +uint8_t PCM_Read(mcu_t& mcu, uint32_t address); void PCM_Reset(void); -void PCM_Update(uint64_t cycles); +void PCM_Update(mcu_t& mcu, uint64_t cycles); diff --git a/src/submcu.cpp b/src/submcu.cpp index 557b18e7..9d67ec69 100644 --- a/src/submcu.cpp +++ b/src/submcu.cpp @@ -216,7 +216,7 @@ void SM_Write(uint16_t address, uint8_t 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 + MCU_GA_SetGAInt(*sm.mcu, 5, (sm_device_mode[SM_DEV_UART3_MODE_STATUS] & 0x80) != 0 && (sm_device_mode[SM_DEV_UART3_CTRL] & 0x20) == 0); } else if (address >= 0x200 && address < 0x2c0) @@ -329,10 +329,11 @@ void SM_SetStatus(uint32_t condition, uint32_t mask) sm.sr &= ~mask; } -void SM_Reset(void) +void SM_Reset(mcu_t& mcu) { memset(&sm, 0, sizeof(sm)); sm.pc = SM_GetVectorAddress(SM_VECTOR_RESET); + sm.mcu = &mcu; } uint8_t SM_ReadAdvance(void) diff --git a/src/submcu.h b/src/submcu.h index d6c7feeb..519d0e76 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,13 +56,14 @@ struct submcu_t { uint8_t sr; uint64_t cycles; uint8_t sleep; + mcu_t* mcu; }; extern submcu_t sm; extern uint8_t sm_rom[4096]; -void SM_Reset(void); +void SM_Reset(mcu_t& mcu); void SM_Update(uint64_t cycles); void SM_SysWrite(uint32_t address, uint8_t data); uint8_t SM_SysRead(uint32_t address); From a299648b3ecb6d7392b005a86f304ca6f32c9a93 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Tue, 23 Apr 2024 21:31:27 -0400 Subject: [PATCH 02/35] WIP: move global memory into mcu_t This also reorders main() so that the mcu_t structure isn't zeroed after loading ROMs. ROM loading will probably need to be extracted from main at some point, especially for library usage. --- src/mcu.cpp | 71 ++++++++++++++++++++--------------------------------- src/mcu.h | 14 +++++++++++ 2 files changed, 41 insertions(+), 44 deletions(-) diff --git a/src/mcu.cpp b/src/mcu.cpp index d2e7ecc5..b1896d46 100644 --- a/src/mcu.cpp +++ b/src/mcu.cpp @@ -122,15 +122,6 @@ const char* roms[ROM_SET_COUNT][5] = 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; @@ -537,13 +528,6 @@ void MCU_UpdateAnalog(mcu_t& mcu, uint64_t cycles) analog_end_time = 0; } -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(mcu_t& mcu, uint32_t address) @@ -558,7 +542,7 @@ uint8_t MCU_Read(mcu_t& mcu, uint32_t address) { case 0: if (!(address & 0x8000)) - ret = rom1[address & 0x7fff]; + ret = mcu.rom1[address & 0x7fff]; else { if (!mcu_mk1) @@ -578,10 +562,10 @@ uint8_t MCU_Read(mcu_t& mcu, uint32_t address) } else if (address >= 0xfb80 && address < 0xff80 && (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 == (base | 0x402)) { @@ -611,11 +595,11 @@ uint8_t MCU_Read(mcu_t& mcu, uint32_t address) else if (address >= 0xfb80 && address < 0xff80 && (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) { @@ -671,53 +655,53 @@ uint8_t MCU_Read(mcu_t& mcu, uint32_t address) break; #endif case 1: - ret = rom2[address_rom & rom2_mask]; + ret = mcu.rom2[address_rom & rom2_mask]; break; case 2: - ret = rom2[address_rom & rom2_mask]; + ret = mcu.rom2[address_rom & rom2_mask]; break; case 3: - ret = rom2[address_rom & rom2_mask]; + ret = mcu.rom2[address_rom & rom2_mask]; break; case 4: - ret = rom2[address_rom & rom2_mask]; + ret = mcu.rom2[address_rom & rom2_mask]; break; case 8: if (!mcu_jv880) - ret = rom2[address_rom & rom2_mask]; + ret = mcu.rom2[address_rom & rom2_mask]; else ret = 0xff; break; case 9: if (!mcu_jv880) - ret = rom2[address_rom & rom2_mask]; + ret = mcu.rom2[address_rom & rom2_mask]; else ret = 0xff; break; case 14: case 15: if (!mcu_jv880) - ret = rom2[address_rom & rom2_mask]; + ret = mcu.rom2[address_rom & 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 + ret = mcu.sram[address & 0x7fff]; // FIXME else ret = 0xff; break; case 12: case 13: if (mcu_jv880) - ret = nvram[address & 0x7fff]; // FIXME + ret = mcu.nvram[address & 0x7fff]; // FIXME else ret = 0xff; break; case 5: if (mcu_mk1) - ret = sram[address & 0x7fff]; // FIXME + ret = mcu.sram[address & 0x7fff]; // FIXME else ret = 0xff; break; @@ -798,11 +782,11 @@ void MCU_Write(mcu_t& mcu, uint32_t address, uint8_t value) else if (address >= 0xfb80 && address < 0xff80 && (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 { @@ -822,11 +806,11 @@ void MCU_Write(mcu_t& mcu, uint32_t address, uint8_t value) else if (address >= 0xfb80 && address < 0xff80 && (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) { @@ -860,19 +844,19 @@ void MCU_Write(mcu_t& mcu, uint32_t address, uint8_t value) } else if (page == 5 && mcu_mk1) { - sram[address & 0x7fff] = value; // FIXME + mcu.sram[address & 0x7fff] = value; // FIXME } else if (page == 10 && !mcu_mk1) { - sram[address & 0x7fff] = value; // FIXME + mcu.sram[address & 0x7fff] = value; // FIXME } else if (page == 12 && mcu_jv880) { - nvram[address & 0x7fff] = value; // FIXME + mcu.nvram[address & 0x7fff] = value; // FIXME } else if (page == 14 && mcu_jv880) { - cardram[address & 0x7fff] = value; // FIXME + mcu.cardram[address & 0x7fff] = value; // FIXME } else { @@ -1593,10 +1577,10 @@ int main(int argc, char *argv[]) LCD_SetBackPath(basePath + "/back.data"); mcu_t mcu; - memset(&mcu, 0, sizeof(mcu_t)); + MCU_Init(mcu); lcd_t lcd; - if (fread(rom1, 1, ROM1_SIZE, s_rf[0]) != ROM1_SIZE) + if (fread(mcu.rom1, 1, ROM1_SIZE, s_rf[0]) != ROM1_SIZE) { fprintf(stderr, "FATAL ERROR: Failed to read the mcu ROM1.\n"); fflush(stderr); @@ -1604,7 +1588,7 @@ int main(int argc, char *argv[]) return 1; } - size_t rom2_read = fread(rom2, 1, ROM2_SIZE, s_rf[1]); + size_t rom2_read = fread(mcu.rom2, 1, ROM2_SIZE, s_rf[1]); if (rom2_read == ROM2_SIZE || rom2_read == ROM2_SIZE / 2) { @@ -1735,7 +1719,6 @@ int main(int argc, char *argv[]) } LCD_Init(lcd, mcu); - MCU_Init(mcu); MCU_PatchROM(); MCU_Reset(mcu); SM_Reset(mcu); diff --git a/src/mcu.h b/src/mcu.h index d321abea..e870b00f 100644 --- a/src/mcu.h +++ b/src/mcu.h @@ -174,6 +174,13 @@ 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; struct mcu_t { uint16_t r[8]; @@ -186,6 +193,13 @@ 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]; }; void MCU_ErrorTrap(mcu_t& mcu); From 123ca81fd1655e9464cad1546e29a4891c877a7f Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Tue, 23 Apr 2024 21:47:09 -0400 Subject: [PATCH 03/35] Move more mcu state into mcu_t --- src/mcu.cpp | 155 ++++++++++++++++++++---------------------- src/mcu.h | 9 ++- src/mcu_interrupt.cpp | 42 ++++++------ 3 files changed, 102 insertions(+), 104 deletions(-) diff --git a/src/mcu.cpp b/src/mcu.cpp index b1896d46..49918087 100644 --- a/src/mcu.cpp +++ b/src/mcu.cpp @@ -148,14 +148,6 @@ 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) @@ -173,7 +165,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 @@ -187,7 +179,7 @@ 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) return 0; @@ -208,14 +200,14 @@ uint16_t MCU_AnalogReadPin(uint32_t pin) } if (mcu_mk1) { - if (mcu_sc155 && (dev_register[DEV_P9DR] & 1) != 0) + if (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_sc155 && (mcu.dev_register[DEV_P9DR] & 2) != 0) + return MCU_SC155Sliders(mcu, 8); else return ANALOG_LEVEL_BATTERY; } @@ -224,24 +216,24 @@ uint16_t MCU_AnalogReadPin(uint32_t pin) } else { - if (mcu_sc155 && (io_sd & 16) != 0) + if (mcu_sc155 && (mcu.io_sd & 16) != 0) { - return MCU_SC155Sliders(pin); + return MCU_SC155Sliders(mcu, pin); } if (pin == 7) { if (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); + return MCU_SC155Sliders(mcu, 8); return 0; case 2: // SW - switch (sw_pos) + switch (mcu.sw_pos) { case 0: default: @@ -262,12 +254,12 @@ 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; @@ -363,11 +355,11 @@ void MCU_DeviceWrite(mcu_t& mcu, uint32_t address, uint8_t data) break; case DEV_ADCSR: { - dev_register[address] &= ~0x7f; - dev_register[address] |= data & 0x7f; + mcu.dev_register[address] &= ~0x7f; + mcu.dev_register[address] |= data & 0x7f; if ((data & 0x80) == 0 && adf_rd) { - dev_register[address] &= ~0x80; + mcu.dev_register[address] &= ~0x80; MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_ANALOG, 0); } if ((data & 0x40) == 0) @@ -378,23 +370,23 @@ void MCU_DeviceWrite(mcu_t& mcu, uint32_t address, uint8_t data) { if ((data & 0x80) == 0 && (ssr_rd & 0x80) != 0) { - dev_register[address] &= ~0x80; + mcu.dev_register[address] &= ~0x80; uart_tx_delay = mcu.cycles + 3000; MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_UART_TX, 0); } if ((data & 0x40) == 0 && (ssr_rd & 0x40) != 0) { uart_rx_delay = mcu.cycles + 3000; - dev_register[address] &= ~0x40; + mcu.dev_register[address] &= ~0x40; MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_UART_RX, 0); } if ((data & 0x20) == 0 && (ssr_rd & 0x20) != 0) { - dev_register[address] &= ~0x20; + mcu.dev_register[address] &= ~0x20; } if ((data & 0x10) == 0 && (ssr_rd & 0x10) != 0) { - dev_register[address] &= ~0x10; + mcu.dev_register[address] &= ~0x10; } break; } @@ -402,10 +394,10 @@ void MCU_DeviceWrite(mcu_t& mcu, 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) @@ -426,13 +418,13 @@ 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]; + 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]; + ssr_rd = mcu.dev_register[address]; + return mcu.dev_register[address]; case DEV_RDR: return uart_rx_byte; case 0x00: @@ -444,11 +436,11 @@ uint8_t MCU_DeviceRead(uint32_t address) uint8_t data = 0xff; uint32_t button_pressed = (uint32_t)SDL_AtomicGet(&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; @@ -460,16 +452,16 @@ uint8_t MCU_DeviceRead(uint32_t address) if (!mcu_mk1) cfg = 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: @@ -482,22 +474,22 @@ 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(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) @@ -510,16 +502,16 @@ void MCU_UpdateAnalog(mcu_t& mcu, uint64_t cycles) { int base = ctrl & 4; for (int i = 0; i <= (ctrl & 3); i++) - MCU_AnalogSample(base + i); + MCU_AnalogSample(mcu, base + i); analog_end_time = cycles + 200; } else { - MCU_AnalogSample(ctrl & 7); - dev_register[DEV_ADCSR] &= ~0x20; + MCU_AnalogSample(mcu, ctrl & 7); + mcu.dev_register[DEV_ADCSR] &= ~0x20; analog_end_time = 0; } - dev_register[DEV_ADCSR] |= 0x80; + mcu.dev_register[DEV_ADCSR] |= 0x80; if (ctrl & 0x40) MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_ANALOG, 1); } @@ -558,10 +550,10 @@ uint8_t MCU_Read(mcu_t& mcu, uint32_t address) } 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 = mcu.ram[(address - 0xfb80) & 0x3ff]; else if (address >= 0x8000 && address < 0xe000) { @@ -590,10 +582,10 @@ uint8_t MCU_Read(mcu_t& mcu, uint32_t address) } 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 = mcu.ram[(address - 0xfb80) & 0x3ff]; } @@ -603,23 +595,23 @@ uint8_t MCU_Read(mcu_t& mcu, uint32_t address) } else if (address >= 0xf000 && address < 0xf100) { - io_sd = address & 0xff; + mcu.io_sd = address & 0xff; if (mcu_cm300) return 0xff; - LCD_Enable((io_sd & 8) != 0); + LCD_Enable((mcu.io_sd & 8) != 0); uint8_t data = 0xff; uint32_t button_pressed = (uint32_t)SDL_AtomicGet(&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; } @@ -749,7 +741,7 @@ void MCU_Write(mcu_t& mcu, uint32_t address, uint8_t value) LCD_Write(address & 1, value); else if (address == (base | 0x401)) { - io_sd = value; + mcu.io_sd = value; LCD_Enable((value & 1) == 0); } else if (address == (base | 0x402)) @@ -780,7 +772,7 @@ void MCU_Write(mcu_t& mcu, uint32_t address, uint8_t 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) { mcu.ram[(address - 0xfb80) & 0x3ff] = value; } @@ -804,7 +796,7 @@ void MCU_Write(mcu_t& mcu, uint32_t address, uint8_t 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) { mcu.ram[(address - 0xfb80) & 0x3ff] = value; } @@ -814,8 +806,8 @@ void MCU_Write(mcu_t& mcu, uint32_t address, uint8_t 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.io_sd & 8) != 0); } else if (address == 0xf105) { @@ -829,7 +821,7 @@ void MCU_Write(mcu_t& mcu, uint32_t address, uint8_t value) } else if (address == 0xf107) { - io_sd = value; + mcu.io_sd = value; } else { @@ -886,6 +878,7 @@ void MCU_ReadInstruction(mcu_t& mcu) void MCU_Init(mcu_t& mcu) { memset(&mcu, 0, sizeof(mcu_t)); + mcu.sw_pos = 3; } void MCU_Reset(mcu_t& mcu) @@ -915,7 +908,7 @@ void MCU_Reset(mcu_t& mcu) mcu.exception_pending = -1; - MCU_DeviceReset(); + MCU_DeviceReset(mcu); if (mcu_mk1) { @@ -931,12 +924,12 @@ void MCU_PostUART(uint8_t data) 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 return; - if (dev_register[DEV_SSR] & 0x40) + if (mcu.dev_register[DEV_SSR] & 0x40) return; if (mcu.cycles < uart_rx_delay) @@ -944,26 +937,26 @@ void MCU_UpdateUART_RX(mcu_t& mcu) 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(mcu, INTERRUPT_SOURCE_UART_RX, (dev_register[DEV_SCR] & 0x40) != 0); + 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(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) return; - dev_register[DEV_SSR] |= 0x80; - MCU_Interrupt_SetRequest(mcu, 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; diff --git a/src/mcu.h b/src/mcu.h index e870b00f..c63d3742 100644 --- a/src/mcu.h +++ b/src/mcu.h @@ -102,8 +102,6 @@ enum { DEV_P9DR = 0x7f, }; -extern uint8_t dev_register[0x80]; - const uint16_t sr_mask = 0x870f; enum { STATUS_T = 0x8000, @@ -200,6 +198,13 @@ struct mcu_t { 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; }; void MCU_ErrorTrap(mcu_t& mcu); diff --git a/src/mcu_interrupt.cpp b/src/mcu_interrupt.cpp index 6ae82ca2..fa36b600 100644 --- a/src/mcu_interrupt.cpp +++ b/src/mcu_interrupt.cpp @@ -57,9 +57,9 @@ void MCU_Interrupt_SetRequest(mcu_t& mcu, uint32_t interrupt, uint32_t value) 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; @@ -141,76 +141,76 @@ void MCU_Interrupt_Handle(mcu_t& mcu) 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; From 5ddb771acc3b82b590d53032b53102ebc58138bb Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Tue, 23 Apr 2024 22:36:40 -0400 Subject: [PATCH 04/35] Remove sm global --- src/mcu.cpp | 16 +- src/mcu.h | 4 + src/submcu.cpp | 469 +++++++++++++++++++++++++------------------------ src/submcu.h | 15 +- 4 files changed, 255 insertions(+), 249 deletions(-) diff --git a/src/mcu.cpp b/src/mcu.cpp index 49918087..58510313 100644 --- a/src/mcu.cpp +++ b/src/mcu.cpp @@ -546,7 +546,7 @@ uint8_t MCU_Read(mcu_t& mcu, uint32_t address) } else if (!mcu_scb55 && address >= 0xec00 && address < 0xf000) { - ret = SM_SysRead(address & 0xff); + ret = SM_SysRead(*mcu.sm, address & 0xff); } else if (address >= 0xff80) { @@ -765,7 +765,7 @@ void MCU_Write(mcu_t& mcu, uint32_t address, uint8_t value) } else if (!mcu_scb55 && address >= 0xec00 && address < 0xf000) { - SM_SysWrite(address & 0xff, value); + SM_SysWrite(*mcu.sm, address & 0xff, value); } else if (address >= 0xff80) { @@ -875,10 +875,11 @@ void MCU_ReadInstruction(mcu_t& mcu) } } -void MCU_Init(mcu_t& mcu) +void MCU_Init(mcu_t& mcu, submcu_t& sm) { memset(&mcu, 0, sizeof(mcu_t)); mcu.sw_pos = 3; + mcu.sm = &sm; } void MCU_Reset(mcu_t& mcu) @@ -1013,7 +1014,7 @@ int SDLCALL work_thread(void* data) TIMER_Clock(mcu, mcu.cycles); if (!mcu_mk1 && !mcu_jv880 && !mcu_scb55) - SM_Update(mcu.cycles); + SM_Update(*mcu.sm, mcu.cycles); else { MCU_UpdateUART_RX(mcu); @@ -1570,7 +1571,8 @@ int main(int argc, char *argv[]) LCD_SetBackPath(basePath + "/back.data"); mcu_t mcu; - MCU_Init(mcu); + submcu_t sm; + MCU_Init(mcu, sm); lcd_t lcd; if (fread(mcu.rom1, 1, ROM1_SIZE, s_rf[0]) != ROM1_SIZE) @@ -1679,7 +1681,7 @@ int main(int argc, char *argv[]) unscramble(tempbuf, mcu_scb55 ? waverom3 : waverom2, 0x100000); } - if (s_rf[4] && fread(sm_rom, 1, ROMSM_SIZE, s_rf[4]) != ROMSM_SIZE) + if (s_rf[4] && fread(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); @@ -1714,7 +1716,7 @@ int main(int argc, char *argv[]) LCD_Init(lcd, mcu); MCU_PatchROM(); MCU_Reset(mcu); - SM_Reset(mcu); + SM_Reset(sm, mcu); PCM_Reset(); if (resetType != ResetType::NONE) MIDI_Reset(resetType); diff --git a/src/mcu.h b/src/mcu.h index c63d3742..a75b9f87 100644 --- a/src/mcu.h +++ b/src/mcu.h @@ -37,6 +37,8 @@ #include "mcu_interrupt.h" #include "SDL_atomic.h" +struct submcu_t; + enum { DEV_P1DDR = 0x00, DEV_P5DDR = 0x08, @@ -205,6 +207,8 @@ struct mcu_t { uint8_t ad_nibble; uint8_t sw_pos; uint8_t io_sd; + + submcu_t* sm; }; void MCU_ErrorTrap(mcu_t& mcu); diff --git a/src/submcu.cpp b/src/submcu.cpp index 9d67ec69..cbb8ac7c 100644 --- a/src/submcu.cpp +++ b/src/submcu.cpp @@ -78,7 +78,6 @@ 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]; @@ -93,23 +92,21 @@ 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) { @@ -172,7 +169,7 @@ 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) @@ -231,7 +228,7 @@ 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) @@ -272,7 +269,7 @@ 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) @@ -314,14 +311,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,177 +326,183 @@ void SM_SetStatus(uint32_t condition, uint32_t mask) sm.sr &= ~mask; } -void SM_Reset(mcu_t& mcu) +void SM_Reset(submcu_t& sm, mcu_t& mcu) { - memset(&sm, 0, sizeof(sm)); - sm.pc = SM_GetVectorAddress(SM_VECTOR_RESET); + 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; sm.mcu = &mcu; } -uint8_t SM_ReadAdvance(void) +uint8_t SM_ReadAdvance(submcu_t& sm) { - uint8_t byte = SM_Read(sm.pc); + 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; @@ -512,10 +515,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; @@ -523,132 +526,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; @@ -662,8 +665,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) @@ -677,115 +680,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; @@ -797,34 +800,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; } @@ -834,16 +837,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; @@ -851,93 +854,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; @@ -949,34 +952,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; } @@ -986,16 +989,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; @@ -1003,28 +1006,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 @@ -1284,19 +1287,19 @@ 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; @@ -1306,7 +1309,7 @@ void SM_HandleInterrupt(void) && (sm_device_mode[SM_DEV_INT_REQUEST] & 0x80) != 0) { sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x80; - SM_StartVector(SM_VECTOR_UART1_RX); + SM_StartVector(sm, SM_VECTOR_UART1_RX); return; } if ((sm_device_mode[SM_DEV_UART2_CTRL] & 0x8) != 0 @@ -1314,7 +1317,7 @@ void SM_HandleInterrupt(void) && (sm_device_mode[SM_DEV_INT_REQUEST] & 0x40) != 0) { sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x40; - SM_StartVector(SM_VECTOR_UART2_RX); + SM_StartVector(sm, SM_VECTOR_UART2_RX); return; } if ((sm_device_mode[SM_DEV_UART3_CTRL] & 0x8) != 0 @@ -1322,7 +1325,7 @@ void SM_HandleInterrupt(void) && (sm_device_mode[SM_DEV_INT_REQUEST] & 0x20) != 0) { sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x20; - SM_StartVector(SM_VECTOR_UART3_RX); + SM_StartVector(sm, SM_VECTOR_UART3_RX); return; } if ((sm_device_mode[SM_DEV_TIMER_CTRL] & 0x80) != 0 @@ -1330,7 +1333,7 @@ void SM_HandleInterrupt(void) && (sm_device_mode[SM_DEV_INT_REQUEST] & 0x10) != 0) { sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x10; - SM_StartVector(SM_VECTOR_IPCM0); + SM_StartVector(sm, SM_VECTOR_IPCM0); return; } if ((sm_device_mode[SM_DEV_TIMER_CTRL] & 0x40) != 0 @@ -1338,13 +1341,13 @@ void SM_HandleInterrupt(void) && (sm_device_mode[SM_DEV_INT_REQUEST] & 0x8) != 0) { sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x8; - SM_StartVector(SM_VECTOR_TIMER_X); + SM_StartVector(sm, SM_VECTOR_TIMER_X); return; } if ((sm_device_mode[SM_DEV_COLLISION] & 0xc0) == 0xc0) { sm_device_mode[SM_DEV_COLLISION] &= ~0x80; - SM_StartVector(SM_VECTOR_COLLISION); + SM_StartVector(sm, SM_VECTOR_COLLISION); return; } if (((sm_device_mode[SM_DEV_UART1_CTRL] & 0x10) == 0 @@ -1353,7 +1356,7 @@ void SM_HandleInterrupt(void) && (sm_device_mode[SM_DEV_INT_REQUEST] & 0x4) != 0) { sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x4; - SM_StartVector(SM_VECTOR_UART1_TX); + SM_StartVector(sm, SM_VECTOR_UART1_TX); return; } if (((sm_device_mode[SM_DEV_UART2_CTRL] & 0x10) == 0 @@ -1362,7 +1365,7 @@ void SM_HandleInterrupt(void) && (sm_device_mode[SM_DEV_INT_REQUEST] & 0x2) != 0) { sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x2; - SM_StartVector(SM_VECTOR_UART2_TX); + SM_StartVector(sm, SM_VECTOR_UART2_TX); return; } if (((sm_device_mode[SM_DEV_UART3_CTRL] & 0x10) == 0 @@ -1371,12 +1374,12 @@ void SM_HandleInterrupt(void) && (sm_device_mode[SM_DEV_INT_REQUEST] & 0x1) != 0) { sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x1; - SM_StartVector(SM_VECTOR_UART3_TX); + SM_StartVector(sm, SM_VECTOR_UART3_TX); return; } } -void SM_UpdateTimer(void) +void SM_UpdateTimer(submcu_t& sm) { while (sm_timer_cycles < sm.cycles) { @@ -1401,7 +1404,7 @@ void SM_UpdateTimer(void) } } -void SM_UpdateUART(void) +void SM_UpdateUART(submcu_t& sm) { if ((sm_device_mode[SM_DEV_UART1_CTRL] & 4) == 0) // RX disabled return; @@ -1422,22 +1425,22 @@ void SM_UpdateUART(void) 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 519d0e76..a216798f 100644 --- a/src/submcu.h +++ b/src/submcu.h @@ -57,14 +57,11 @@ struct submcu_t { uint64_t cycles; uint8_t sleep; mcu_t* mcu; + uint8_t sm_rom[4096]; }; -extern submcu_t sm; - -extern uint8_t sm_rom[4096]; - -void SM_Reset(mcu_t& mcu); -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_Reset(submcu_t& sm, mcu_t& mcu); +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); From d23df55cb8ae9907e207625dde91de71d67cf97a Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Wed, 24 Apr 2024 00:54:52 -0400 Subject: [PATCH 05/35] Finish removing globals from submcu and uart --- src/mcu.cpp | 40 ++++---- src/mcu.h | 17 ++-- src/midi.h | 4 +- src/midi_win32.cpp | 19 ++-- src/submcu.cpp | 231 +++++++++++++++++++++++---------------------- src/submcu.h | 16 ++++ 6 files changed, 174 insertions(+), 153 deletions(-) diff --git a/src/mcu.cpp b/src/mcu.cpp index 58510313..1c2ba5a9 100644 --- a/src/mcu.cpp +++ b/src/mcu.cpp @@ -268,14 +268,6 @@ 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(mcu_t& mcu, uint32_t address, uint8_t data) { address &= 0x7f; @@ -371,12 +363,12 @@ void MCU_DeviceWrite(mcu_t& mcu, uint32_t address, uint8_t data) if ((data & 0x80) == 0 && (ssr_rd & 0x80) != 0) { mcu.dev_register[address] &= ~0x80; - uart_tx_delay = mcu.cycles + 3000; + mcu.uart_tx_delay = mcu.cycles + 3000; MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_UART_TX, 0); } if ((data & 0x40) == 0 && (ssr_rd & 0x40) != 0) { - uart_rx_delay = mcu.cycles + 3000; + mcu.uart_rx_delay = mcu.cycles + 3000; mcu.dev_register[address] &= ~0x40; MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_UART_RX, 0); } @@ -426,7 +418,7 @@ uint8_t MCU_DeviceRead(mcu_t& mcu, uint32_t address) 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: @@ -917,27 +909,27 @@ void MCU_Reset(mcu_t& mcu) } } -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(mcu_t& mcu) { 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 (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; + 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); } @@ -951,7 +943,7 @@ void MCU_UpdateUART_TX(mcu_t& mcu) if (mcu.dev_register[DEV_SSR] & 0x80) return; - if (mcu.cycles < uart_tx_delay) + if (mcu.cycles < mcu.uart_tx_delay) return; mcu.dev_register[DEV_SSR] |= 0x80; @@ -1305,7 +1297,7 @@ enum class ResetType { GM_RESET, }; -void MIDI_Reset(ResetType resetType) +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 }; @@ -1314,14 +1306,14 @@ void MIDI_Reset(ResetType resetType) { for (size_t i = 0; i < sizeof(gsReset); i++) { - MCU_PostUART(gsReset[i]); + MCU_PostUART(mcu, gsReset[i]); } } else if (resetType == ResetType::GM_RESET) { for (size_t i = 0; i < sizeof(gmReset); i++) { - MCU_PostUART(gmReset[i]); + MCU_PostUART(mcu, gmReset[i]); } } @@ -1707,7 +1699,7 @@ int main(int argc, char *argv[]) return 2; } - if(!MIDI_Init(port)) + if(!MIDI_Init(mcu, port)) { fprintf(stderr, "ERROR: Failed to initialize the MIDI Input.\nWARNING: Continuing without MIDI Input...\n"); fflush(stderr); @@ -1719,7 +1711,7 @@ int main(int argc, char *argv[]) SM_Reset(sm, mcu); PCM_Reset(); - if (resetType != ResetType::NONE) MIDI_Reset(resetType); + if (resetType != ResetType::NONE) MIDI_Reset(mcu, resetType); MCU_Run(mcu, lcd); diff --git a/src/mcu.h b/src/mcu.h index a75b9f87..76ee3ba5 100644 --- a/src/mcu.h +++ b/src/mcu.h @@ -182,6 +182,8 @@ 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; + struct mcu_t { uint16_t r[8]; uint16_t pc; @@ -209,6 +211,14 @@ struct mcu_t { uint8_t io_sd; submcu_t* sm; + + 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; }; void MCU_ErrorTrap(mcu_t& mcu); @@ -476,11 +486,6 @@ 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); @@ -490,7 +495,7 @@ void MCU_GA_SetGAInt(mcu_t& mcu, int line, int value); void MCU_EncoderTrigger(mcu_t& mcu, int dir); void MCU_PostSample(int *sample); -void MCU_PostUART(uint8_t data); +void MCU_PostUART(mcu_t& mcu, uint8_t data); void MCU_WorkThread_Lock(void); void MCU_WorkThread_Unlock(void); diff --git a/src/midi.h b/src/midi.h index 94366205..4a62f933 100644 --- a/src/midi.h +++ b/src/midi.h @@ -33,6 +33,8 @@ */ #pragma once -int MIDI_Init(int port); +struct mcu_t; + +int MIDI_Init(mcu_t& mcu, int port); void MIDI_Quit(void); diff --git a/src/midi_win32.cpp b/src/midi_win32.cpp index c453aea1..4d6a40ac 100644 --- a/src/midi_win32.cpp +++ b/src/midi_win32.cpp @@ -43,6 +43,8 @@ static MIDIHDR midi_buffer; static char midi_in_buffer[1024]; +static mcu_t* midi_mcu_instance = nullptr; + void CALLBACK MIDI_Callback( HMIDIIN hMidiIn, UINT wMsg, @@ -65,14 +67,14 @@ void CALLBACK MIDI_Callback( case 0xa0: case 0xb0: case 0xe0: - MCU_PostUART(b1); - MCU_PostUART((dwParam1 >> 8) & 0xff); - MCU_PostUART((dwParam1 >> 16) & 0xff); + MCU_PostUART(*midi_mcu_instance, b1); + MCU_PostUART(*midi_mcu_instance, (dwParam1 >> 8) & 0xff); + MCU_PostUART(*midi_mcu_instance, (dwParam1 >> 16) & 0xff); break; case 0xc0: case 0xd0: - MCU_PostUART(b1); - MCU_PostUART((dwParam1 >> 8) & 0xff); + MCU_PostUART(*midi_mcu_instance, b1); + MCU_PostUART(*midi_mcu_instance, (dwParam1 >> 8) & 0xff); break; } break; @@ -86,7 +88,7 @@ void CALLBACK MIDI_Callback( { for (int i = 0; i < midi_buffer.dwBytesRecorded; i++) { - MCU_PostUART(midi_in_buffer[i]); + MCU_PostUART(*midi_mcu_instance, midi_in_buffer[i]); } } @@ -101,8 +103,10 @@ void CALLBACK MIDI_Callback( } } -int MIDI_Init(int port) +int MIDI_Init(mcu_t& mcu, int port) { + midi_mcu_instance = &mcu; + int num = midiInGetNumDevs(); if (num == 0) @@ -149,4 +153,5 @@ void MIDI_Quit() midiInClose(midi_handle); midi_handle = 0; } + midi_mcu_instance = nullptr; } diff --git a/src/submcu.cpp b/src/submcu.cpp index cbb8ac7c..4fe39b3e 100644 --- a/src/submcu.cpp +++ b/src/submcu.cpp @@ -78,24 +78,6 @@ enum { SM_DEV_TIMER_CTRL = 0x1f }; -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; - -static uint8_t uart_rx_gotbyte; -static uint8_t uart_rx_byte; -static uint64_t uart_rx_delay; - void SM_ErrorTrap(submcu_t& sm) { printf("%.4x\n", sm.pc); @@ -110,11 +92,11 @@ uint8_t SM_Read(submcu_t& sm, uint16_t address) } 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) { @@ -123,8 +105,8 @@ uint8_t SM_Read(submcu_t& sm, 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: { @@ -134,7 +116,7 @@ uint8_t SM_Read(submcu_t& sm, 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; } @@ -147,20 +129,20 @@ uint8_t SM_Read(submcu_t& sm, uint16_t address) case SM_DEV_P1_DATA: return MCU_ReadP1(); 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 { @@ -174,7 +156,7 @@ 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,42 +167,42 @@ void SM_Write(submcu_t& sm, uint16_t address, uint8_t data) MCU_WriteP1(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(*sm.mcu, 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 { @@ -234,22 +216,22 @@ void SM_SysWrite(submcu_t& sm, uint32_t address, uint8_t data) 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) { @@ -261,7 +243,7 @@ void SM_SysWrite(submcu_t& sm, uint32_t address, uint8_t data) } else if (address == 0xf7) { - sm_p0_dir = data; + sm.sm_p0_dir = data; } else { @@ -274,23 +256,23 @@ 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) { @@ -302,7 +284,7 @@ uint8_t SM_SysRead(submcu_t& sm, uint32_t address) } else if (address == 0xf7) { - return sm_p0_dir; + return sm.sm_p0_dir; } else { @@ -337,6 +319,23 @@ void SM_Reset(submcu_t& sm, mcu_t& mcu) sm.cycles = 0; sm.sleep = 0; sm.mcu = &mcu; + + memset(sm.sm_ram, 0, sizeof(sm.sm_ram)); + memset(sm.sm_shared_ram, 0, sizeof(sm.sm_shared_ram)); + memset(sm.sm_access, 0, sizeof(sm.sm_access)); + + sm.sm_p0_dir = 0; + sm.sm_p1_dir = 0; + + memset(sm.sm_device_mode, 0, sizeof(sm.sm_device_mode)); + + sm.sm_cts = 0; + + sm.sm_timer_cycles = 0; + sm.sm_timer_prescaler = 0; + sm.sm_timer_counter = 0; + + sm.uart_rx_gotbyte = 0; } uint8_t SM_ReadAdvance(submcu_t& sm) @@ -1304,76 +1303,76 @@ 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.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.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.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.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.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.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.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.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.sm_device_mode[SM_DEV_INT_REQUEST] &= ~0x1; SM_StartVector(sm, SM_VECTOR_UART3_TX); return; } @@ -1381,48 +1380,50 @@ void SM_HandleInterrupt(submcu_t& sm) 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(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(submcu_t& sm, uint64_t cycles) diff --git a/src/submcu.h b/src/submcu.h index a216798f..c8121f85 100644 --- a/src/submcu.h +++ b/src/submcu.h @@ -58,6 +58,22 @@ struct submcu_t { 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]; + + 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; + + uint8_t uart_rx_gotbyte; }; void SM_Reset(submcu_t& sm, mcu_t& mcu); From 621322200047ea451485cd836bb286adabd89448 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Wed, 24 Apr 2024 02:23:35 -0400 Subject: [PATCH 06/35] Remove romset and pcm globals --- src/lcd.cpp | 14 ++-- src/mcu.cpp | 175 ++++++++++++++++++++++------------------------ src/mcu.h | 22 +++--- src/mcu_timer.cpp | 4 +- src/pcm.cpp | 144 +++++++++++++++++++------------------- src/pcm.h | 13 ++-- 6 files changed, 186 insertions(+), 186 deletions(-) diff --git a/src/lcd.cpp b/src/lcd.cpp index 20fec4e1..8fec5b0a 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -239,7 +239,7 @@ void LCD_Init(lcd_t& lcd, mcu_t& mcu) std::string title = "Nuked SC-55: "; - title += rs_name[romset]; + title += rs_name[mcu.romset]; window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, lcd_width, lcd_height, SDL_WINDOW_SHOWN); if (!window) @@ -414,17 +414,17 @@ 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(); - if (!lcd_enable && !mcu_jv880) + if (!lcd_enable && !lcd.mcu->mcu_jv880) { memset(lcd_buffer, 0, sizeof(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++) { @@ -441,7 +441,7 @@ void LCD_Update(lcd_t& lcd) } } - if (mcu_jv880) + if (lcd.mcu->mcu_jv880) { for (int i = 0; i < 2; i++) { @@ -547,8 +547,8 @@ void LCD_Update(lcd_t& lcd) int mask = 0; uint32_t button_pressed = (uint32_t)SDL_AtomicGet(&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) diff --git a/src/mcu.cpp b/src/mcu.cpp index 1c2ba5a9..9c94876d 100644 --- a/src/mcu.cpp +++ b/src/mcu.cpp @@ -120,8 +120,6 @@ const char* roms[ROM_SET_COUNT][5] = "rom_sm.bin", }; -int romset = ROM_SET_MK2; - static int audio_buffer_size; static int audio_page_size; static short *sample_buffer; @@ -136,13 +134,6 @@ 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; @@ -181,9 +172,9 @@ uint16_t MCU_SC155Sliders(mcu_t& mcu, uint32_t index) 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; @@ -198,15 +189,15 @@ uint16_t MCU_AnalogReadPin(mcu_t& mcu, uint32_t pin) else return ANALOG_LEVEL_RCU_LOW; } - if (mcu_mk1) + if (mcu.mcu_mk1) { - if (mcu_sc155 && (mcu.dev_register[DEV_P9DR] & 1) != 0) + if (mcu.mcu_sc155 && (mcu.dev_register[DEV_P9DR] & 1) != 0) { return MCU_SC155Sliders(mcu, pin); } if (pin == 7) { - if (mcu_sc155 && (mcu.dev_register[DEV_P9DR] & 2) != 0) + if (mcu.mcu_sc155 && (mcu.dev_register[DEV_P9DR] & 2) != 0) return MCU_SC155Sliders(mcu, 8); else return ANALOG_LEVEL_BATTERY; @@ -216,20 +207,20 @@ uint16_t MCU_AnalogReadPin(mcu_t& mcu, uint32_t pin) } else { - if (mcu_sc155 && (mcu.io_sd & 16) != 0) + if (mcu.mcu_sc155 && (mcu.io_sd & 16) != 0) { return MCU_SC155Sliders(mcu, pin); } if (pin == 7) { - if (mcu_mk1) + if (mcu.mcu_mk1) return ANALOG_LEVEL_BATTERY; switch ((mcu.io_sd >> 2) & 3) { case 0: // Battery voltage return ANALOG_LEVEL_BATTERY; case 1: // NC - if (mcu_sc155) + if (mcu.mcu_sc155) return MCU_SC155Sliders(mcu, 8); return 0; case 2: // SW @@ -423,7 +414,7 @@ uint8_t MCU_DeviceRead(mcu_t& mcu, uint32_t address) 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); @@ -441,8 +432,8 @@ uint8_t MCU_DeviceRead(mcu_t& mcu, 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 = mcu.dev_register[DEV_P9DDR]; @@ -512,12 +503,10 @@ void MCU_UpdateAnalog(mcu_t& mcu, uint64_t cycles) analog_end_time = 0; } -int rom2_mask = ROM2_SIZE - 1; - 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; @@ -529,14 +518,14 @@ uint8_t MCU_Read(mcu_t& mcu, uint32_t address) 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(mcu, 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(*mcu.sm, address & 0xff); } @@ -555,7 +544,7 @@ uint8_t MCU_Read(mcu_t& mcu, uint32_t address) { ret = ga_int_trigger; ga_int_trigger = 0; - MCU_Interrupt_SetRequest(mcu, mcu_jv880 ? INTERRUPT_SOURCE_IRQ0 : INTERRUPT_SOURCE_IRQ1, 0); + MCU_Interrupt_SetRequest(mcu, mcu.mcu_jv880 ? INTERRUPT_SOURCE_IRQ0 : INTERRUPT_SOURCE_IRQ1, 0); } else { @@ -570,7 +559,7 @@ uint8_t MCU_Read(mcu_t& mcu, uint32_t address) { if (address >= 0xe000 && address < 0xe040) { - ret = PCM_Read(mcu, address & 0x3f); + ret = PCM_Read(*mcu.pcm, address & 0x3f); } else if (address >= 0xff80) { @@ -589,7 +578,7 @@ uint8_t MCU_Read(mcu_t& mcu, uint32_t address) { mcu.io_sd = address & 0xff; - if (mcu_cm300) + if (mcu.mcu_cm300) return 0xff; LCD_Enable((mcu.io_sd & 8) != 0); @@ -639,52 +628,52 @@ uint8_t MCU_Read(mcu_t& mcu, uint32_t address) break; #endif case 1: - ret = mcu.rom2[address_rom & rom2_mask]; + ret = mcu.rom2[address_rom & mcu.rom2_mask]; break; case 2: - ret = mcu.rom2[address_rom & rom2_mask]; + ret = mcu.rom2[address_rom & mcu.rom2_mask]; break; case 3: - ret = mcu.rom2[address_rom & rom2_mask]; + ret = mcu.rom2[address_rom & mcu.rom2_mask]; break; case 4: - ret = mcu.rom2[address_rom & rom2_mask]; + ret = mcu.rom2[address_rom & mcu.rom2_mask]; break; case 8: - if (!mcu_jv880) - ret = mcu.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 = mcu.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 = mcu.rom2[address_rom & rom2_mask]; + if (!mcu.mcu_jv880) + ret = mcu.rom2[address_rom & mcu.rom2_mask]; else ret = mcu.cardram[address & 0x7fff]; // FIXME break; case 10: case 11: - if (!mcu_mk1) + if (!mcu.mcu_mk1) ret = mcu.sram[address & 0x7fff]; // FIXME else ret = 0xff; break; case 12: case 13: - if (mcu_jv880) + if (mcu.mcu_jv880) ret = mcu.nvram[address & 0x7fff]; // FIXME else ret = 0xff; break; case 5: - if (mcu_mk1) + if (mcu.mcu_mk1) ret = mcu.sram[address & 0x7fff]; // FIXME else ret = 0xff; @@ -724,9 +713,9 @@ void MCU_Write(mcu_t& mcu, 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)) @@ -753,9 +742,9 @@ void MCU_Write(mcu_t& mcu, 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(*mcu.sm, address & 0xff, value); } @@ -781,7 +770,7 @@ void MCU_Write(mcu_t& mcu, 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) { @@ -826,19 +815,19 @@ void MCU_Write(mcu_t& mcu, 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) { mcu.sram[address & 0x7fff] = value; // FIXME } - else if (page == 10 && !mcu_mk1) + else if (page == 10 && !mcu.mcu_mk1) { mcu.sram[address & 0x7fff] = value; // FIXME } - else if (page == 12 && mcu_jv880) + else if (page == 12 && mcu.mcu_jv880) { mcu.nvram[address & 0x7fff] = value; // FIXME } - else if (page == 14 && mcu_jv880) + else if (page == 14 && mcu.mcu_jv880) { mcu.cardram[address & 0x7fff] = value; // FIXME } @@ -867,11 +856,14 @@ void MCU_ReadInstruction(mcu_t& mcu) } } -void MCU_Init(mcu_t& mcu, submcu_t& sm) +void MCU_Init(mcu_t& mcu, submcu_t& sm, pcm_t& pcm) { memset(&mcu, 0, sizeof(mcu_t)); mcu.sw_pos = 3; mcu.sm = &sm; + mcu.pcm = &pcm; + mcu.romset = ROM_SET_MK2; + mcu.rom2_mask = ROM2_SIZE - 1; } void MCU_Reset(mcu_t& mcu) @@ -903,7 +895,7 @@ void MCU_Reset(mcu_t& mcu) MCU_DeviceReset(mcu); - if (mcu_mk1) + if (mcu.mcu_mk1) { ga_int_enable = 255; } @@ -974,7 +966,7 @@ int SDLCALL work_thread(void* data) MCU_WorkThread_Lock(); while (work_thread_run) { - if (pcm.config_reg_3c & 0x40) + if (mcu.pcm->config_reg_3c & 0x40) sample_write_ptr &= ~3; else sample_write_ptr &= ~1; @@ -1001,11 +993,11 @@ int SDLCALL work_thread(void* data) // if (mcu.cycles % 24000000 == 0) // printf("seconds: %i\n", (int)(mcu.cycles / 24000000)); - PCM_Update(mcu, mcu.cycles); + PCM_Update(*mcu.pcm, mcu.cycles); TIMER_Clock(mcu, mcu.cycles); - if (!mcu_mk1 && !mcu_jv880 && !mcu_scb55) + if (!mcu.mcu_mk1 && !mcu.mcu_jv880 && !mcu.mcu_scb55) SM_Update(*mcu.sm, mcu.cycles); else { @@ -1015,7 +1007,7 @@ int SDLCALL work_thread(void* data) MCU_UpdateAnalog(mcu, mcu.cycles); - if (mcu_mk1) + if (mcu.mcu_mk1) { if (ga_lcd_counter) { @@ -1163,7 +1155,7 @@ static const char* audio_format_to_str(int format) return "UNK"; } -int MCU_OpenAudio(int deviceIndex, int pageSize, int pageNum) +int MCU_OpenAudio(mcu_t& mcu, int deviceIndex, int pageSize, int pageNum) { SDL_AudioSpec spec = {}; SDL_AudioSpec spec_actual = {}; @@ -1172,7 +1164,7 @@ int MCU_OpenAudio(int deviceIndex, int pageSize, int pageNum) audio_buffer_size = audio_page_size*pageNum; spec.format = AUDIO_S16SYS; - spec.freq = (mcu_mk1 || mcu_jv880) ? 64000 : 66207; + spec.freq = (mcu.mcu_mk1 || mcu.mcu_jv880) ? 64000 : 66207; spec.channels = 2; spec.callback = audio_callback; spec.samples = audio_page_size / 4; @@ -1257,7 +1249,7 @@ void MCU_GA_SetGAInt(mcu_t& mcu, int line, int value) ga_int_trigger = line; ga_int[line] = value; - if (mcu_jv880) + if (mcu.mcu_jv880) MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_IRQ0, ga_int_trigger != 0); else MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_IRQ1, ga_int_trigger != 0); @@ -1265,7 +1257,7 @@ void MCU_GA_SetGAInt(mcu_t& mcu, int line, int value) void MCU_EncoderTrigger(mcu_t& mcu, int dir) { - if (!mcu_jv880) return; + if (!mcu.mcu_jv880) return; MCU_GA_SetGAInt(mcu, dir == 0 ? 3 : 4, 0); MCU_GA_SetGAInt(mcu, dir == 0 ? 3 : 4, 1); } @@ -1331,7 +1323,13 @@ int main(int argc, char *argv[]) bool autodetect = true; ResetType resetType = ResetType::NONE; - romset = ROM_SET_MK2; + int romset = ROM_SET_MK2; + + mcu_t mcu; + submcu_t sm; + pcm_t pcm; + MCU_Init(mcu, sm, pcm); + lcd_t lcd; { for (int i = 1; i < argc; i++) @@ -1488,42 +1486,42 @@ int main(int argc, char *argv[]) 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; + mcu.mcu_mk1 = false; + mcu.mcu_cm300 = false; + mcu.mcu_st = false; + mcu.mcu_jv880 = false; + mcu.mcu_scb55 = false; + mcu.mcu_sc155 = false; switch (romset) { case ROM_SET_MK2: case ROM_SET_SC155MK2: if (romset == ROM_SET_SC155MK2) - mcu_sc155 = true; + mcu.mcu_sc155 = true; break; case ROM_SET_ST: - mcu_st = true; + mcu.mcu_st = true; break; case ROM_SET_MK1: case ROM_SET_SC155: - mcu_mk1 = true; - mcu_st = false; + mcu.mcu_mk1 = true; + mcu.mcu_st = false; if (romset == ROM_SET_SC155) - mcu_sc155 = true; + mcu.mcu_sc155 = true; break; case ROM_SET_CM300: - mcu_mk1 = true; - mcu_cm300 = true; + mcu.mcu_mk1 = true; + mcu.mcu_cm300 = true; break; case ROM_SET_JV880: - mcu_jv880 = true; - rom2_mask /= 2; // rom is half the size + mcu.mcu_jv880 = true; + mcu.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; + mcu.mcu_scb55 = true; break; } @@ -1541,7 +1539,7 @@ int main(int argc, char *argv[]) } rpaths[i] = basePath + "/" + roms[romset][i]; s_rf[i] = Files::utf8_fopen(rpaths[i].c_str(), "rb"); - bool optional = mcu_jv880 && i == 4; + bool optional = mcu.mcu_jv880 && i == 4; r_ok &= optional || (s_rf[i] != nullptr); if(!s_rf[i]) { @@ -1562,11 +1560,6 @@ int main(int argc, char *argv[]) LCD_SetBackPath(basePath + "/back.data"); - mcu_t mcu; - submcu_t sm; - MCU_Init(mcu, sm); - lcd_t lcd; - if (fread(mcu.rom1, 1, ROM1_SIZE, s_rf[0]) != ROM1_SIZE) { fprintf(stderr, "FATAL ERROR: Failed to read the mcu ROM1.\n"); @@ -1579,7 +1572,7 @@ int main(int argc, char *argv[]) if (rom2_read == ROM2_SIZE || rom2_read == ROM2_SIZE / 2) { - rom2_mask = rom2_read - 1; + mcu.rom2_mask = rom2_read - 1; } else { @@ -1589,7 +1582,7 @@ int main(int argc, char *argv[]) return 1; } - if (mcu_mk1) + if (mcu.mcu_mk1) { if (fread(tempbuf, 1, 0x100000, s_rf[2]) != 0x100000) { @@ -1621,7 +1614,7 @@ int main(int argc, char *argv[]) unscramble(tempbuf, waverom3, 0x100000); } - else if (mcu_jv880) + else if (mcu.mcu_jv880) { if (fread(tempbuf, 1, 0x200000, s_rf[2]) != 0x200000) { @@ -1670,7 +1663,7 @@ int main(int argc, char *argv[]) return 1; } - unscramble(tempbuf, mcu_scb55 ? waverom3 : waverom2, 0x100000); + unscramble(tempbuf, mcu.mcu_scb55 ? waverom3 : waverom2, 0x100000); } if (s_rf[4] && fread(sm.sm_rom, 1, ROMSM_SIZE, s_rf[4]) != ROMSM_SIZE) @@ -1692,7 +1685,7 @@ int main(int argc, char *argv[]) return 2; } - if (!MCU_OpenAudio(audioDeviceIndex, pageSize, pageNum)) + if (!MCU_OpenAudio(mcu, audioDeviceIndex, pageSize, pageNum)) { fprintf(stderr, "FATAL ERROR: Failed to open the audio stream.\n"); fflush(stderr); @@ -1709,7 +1702,7 @@ int main(int argc, char *argv[]) MCU_PatchROM(); MCU_Reset(mcu); SM_Reset(sm, mcu); - PCM_Reset(); + PCM_Reset(pcm, mcu); if (resetType != ResetType::NONE) MIDI_Reset(mcu, resetType); diff --git a/src/mcu.h b/src/mcu.h index 76ee3ba5..5b50bde4 100644 --- a/src/mcu.h +++ b/src/mcu.h @@ -38,6 +38,7 @@ #include "SDL_atomic.h" struct submcu_t; +struct pcm_t; enum { DEV_P1DDR = 0x00, @@ -211,6 +212,7 @@ struct mcu_t { uint8_t io_sd; submcu_t* sm; + pcm_t* pcm; uint32_t uart_write_ptr; uint32_t uart_read_ptr; @@ -219,6 +221,17 @@ struct mcu_t { 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 = ROM2_SIZE - 1; }; void MCU_ErrorTrap(mcu_t& mcu); @@ -475,15 +488,6 @@ enum { 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; uint8_t MCU_ReadP0(void); diff --git a/src/mcu_timer.cpp b/src/mcu_timer.cpp index bb18ae44..b65bf881 100644 --- a/src/mcu_timer.cpp +++ b/src/mcu_timer.cpp @@ -244,7 +244,7 @@ void TIMER_Clock(mcu_t& mcu, uint64_t cycles) continue; break; case 3: // ext (o / 2) - if (mcu_mk1) + if (mcu.mcu_mk1) { if (timer_cycles & 3) continue; @@ -305,7 +305,7 @@ void TIMER_Clock(mcu_t& mcu, uint64_t cycles) case 5: case 6: case 7: // ext (o / 2) - if (mcu_mk1) + if (mcu.mcu_mk1) { if ((timer_cycles & 3) == 0) timer_step = 1; diff --git a/src/pcm.cpp b/src/pcm.cpp index c6a37c9a..4ed70775 100644 --- a/src/pcm.cpp +++ b/src/pcm.cpp @@ -38,13 +38,12 @@ #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,23 +53,23 @@ uint8_t PCM_ReadROM(uint32_t address) switch (bank) { case 0: - if (mcu_mk1) + if (pcm.mcu->mcu_mk1) return waverom1[address & 0xfffff]; else return waverom1[address & 0x1fffff]; case 1: - if (!mcu_jv880) + if (!pcm.mcu->mcu_jv880) return waverom2[address & 0xfffff]; else return waverom2[address & 0x1fffff]; case 2: - if (mcu_jv880) return 0; + if (pcm.mcu->mcu_jv880) return 0; return waverom3[address & 0xfffff]; case 3: case 4: case 5: case 6: - if (mcu_jv880) + if (pcm.mcu->mcu_jv880) return waverom_exp[(address & 0x1fffff) + (bank - 3) * 0x200000]; default: break; @@ -78,7 +77,7 @@ uint8_t PCM_ReadROM(uint32_t address) 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 +118,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 +191,7 @@ void PCM_Write(uint32_t address, uint8_t data) // rv: [30][2], [30][3] // ch: [31][2], [31][5] -uint8_t PCM_Read(mcu_t& mcu, uint32_t address) +uint8_t PCM_Read(pcm_t& pcm, uint32_t address) { address &= 0x3f; //printf("PCM Read: %.2x\n", address); @@ -209,10 +208,10 @@ uint8_t PCM_Read(mcu_t& mcu, uint32_t address) if (address == 0x3e && pcm.irq_assert) { pcm.irq_assert = 0; - if (mcu_jv880) - MCU_GA_SetGAInt(mcu, 5, 0); + if (pcm.mcu->mcu_jv880) + MCU_GA_SetGAInt(*pcm.mcu, 5, 0); else - MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_IRQ0, 0); + MCU_Interrupt_SetRequest(*pcm.mcu, INTERRUPT_SOURCE_IRQ0, 0); } status |= pcm.irq_channel; @@ -267,9 +266,10 @@ uint8_t PCM_Read(mcu_t& mcu, uint32_t address) return 0; } -void PCM_Reset(void) +void PCM_Reset(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 +326,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 +490,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 +501,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 +522,7 @@ inline void eram_pack(int addr, int val) pcm.eram[addr] = data; } -void PCM_Update(mcu_t& mcu, 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; @@ -677,7 +677,7 @@ void PCM_Update(mcu_t& mcu, 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 +697,8 @@ void PCM_Update(mcu_t& mcu, 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 +712,8 @@ void PCM_Update(mcu_t& mcu, 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 +727,8 @@ void PCM_Update(mcu_t& mcu, 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 +739,14 @@ void PCM_Update(mcu_t& mcu, 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 +757,31 @@ void PCM_Update(mcu_t& mcu, 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 +793,7 @@ void PCM_Update(mcu_t& mcu, 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 +807,7 @@ void PCM_Update(mcu_t& mcu, 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 +821,7 @@ void PCM_Update(mcu_t& mcu, 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 +829,13 @@ void PCM_Update(mcu_t& mcu, 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 +843,63 @@ void PCM_Update(mcu_t& mcu, 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 +913,8 @@ void PCM_Update(mcu_t& mcu, 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 +929,16 @@ void PCM_Update(mcu_t& mcu, 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 +952,9 @@ void PCM_Update(mcu_t& mcu, 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 +963,7 @@ void PCM_Update(mcu_t& mcu, 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 +1147,7 @@ void PCM_Update(mcu_t& mcu, 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 +1167,7 @@ void PCM_Update(mcu_t& mcu, 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 +1193,7 @@ void PCM_Update(mcu_t& mcu, 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 +1222,7 @@ void PCM_Update(mcu_t& mcu, 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 +1251,7 @@ void PCM_Update(mcu_t& mcu, 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 +1375,7 @@ void PCM_Update(mcu_t& mcu, 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 +1433,18 @@ void PCM_Update(mcu_t& mcu, uint64_t cycles) ram2[8] |= 0x4000; pcm.irq_assert = 1; pcm.irq_channel = slot; - if (mcu_jv880) - MCU_GA_SetGAInt(mcu, 5, 1); + if (pcm.mcu->mcu_jv880) + MCU_GA_SetGAInt(*pcm.mcu, 5, 1); else - MCU_Interrupt_SetRequest(mcu, 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 +1569,6 @@ void PCM_Update(mcu_t& mcu, 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 a0aae9e4..ecd061e7 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]; + + mcu_t* mcu; }; -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(mcu_t& mcu, uint32_t address); -void PCM_Reset(void); -void PCM_Update(mcu_t& mcu, 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_Reset(pcm_t& pcm, mcu_t& mcu); +void PCM_Update(pcm_t& pcm, uint64_t cycles); From 40546d4861fbdfbff85349417f585c3b8692cba6 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Wed, 24 Apr 2024 03:11:40 -0400 Subject: [PATCH 07/35] Move waveroms into pcm_t Also heap-allocate pcm because the waveroms are so large they overflow the stack otherwise. --- src/mcu.cpp | 25 ++++++++++++++----------- src/pcm.cpp | 17 ++++++----------- src/pcm.h | 10 +++++----- 3 files changed, 25 insertions(+), 27 deletions(-) diff --git a/src/mcu.cpp b/src/mcu.cpp index 9c94876d..b88fdbef 100644 --- a/src/mcu.cpp +++ b/src/mcu.cpp @@ -1327,8 +1327,10 @@ int main(int argc, char *argv[]) mcu_t mcu; submcu_t sm; - pcm_t pcm; - MCU_Init(mcu, sm, pcm); + // allocate pcm because the waveroms will overflow the stack + pcm_t* pcm = (pcm_t*)malloc(sizeof(pcm_t)); + PCM_Reset(*pcm, mcu); + MCU_Init(mcu, sm, *pcm); lcd_t lcd; { @@ -1592,7 +1594,7 @@ int main(int argc, char *argv[]) return 1; } - unscramble(tempbuf, waverom1, 0x100000); + unscramble(tempbuf, pcm->waverom1, 0x100000); if (fread(tempbuf, 1, 0x100000, s_rf[3]) != 0x100000) { @@ -1602,7 +1604,7 @@ int main(int argc, char *argv[]) return 1; } - unscramble(tempbuf, waverom2, 0x100000); + unscramble(tempbuf, pcm->waverom2, 0x100000); if (fread(tempbuf, 1, 0x100000, s_rf[4]) != 0x100000) { @@ -1612,7 +1614,7 @@ int main(int argc, char *argv[]) return 1; } - unscramble(tempbuf, waverom3, 0x100000); + unscramble(tempbuf, pcm->waverom3, 0x100000); } else if (mcu.mcu_jv880) { @@ -1624,7 +1626,7 @@ int main(int argc, char *argv[]) return 1; } - unscramble(tempbuf, waverom1, 0x200000); + unscramble(tempbuf, pcm->waverom1, 0x200000); if (fread(tempbuf, 1, 0x200000, s_rf[3]) != 0x200000) { @@ -1634,10 +1636,10 @@ int main(int argc, char *argv[]) return 1; } - unscramble(tempbuf, waverom2, 0x200000); + unscramble(tempbuf, pcm->waverom2, 0x200000); if (s_rf[4] && fread(tempbuf, 1, 0x800000, s_rf[4])) - unscramble(tempbuf, waverom_exp, 0x800000); + unscramble(tempbuf, pcm->waverom_exp, 0x800000); else printf("WaveRom EXP not found, skipping it.\n"); } @@ -1651,7 +1653,7 @@ int main(int argc, char *argv[]) return 1; } - unscramble(tempbuf, waverom1, 0x200000); + unscramble(tempbuf, pcm->waverom1, 0x200000); if (s_rf[3]) { @@ -1663,7 +1665,7 @@ int main(int argc, char *argv[]) return 1; } - unscramble(tempbuf, mcu.mcu_scb55 ? waverom3 : waverom2, 0x100000); + unscramble(tempbuf, mcu.mcu_scb55 ? pcm->waverom3 : pcm->waverom2, 0x100000); } if (s_rf[4] && fread(sm.sm_rom, 1, ROMSM_SIZE, s_rf[4]) != ROMSM_SIZE) @@ -1702,7 +1704,6 @@ int main(int argc, char *argv[]) MCU_PatchROM(); MCU_Reset(mcu); SM_Reset(sm, mcu); - PCM_Reset(pcm, mcu); if (resetType != ResetType::NONE) MIDI_Reset(mcu, resetType); @@ -1713,5 +1714,7 @@ int main(int argc, char *argv[]) LCD_UnInit(); SDL_Quit(); + free(pcm); + return 0; } diff --git a/src/pcm.cpp b/src/pcm.cpp index 4ed70775..1fbdb9b9 100644 --- a/src/pcm.cpp +++ b/src/pcm.cpp @@ -38,11 +38,6 @@ #include "mcu_interrupt.h" #include "pcm.h" -uint8_t waverom1[0x200000]; -uint8_t waverom2[0x200000]; -uint8_t waverom3[0x100000]; -uint8_t waverom_exp[0x800000]; - uint8_t PCM_ReadROM(pcm_t& pcm, uint32_t address) { int bank; @@ -54,23 +49,23 @@ uint8_t PCM_ReadROM(pcm_t& pcm, uint32_t address) { case 0: if (pcm.mcu->mcu_mk1) - return waverom1[address & 0xfffff]; + return pcm.waverom1[address & 0xfffff]; else - return waverom1[address & 0x1fffff]; + return pcm.waverom1[address & 0x1fffff]; case 1: if (!pcm.mcu->mcu_jv880) - return waverom2[address & 0xfffff]; + return pcm.waverom2[address & 0xfffff]; else - return waverom2[address & 0x1fffff]; + return pcm.waverom2[address & 0x1fffff]; case 2: if (pcm.mcu->mcu_jv880) return 0; - return waverom3[address & 0xfffff]; + return pcm.waverom3[address & 0xfffff]; case 3: case 4: case 5: case 6: if (pcm.mcu->mcu_jv880) - return waverom_exp[(address & 0x1fffff) + (bank - 3) * 0x200000]; + return pcm.waverom_exp[(address & 0x1fffff) + (bank - 3) * 0x200000]; default: break; } diff --git a/src/pcm.h b/src/pcm.h index ecd061e7..d45b01a9 100644 --- a/src/pcm.h +++ b/src/pcm.h @@ -65,12 +65,12 @@ struct pcm_t { int rcsum[2]; mcu_t* mcu; -}; -extern uint8_t waverom1[]; -extern uint8_t waverom2[]; -extern uint8_t waverom3[]; -extern uint8_t waverom_exp[]; + uint8_t waverom1[0x200000]; + uint8_t waverom2[0x200000]; + uint8_t waverom3[0x100000]; + uint8_t waverom_exp[0x800000]; +}; void PCM_Write(pcm_t& pcm, uint32_t address, uint8_t data); uint8_t PCM_Read(pcm_t& pcm, uint32_t address); From 27783620cfb72e9e6f7a0e40b91e9f2974d1b461 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Wed, 24 Apr 2024 19:20:55 -0400 Subject: [PATCH 08/35] Remove mcu_timer global state --- src/mcu.cpp | 17 +++-- src/mcu.h | 2 + src/mcu_timer.cpp | 166 ++++++++++++++++++++++------------------------ src/mcu_timer.h | 18 +++-- 4 files changed, 104 insertions(+), 99 deletions(-) diff --git a/src/mcu.cpp b/src/mcu.cpp index b88fdbef..61aeb49d 100644 --- a/src/mcu.cpp +++ b/src/mcu.cpp @@ -264,12 +264,12 @@ void MCU_DeviceWrite(mcu_t& mcu, uint32_t address, uint8_t data) address &= 0x7f; if (address >= 0x10 && address < 0x40) { - TIMER_Write(mcu, address, data); + TIMER_Write(*mcu.timer, address, data); return; } if (address >= 0x50 && address < 0x55) { - TIMER2_Write(mcu, address, data); + TIMER2_Write(*mcu.timer, address, data); return; } switch (address) @@ -385,11 +385,11 @@ 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) { @@ -856,12 +856,13 @@ void MCU_ReadInstruction(mcu_t& mcu) } } -void MCU_Init(mcu_t& mcu, submcu_t& sm, pcm_t& pcm) +void MCU_Init(mcu_t& mcu, submcu_t& sm, pcm_t& pcm, mcu_timer_t& timer) { memset(&mcu, 0, sizeof(mcu_t)); mcu.sw_pos = 3; mcu.sm = &sm; mcu.pcm = &pcm; + mcu.timer = &timer; mcu.romset = ROM_SET_MK2; mcu.rom2_mask = ROM2_SIZE - 1; } @@ -995,7 +996,7 @@ int SDLCALL work_thread(void* data) PCM_Update(*mcu.pcm, mcu.cycles); - TIMER_Clock(mcu, mcu.cycles); + TIMER_Clock(*mcu.timer, mcu.cycles); if (!mcu.mcu_mk1 && !mcu.mcu_jv880 && !mcu.mcu_scb55) SM_Update(*mcu.sm, mcu.cycles); @@ -1327,10 +1328,12 @@ int main(int argc, char *argv[]) mcu_t mcu; submcu_t sm; + mcu_timer_t timer; // allocate pcm because the waveroms will overflow the stack pcm_t* pcm = (pcm_t*)malloc(sizeof(pcm_t)); PCM_Reset(*pcm, mcu); - MCU_Init(mcu, sm, *pcm); + MCU_Init(mcu, sm, *pcm, timer); + TIMER_Init(timer, mcu); lcd_t lcd; { diff --git a/src/mcu.h b/src/mcu.h index 5b50bde4..1d95875d 100644 --- a/src/mcu.h +++ b/src/mcu.h @@ -39,6 +39,7 @@ struct submcu_t; struct pcm_t; +struct mcu_timer_t; enum { DEV_P1DDR = 0x00, @@ -213,6 +214,7 @@ struct mcu_t { submcu_t* sm; pcm_t* pcm; + mcu_timer_t* timer; uint32_t uart_write_ptr; uint32_t uart_read_ptr; diff --git a/src/mcu_timer.cpp b/src/mcu_timer.cpp index b65bf881..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(mcu_t& mcu, 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(mcu, 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(mcu, 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(mcu, 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(mcu_t& mcu, 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(mcu_t& mcu, uint32_t address, uint8_t data) { timer.tcsr &= ~0x20; timer.status_rd &= ~0x20; - MCU_Interrupt_SetRequest(mcu, 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(mcu, 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(mcu, 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(mcu_t& mcu, 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(mcu_t& mcu, 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.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(mcu, INTERRUPT_SOURCE_FRT0_FOVI + i * 4, 1); - if ((timer->tcr & 0x20) != 0 && (timer->tcsr & 0x20) != 0) - MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_FRT0_OCIA + i * 4, 1); - if ((timer->tcr & 0x40) != 0 && (timer->tcsr & 0x40) != 0) - MCU_Interrupt_SetRequest(mcu, 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(mcu_t& mcu, 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.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(mcu_t& mcu, uint64_t cycles) if (matchb) timer.tcsr |= 0x80; if ((timer.tcr & 0x20) != 0 && (timer.tcsr & 0x20) != 0) - MCU_Interrupt_SetRequest(mcu, 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(mcu, 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(mcu, 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 211b84a1..9a76f340 100644 --- a/src/mcu_timer.h +++ b/src/mcu_timer.h @@ -53,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(mcu_t& mcu, uint32_t address, uint8_t data); -uint8_t TIMER_Read(uint32_t address); -void TIMER_Clock(mcu_t& mcu, 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(mcu_t& mcu, 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); From 3889ef757935878b70ebcef86f81d6ef85126319 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Wed, 24 Apr 2024 19:36:07 -0400 Subject: [PATCH 09/35] Move ga_* globals into mcu_t --- src/mcu.cpp | 37 ++++++++++++++++--------------------- src/mcu.h | 5 +++++ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/mcu.cpp b/src/mcu.cpp index 61aeb49d..4c1d1897 100644 --- a/src/mcu.cpp +++ b/src/mcu.cpp @@ -134,11 +134,6 @@ void MCU_ErrorTrap(mcu_t& mcu) printf("%.2x %.4x\n", mcu.cp, mcu.pc); } -static int ga_int[8]; -static int ga_int_enable = 0; -static int ga_int_trigger = 0; -static int ga_lcd_counter = 0; - SDL_atomic_t mcu_button_pressed = { 0 }; uint8_t RCU_Read(void) @@ -542,8 +537,8 @@ uint8_t MCU_Read(mcu_t& mcu, uint32_t address) } else if (address == (base | 0x402)) { - ret = ga_int_trigger; - ga_int_trigger = 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 @@ -598,8 +593,8 @@ uint8_t MCU_Read(mcu_t& mcu, uint32_t address) } else if (address == 0xf106) { - ret = ga_int_trigger; - ga_int_trigger = 0; + ret = mcu.ga_int_trigger; + mcu.ga_int_trigger = 0; MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_IRQ1, 0); } else @@ -726,7 +721,7 @@ void MCU_Write(mcu_t& mcu, uint32_t address, uint8_t value) LCD_Enable((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); // @@ -793,12 +788,12 @@ void MCU_Write(mcu_t& mcu, uint32_t address, uint8_t value) else if (address == 0xf105) { LCD_Write(0, value); - ga_lcd_counter = 500; + mcu.ga_lcd_counter = 500; } else if (address == 0xf104) { LCD_Write(1, value); - ga_lcd_counter = 500; + mcu.ga_lcd_counter = 500; } else if (address == 0xf107) { @@ -898,7 +893,7 @@ void MCU_Reset(mcu_t& mcu) if (mcu.mcu_mk1) { - ga_int_enable = 255; + mcu.ga_int_enable = 255; } } @@ -1010,10 +1005,10 @@ int SDLCALL work_thread(void* data) if (mcu.mcu_mk1) { - if (ga_lcd_counter) + if (mcu.ga_lcd_counter) { - ga_lcd_counter--; - if (ga_lcd_counter == 0) + mcu.ga_lcd_counter--; + if (mcu.ga_lcd_counter == 0) { MCU_GA_SetGAInt(mcu, 1, 0); MCU_GA_SetGAInt(mcu, 1, 1); @@ -1246,14 +1241,14 @@ void MCU_PostSample(int *sample) 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.mcu_jv880) - MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_IRQ0, ga_int_trigger != 0); + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_IRQ0, mcu.ga_int_trigger != 0); else - MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_IRQ1, ga_int_trigger != 0); + MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_IRQ1, mcu.ga_int_trigger != 0); } void MCU_EncoderTrigger(mcu_t& mcu, int dir) diff --git a/src/mcu.h b/src/mcu.h index 1d95875d..a7ba114b 100644 --- a/src/mcu.h +++ b/src/mcu.h @@ -234,6 +234,11 @@ struct mcu_t { int mcu_sc155; // 0 - SC-55(MK2), 1 - SC-155(MK2) int rom2_mask = ROM2_SIZE - 1; + + int ga_int[8]; + int ga_int_enable = 0; + int ga_int_trigger = 0; + int ga_lcd_counter = 0; }; void MCU_ErrorTrap(mcu_t& mcu); From c77cfe97fd8ade4de2f04e6e5a4ca397caa51263 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Wed, 24 Apr 2024 19:41:29 -0400 Subject: [PATCH 10/35] Move mcu_button_pressed into mcu_t --- src/lcd.cpp | 4 ++-- src/mcu.cpp | 10 ++++------ src/mcu.h | 6 +++--- src/submcu.cpp | 4 ++-- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/lcd.cpp b/src/lcd.cpp index 8fec5b0a..9f3b9d79 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -545,7 +545,7 @@ void LCD_Update(lcd_t& lcd) continue; 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 = 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]); @@ -560,7 +560,7 @@ void LCD_Update(lcd_t& lcd) 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) diff --git a/src/mcu.cpp b/src/mcu.cpp index 4c1d1897..4f22502b 100644 --- a/src/mcu.cpp +++ b/src/mcu.cpp @@ -134,8 +134,6 @@ void MCU_ErrorTrap(mcu_t& mcu) printf("%.2x %.4x\n", mcu.cp, mcu.pc); } -SDL_atomic_t mcu_button_pressed = { 0 }; - uint8_t RCU_Read(void) { return 0; @@ -412,7 +410,7 @@ uint8_t MCU_DeviceRead(mcu_t& mcu, uint32_t address) 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 (mcu.io_sd == 0b11111011) data &= ((button_pressed >> 0) & 0b11111) ^ 0xFF; @@ -579,7 +577,7 @@ uint8_t MCU_Read(mcu_t& mcu, uint32_t address) LCD_Enable((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 ((mcu.io_sd & 1) == 0) data &= ((button_pressed >> 0) & 255) ^ 255; @@ -1058,10 +1056,10 @@ uint8_t MCU_ReadP0(void) 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) data &= ((button_pressed >> 0) & 255) ^ 255; diff --git a/src/mcu.h b/src/mcu.h index a7ba114b..b2446e40 100644 --- a/src/mcu.h +++ b/src/mcu.h @@ -239,6 +239,8 @@ struct mcu_t { int ga_int_enable = 0; int ga_int_trigger = 0; int ga_lcd_counter = 0; + + SDL_atomic_t mcu_button_pressed = { 0 }; }; void MCU_ErrorTrap(mcu_t& mcu); @@ -495,10 +497,8 @@ enum { extern const char* rs_name[ROM_SET_COUNT]; -extern SDL_atomic_t mcu_button_pressed; - uint8_t MCU_ReadP0(void); -uint8_t MCU_ReadP1(void); +uint8_t MCU_ReadP1(mcu_t& mcu); void MCU_WriteP0(uint8_t data); void MCU_WriteP1(uint8_t data); void MCU_GA_SetGAInt(mcu_t& mcu, int line, int value); diff --git a/src/submcu.cpp b/src/submcu.cpp index 4fe39b3e..0bc18de4 100644 --- a/src/submcu.cpp +++ b/src/submcu.cpp @@ -127,7 +127,7 @@ uint8_t SM_Read(submcu_t& sm, 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.sm_p1_dir; case SM_DEV_PRESCALER: @@ -276,7 +276,7 @@ uint8_t SM_SysRead(submcu_t& sm, uint32_t address) } else if (address == 0xf5) { - return MCU_ReadP1(); + return MCU_ReadP1(*sm.mcu); } else if (address == 0xf6) { From 3a5a4cfacbb07fc4448b7cf2ef3b84f3f019f1ec Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Wed, 24 Apr 2024 19:51:18 -0400 Subject: [PATCH 11/35] Move mcu_p0_data, mcu_p1_data into mcu_t --- src/mcu.cpp | 25 +++++++++++-------------- src/mcu.h | 9 ++++++--- src/submcu.cpp | 8 ++++---- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/mcu.cpp b/src/mcu.cpp index 4f22502b..b7201a05 100644 --- a/src/mcu.cpp +++ b/src/mcu.cpp @@ -1041,17 +1041,14 @@ static void MCU_Run(mcu_t& mcu, lcd_t& lcd) SDL_WaitThread(thread, 0); } -void MCU_PatchROM(void) +void MCU_PatchROM(mcu_t& 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) { return 0xff; } @@ -1061,26 +1058,26 @@ uint8_t MCU_ReadP1(mcu_t& mcu) uint8_t data = 0xff; 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) +void MCU_WriteP0(mcu_t& mcu, uint8_t data) { - mcu_p0_data = data; + mcu.mcu_p0_data = data; } -void MCU_WriteP1(uint8_t data) +void MCU_WriteP1(mcu_t& mcu, uint8_t data) { - mcu_p1_data = data; + mcu.mcu_p1_data = data; } uint8_t tempbuf[0x800000]; @@ -1697,7 +1694,7 @@ int main(int argc, char *argv[]) } LCD_Init(lcd, mcu); - MCU_PatchROM(); + MCU_PatchROM(mcu); MCU_Reset(mcu); SM_Reset(sm, mcu); diff --git a/src/mcu.h b/src/mcu.h index b2446e40..f8f13dbe 100644 --- a/src/mcu.h +++ b/src/mcu.h @@ -241,6 +241,9 @@ struct mcu_t { int ga_lcd_counter = 0; SDL_atomic_t mcu_button_pressed = { 0 }; + + uint8_t mcu_p0_data = 0x00; + uint8_t mcu_p1_data = 0x00; }; void MCU_ErrorTrap(mcu_t& mcu); @@ -497,10 +500,10 @@ enum { extern const char* rs_name[ROM_SET_COUNT]; -uint8_t MCU_ReadP0(void); +uint8_t MCU_ReadP0(mcu_t& mcu); uint8_t MCU_ReadP1(mcu_t& mcu); -void MCU_WriteP0(uint8_t data); -void MCU_WriteP1(uint8_t data); +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(mcu_t& mcu, int dir); diff --git a/src/submcu.cpp b/src/submcu.cpp index 0bc18de4..db0d040c 100644 --- a/src/submcu.cpp +++ b/src/submcu.cpp @@ -164,7 +164,7 @@ void SM_Write(submcu_t& sm, 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.sm_p1_dir = data; @@ -235,11 +235,11 @@ void SM_SysWrite(submcu_t& sm, uint32_t address, uint8_t data) } 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) { @@ -280,7 +280,7 @@ uint8_t SM_SysRead(submcu_t& sm, uint32_t address) } else if (address == 0xf6) { - return MCU_ReadP0(); + return MCU_ReadP0(*sm.mcu); } else if (address == 0xf7) { From 93bf4fc9af9d8959c57f10272c854532abbab1b6 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Wed, 24 Apr 2024 19:57:08 -0400 Subject: [PATCH 12/35] Make midi_rtmidi conform to new interface --- src/midi_rtmidi.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/midi_rtmidi.cpp b/src/midi_rtmidi.cpp index d16036bc..a9dca649 100644 --- a/src/midi_rtmidi.cpp +++ b/src/midi_rtmidi.cpp @@ -5,6 +5,7 @@ static RtMidiIn *s_midi_in = nullptr; +static mcu_t* midi_mcu_instance = nullptr; static void MidiOnReceive(double, std::vector *message, void *) { @@ -12,7 +13,7 @@ static void MidiOnReceive(double, std::vector *message, void *) uint8_t *end = message->data() + message->size(); while(beg < end) - MCU_PostUART(*beg++); + MCU_PostUART(*midi_mcu_instance, *beg++); } static void MidiOnError(RtMidiError::Type, const std::string &errorText, void *) @@ -21,7 +22,7 @@ static void MidiOnError(RtMidiError::Type, const std::string &errorText, void *) fflush(stderr); } -int MIDI_Init(int port) +int MIDI_Init(mcu_t& mcu, int port) { if (s_midi_in) { @@ -29,6 +30,8 @@ int MIDI_Init(int port) return 0; // Already running } + midi_mcu_instance = &mcu; + 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 +65,6 @@ void MIDI_Quit() s_midi_in->closePort(); delete s_midi_in; s_midi_in = nullptr; + midi_mcu_instance = nullptr; } } From 65630d5362a6e89fdddb19cd15df3788aae78bf5 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Wed, 24 Apr 2024 22:00:07 -0400 Subject: [PATCH 13/35] Move global lcd state into lcd_t --- src/lcd.cpp | 224 +++++++++++++++++++++++++--------------------------- src/lcd.h | 34 ++++++-- src/mcu.cpp | 37 ++++----- src/mcu.h | 2 + 4 files changed, 155 insertions(+), 142 deletions(-) diff --git a/src/lcd.cpp b/src/lcd.cpp index 9f3b9d79..588260e4 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -43,66 +43,56 @@ #include "submcu.h" #include "utils/files.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 +101,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 +152,10 @@ 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,27 +200,38 @@ const int button_map_jv880[][2] = }; -void LCD_SetBackPath(const std::string &path) +void LCD_SetBackPath(lcd_t& lcd, const std::string &path) { - m_back_path = path; + lcd.m_back_path = path; } void LCD_Init(lcd_t& lcd, mcu_t& mcu) { FILE *raw; - if(lcd_init) + if (lcd.lcd_init) return; + if (mcu.romset == ROM_SET_JV880) + { + lcd.lcd_width = 820; + lcd.lcd_height = 100; + } + else + { + lcd.lcd_width = 741; + lcd.lcd_height = 268; + } + lcd.mcu = &mcu; - lcd_quit_requested = false; + lcd.lcd_quit_requested = false; std::string title = "Nuked SC-55: "; title += rs_name[mcu.romset]; - window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, lcd_width, lcd_height, SDL_WINDOW_SHOWN); + window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, lcd.lcd_width, lcd.lcd_height, SDL_WINDOW_SHOWN); if (!window) return; @@ -249,37 +239,37 @@ void LCD_Init(lcd_t& lcd, mcu_t& mcu) if (!renderer) return; - texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_BGR888, SDL_TEXTUREACCESS_STREAMING, lcd_width, lcd_height); + texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_BGR888, SDL_TEXTUREACCESS_STREAMING, lcd.lcd_width, lcd.lcd_height); if (!texture) return; - raw = Files::utf8_fopen(m_back_path.c_str(), "rb"); + raw = Files::utf8_fopen(lcd.m_back_path.c_str(), "rb"); if (!raw) return; - fread(lcd_background, 1, sizeof(lcd_background), raw); + fread(lcd.lcd_background, 1, sizeof(lcd.lcd_background), raw); fclose(raw); - lcd_init = 1; + lcd.lcd_init = 1; } -void LCD_UnInit(void) +void LCD_UnInit(lcd_t& lcd) { - if(!lcd_init) + if (!lcd.lcd_init) return; } 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++) @@ -300,22 +290,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++) @@ -335,7 +325,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; } } } @@ -380,13 +370,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) { @@ -403,7 +393,7 @@ 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; } } } @@ -411,32 +401,32 @@ void LCD_FontRenderLR(uint8_t ch) void LCD_Update(lcd_t& lcd) { - if (!lcd_init) + if (!lcd.lcd_init) return; if (!lcd.mcu->mcu_cm300 && !lcd.mcu->mcu_st && !lcd.mcu->mcu_scb55) { MCU_WorkThread_Lock(); - if (!lcd_enable && !lcd.mcu->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 (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]; } } } @@ -447,68 +437,68 @@ void LCD_Update(lcd_t& lcd) { 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); } } } @@ -516,7 +506,7 @@ void LCD_Update(lcd_t& lcd) MCU_WorkThread_Unlock(); - SDL_UpdateTexture(texture, NULL, lcd_buffer, lcd_width_max * 4); + SDL_UpdateTexture(texture, NULL, lcd.lcd_buffer, lcd_width_max * 4); SDL_RenderCopy(renderer, texture, NULL, NULL); SDL_RenderPresent(renderer); } @@ -535,7 +525,7 @@ void LCD_Update(lcd_t& lcd) switch (sdl_event.type) { case SDL_QUIT: - lcd_quit_requested = true; + lcd.lcd_quit_requested = true; break; case SDL_KEYDOWN: diff --git a/src/lcd.h b/src/lcd.h index 29c81e8a..0cc4ff63 100644 --- a/src/lcd.h +++ b/src/lcd.h @@ -38,18 +38,38 @@ struct mcu_t; +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_init = 0; + + 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 = 0; + uint8_t LCD_Data[80]; + uint8_t LCD_CG[64]; + + uint8_t lcd_enable = 1; + bool lcd_quit_requested = false; + + std::string m_back_path = "back.data"; + + uint32_t lcd_buffer[lcd_height_max][lcd_width_max]; + uint32_t lcd_background[268][741]; }; -extern int lcd_width; -extern int lcd_height; -void LCD_SetBackPath(const std::string &path); +void LCD_SetBackPath(lcd_t& lcd, const std::string &path); void LCD_Init(lcd_t& lcd, mcu_t& mcu); -void LCD_UnInit(void); -void LCD_Write(uint32_t address, uint8_t data); -void LCD_Enable(uint32_t enable); -bool LCD_QuitRequested(); +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(lcd_t& lcd); diff --git a/src/mcu.cpp b/src/mcu.cpp index b7201a05..173ec20e 100644 --- a/src/mcu.cpp +++ b/src/mcu.cpp @@ -574,7 +574,7 @@ uint8_t MCU_Read(mcu_t& mcu, uint32_t address) if (mcu.mcu_cm300) return 0xff; - LCD_Enable((mcu.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.mcu_button_pressed); @@ -712,11 +712,11 @@ void MCU_Write(mcu_t& mcu, uint32_t address, uint8_t value) 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)) { mcu.io_sd = value; - LCD_Enable((value & 1) == 0); + LCD_Enable(*mcu.lcd, (value & 1) == 0); } else if (address == (base | 0x402)) mcu.ga_int_enable = (value << 1); @@ -781,16 +781,16 @@ void MCU_Write(mcu_t& mcu, uint32_t address, uint8_t value) else if (address >= 0xf000 && address < 0xf100) { mcu.io_sd = address & 0xff; - LCD_Enable((mcu.io_sd & 8) != 0); + LCD_Enable(*mcu.lcd, (mcu.io_sd & 8) != 0); } else if (address == 0xf105) { - LCD_Write(0, value); + LCD_Write(*mcu.lcd, 0, value); mcu.ga_lcd_counter = 500; } else if (address == 0xf104) { - LCD_Write(1, value); + LCD_Write(*mcu.lcd, 1, value); mcu.ga_lcd_counter = 500; } else if (address == 0xf107) @@ -849,13 +849,14 @@ void MCU_ReadInstruction(mcu_t& mcu) } } -void MCU_Init(mcu_t& mcu, submcu_t& sm, pcm_t& pcm, mcu_timer_t& timer) +void 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; } @@ -1021,7 +1022,7 @@ int SDLCALL work_thread(void* data) return 0; } -static void MCU_Run(mcu_t& mcu, lcd_t& lcd) +static void MCU_Run(mcu_t& mcu) { bool working = true; @@ -1030,10 +1031,10 @@ static void MCU_Run(mcu_t& mcu, lcd_t& lcd) while (working) { - if(LCD_QuitRequested()) + if(LCD_QuitRequested(*mcu.lcd)) working = false; - LCD_Update(lcd); + LCD_Update(*mcu.lcd); SDL_Delay(15); } @@ -1319,12 +1320,13 @@ int main(int argc, char *argv[]) mcu_t mcu; submcu_t sm; mcu_timer_t timer; + // allocate pcm because the bitmaps will overflow the stack + lcd_t* lcd = (lcd_t*)malloc(sizeof(lcd_t)); // allocate pcm because the waveroms will overflow the stack pcm_t* pcm = (pcm_t*)malloc(sizeof(pcm_t)); PCM_Reset(*pcm, mcu); - MCU_Init(mcu, sm, *pcm, timer); + MCU_Init(mcu, sm, *pcm, timer, *lcd); TIMER_Init(timer, mcu); - lcd_t lcd; { for (int i = 1; i < argc; i++) @@ -1481,6 +1483,7 @@ int main(int argc, char *argv[]) printf("ROM set autodetect: %s\n", rs_name[romset]); } + mcu.romset = romset; mcu.mcu_mk1 = false; mcu.mcu_cm300 = false; mcu.mcu_st = false; @@ -1511,8 +1514,6 @@ int main(int argc, char *argv[]) case ROM_SET_JV880: mcu.mcu_jv880 = true; mcu.rom2_mask /= 2; // rom is half the size - lcd_width = 820; - lcd_height = 100; break; case ROM_SET_SCB55: case ROM_SET_RLP3237: @@ -1553,7 +1554,7 @@ int main(int argc, char *argv[]) return 1; } - LCD_SetBackPath(basePath + "/back.data"); + LCD_SetBackPath(*lcd, basePath + "/back.data"); if (fread(mcu.rom1, 1, ROM1_SIZE, s_rf[0]) != ROM1_SIZE) { @@ -1693,18 +1694,18 @@ int main(int argc, char *argv[]) fflush(stderr); } - LCD_Init(lcd, mcu); + LCD_Init(*lcd, mcu); MCU_PatchROM(mcu); MCU_Reset(mcu); SM_Reset(sm, mcu); if (resetType != ResetType::NONE) MIDI_Reset(mcu, resetType); - MCU_Run(mcu, lcd); + MCU_Run(mcu); MCU_CloseAudio(); MIDI_Quit(); - LCD_UnInit(); + LCD_UnInit(*lcd); SDL_Quit(); free(pcm); diff --git a/src/mcu.h b/src/mcu.h index f8f13dbe..09658bd7 100644 --- a/src/mcu.h +++ b/src/mcu.h @@ -40,6 +40,7 @@ struct submcu_t; struct pcm_t; struct mcu_timer_t; +struct lcd_t; enum { DEV_P1DDR = 0x00, @@ -215,6 +216,7 @@ struct mcu_t { submcu_t* sm; pcm_t* pcm; mcu_timer_t* timer; + lcd_t* lcd; uint32_t uart_write_ptr; uint32_t uart_read_ptr; From 2b1d5216d0b51664c3f2ff758d1e0d15b5ed59c0 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Wed, 24 Apr 2024 22:19:39 -0400 Subject: [PATCH 14/35] Move adf_rd, analog_end_time, ssr_rd into mcu_t --- src/mcu.cpp | 32 +++++++++++++------------------- src/mcu.h | 6 ++++++ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/mcu.cpp b/src/mcu.cpp index 173ec20e..acec0ee6 100644 --- a/src/mcu.cpp +++ b/src/mcu.cpp @@ -246,12 +246,6 @@ void MCU_AnalogSample(mcu_t& mcu, int channel) mcu.dev_register[DEV_ADDRAL + dest] = (value << 6) & 0xc0; } -int adf_rd = 0; - -uint64_t analog_end_time; - -int ssr_rd = 0; - void MCU_DeviceWrite(mcu_t& mcu, uint32_t address, uint8_t data) { address &= 0x7f; @@ -333,7 +327,7 @@ void MCU_DeviceWrite(mcu_t& mcu, uint32_t address, uint8_t data) { mcu.dev_register[address] &= ~0x7f; mcu.dev_register[address] |= data & 0x7f; - if ((data & 0x80) == 0 && adf_rd) + if ((data & 0x80) == 0 && mcu.adf_rd) { mcu.dev_register[address] &= ~0x80; MCU_Interrupt_SetRequest(mcu, INTERRUPT_SOURCE_ANALOG, 0); @@ -344,23 +338,23 @@ void MCU_DeviceWrite(mcu_t& mcu, uint32_t address, uint8_t data) } case DEV_SSR: { - if ((data & 0x80) == 0 && (ssr_rd & 0x80) != 0) + if ((data & 0x80) == 0 && (mcu.ssr_rd & 0x80) != 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) { 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) { mcu.dev_register[address] &= ~0x20; } - if ((data & 0x10) == 0 && (ssr_rd & 0x10) != 0) + if ((data & 0x10) == 0 && (mcu.ssr_rd & 0x10) != 0) { mcu.dev_register[address] &= ~0x10; } @@ -396,10 +390,10 @@ uint8_t MCU_DeviceRead(mcu_t& mcu, uint32_t address) case DEV_ADDRDL: return mcu.dev_register[address]; case DEV_ADCSR: - adf_rd = (mcu.dev_register[address] & 0x80) != 0; + mcu.adf_rd = (mcu.dev_register[address] & 0x80) != 0; return mcu.dev_register[address]; case DEV_SSR: - ssr_rd = mcu.dev_register[address]; + mcu.ssr_rd = mcu.dev_register[address]; return mcu.dev_register[address]; case DEV_RDR: return mcu.uart_rx_byte; @@ -470,22 +464,22 @@ void MCU_UpdateAnalog(mcu_t& mcu, uint64_t cycles) 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(mcu, base + i); - analog_end_time = cycles + 200; + mcu.analog_end_time = cycles + 200; } else { MCU_AnalogSample(mcu, ctrl & 7); mcu.dev_register[DEV_ADCSR] &= ~0x20; - analog_end_time = 0; + mcu.analog_end_time = 0; } mcu.dev_register[DEV_ADCSR] |= 0x80; if (ctrl & 0x40) @@ -493,7 +487,7 @@ void MCU_UpdateAnalog(mcu_t& mcu, uint64_t cycles) } } else - analog_end_time = 0; + mcu.analog_end_time = 0; } uint8_t MCU_Read(mcu_t& mcu, uint32_t address) diff --git a/src/mcu.h b/src/mcu.h index 09658bd7..46bbc925 100644 --- a/src/mcu.h +++ b/src/mcu.h @@ -246,6 +246,12 @@ struct mcu_t { uint8_t mcu_p0_data = 0x00; uint8_t mcu_p1_data = 0x00; + + int adf_rd = 0; + + uint64_t analog_end_time; + + int ssr_rd = 0; }; void MCU_ErrorTrap(mcu_t& mcu); From a89ddb1db89b3c0b2d9198c5b4f2bc68b090a15b Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Wed, 24 Apr 2024 22:41:59 -0400 Subject: [PATCH 15/35] Move operand globals into mcu_t --- src/mcu.h | 9 ++ src/mcu_opcodes.cpp | 235 +++++++++++++++++++++----------------------- 2 files changed, 122 insertions(+), 122 deletions(-) diff --git a/src/mcu.h b/src/mcu.h index 46bbc925..c4baf98a 100644 --- a/src/mcu.h +++ b/src/mcu.h @@ -252,6 +252,15 @@ struct mcu_t { uint64_t analog_end_time; int ssr_rd = 0; + + 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 MCU_ErrorTrap(mcu_t& mcu); diff --git a/src/mcu_opcodes.cpp b/src/mcu_opcodes.cpp index 9c1cac92..5c4c9a13 100644 --- a/src/mcu_opcodes.cpp +++ b/src/mcu_opcodes.cpp @@ -491,65 +491,56 @@ void MCU_Jump_PJMP(mcu_t& mcu, uint8_t operand) 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(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(mcu, EXCEPTION_SOURCE_ADDRESS_ERROR); } - return MCU_Read16(mcu, MCU_GetAddress(operand_ep, operand_ea)); + return MCU_Read16(mcu, MCU_GetAddress(mcu.operand_ep, mcu.operand_ea)); } - return MCU_Read(mcu, 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(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(mcu, EXCEPTION_SOURCE_ADDRESS_ERROR); } - MCU_Write16(mcu, MCU_GetAddress(operand_ep, operand_ea), data); + MCU_Write16(mcu, MCU_GetAddress(mcu.operand_ep, mcu.operand_ea), data); } else - MCU_Write(mcu, 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(mcu, EXCEPTION_SOURCE_INVALID_INSTRUCTION); @@ -670,21 +661,21 @@ void MCU_Operand_General(mcu_t& mcu, uint8_t operand) } opcode = MCU_ReadCodeAdvance(mcu); - opcode_extended = opcode == 0x00; - if (opcode_extended) + mcu.opcode_extended = opcode == 0x00; + if (mcu.opcode_extended) { 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](mcu, opcode, opcode_reg); } @@ -842,32 +833,32 @@ void MCU_Opcode_NotImplemented(mcu_t& mcu, 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); MCU_Operand_Write(mcu, data); - MCU_SetStatusCommon(mcu, data, operand_size); + 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(mcu) << 8; data |= MCU_ReadCodeAdvance(mcu); MCU_Operand_Write(mcu, data); - MCU_SetStatusCommon(mcu, data, operand_size); + 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(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(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(mcu); @@ -875,7 +866,7 @@ void MCU_Opcode_MOVG_Immediate(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) 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(mcu); @@ -891,15 +882,15 @@ void MCU_Opcode_MOVG_Immediate(mcu_t& mcu, 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(mcu); - uint32_t val = MCU_ControlRegisterRead(mcu, opcode_reg, operand_size); + uint32_t val = MCU_ControlRegisterRead(mcu, opcode_reg, mcu.operand_size); val |= data; - MCU_ControlRegisterWrite(mcu, opcode_reg, operand_size, val); + MCU_ControlRegisterWrite(mcu, opcode_reg, mcu.operand_size, val); if (opcode_reg >= 2) { - MCU_SetStatusCommon(mcu, val, operand_size); + MCU_SetStatusCommon(mcu, val, mcu.operand_size); } mcu.ex_ignore = 1; } @@ -915,15 +906,15 @@ void MCU_Opcode_BSET_ORC(mcu_t& mcu, 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(mcu); - uint32_t val = MCU_ControlRegisterRead(mcu, opcode_reg, operand_size); + uint32_t val = MCU_ControlRegisterRead(mcu, opcode_reg, mcu.operand_size); val &= data; - MCU_ControlRegisterWrite(mcu, opcode_reg, operand_size, val); + MCU_ControlRegisterWrite(mcu, opcode_reg, mcu.operand_size, val); if (opcode_reg >= 2) { - MCU_SetStatusCommon(mcu, val, operand_size); + MCU_SetStatusCommon(mcu, val, mcu.operand_size); } mcu.ex_ignore = 1; } @@ -939,7 +930,7 @@ void MCU_Opcode_BCLR_ANDC(mcu_t& mcu, 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(mcu); uint32_t bit = mcu.r[opcode_reg] & 0x0f; @@ -953,7 +944,7 @@ void MCU_Opcode_BTST(mcu_t& mcu, 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(mcu, 0); MCU_SetStatus(mcu, 0, STATUS_N); @@ -961,48 +952,48 @@ void MCU_Opcode_CLR(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) 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); - MCU_SetStatusCommon(mcu, data, operand_size); + 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; + 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.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(mcu); data = ~data; MCU_Operand_Write(mcu, data); - MCU_SetStatusCommon(mcu, data, operand_size); + 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(mcu); - data = MCU_SUB_Common(mcu, 0, data, 0, operand_size); + 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; + uint32_t data = mcu.r[mcu.operand_reg]; + mcu.r[mcu.operand_reg] = (int8_t)data; MCU_SetStatusCommon(mcu, data, OPERAND_WORD); } else @@ -1014,19 +1005,19 @@ void MCU_Opcode_CLR(mcu_t& mcu, 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); - MCU_ControlRegisterWrite(mcu, opcode_reg, operand_size, data); + MCU_ControlRegisterWrite(mcu, opcode_reg, mcu.operand_size, data); mcu.ex_ignore = 1; } void MCU_Opcode_STC(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { - uint32_t data = MCU_ControlRegisterRead(mcu, opcode_reg, operand_size); + uint32_t data = MCU_ControlRegisterRead(mcu, opcode_reg, mcu.operand_size); MCU_Operand_Write(mcu, data); } 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(mcu); uint32_t bit = opcode_reg | ((opcode & 1) << 3); @@ -1042,7 +1033,7 @@ void MCU_Opcode_BSET(mcu_t& mcu, 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(mcu); uint32_t bit = opcode_reg | ((opcode & 1) << 3); @@ -1058,7 +1049,7 @@ void MCU_Opcode_BCLR(mcu_t& mcu, 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) { @@ -1076,14 +1067,14 @@ void MCU_Opcode_MOVG(mcu_t& mcu, 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 { @@ -1094,27 +1085,27 @@ void MCU_Opcode_MOVG(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { data = mcu.r[opcode_reg]; MCU_Operand_Write(mcu, data); - MCU_SetStatusCommon(mcu, data, operand_size); + MCU_SetStatusCommon(mcu, data, mcu.operand_size); } } else { data = MCU_Operand_Read(mcu); - if (operand_size) + if (mcu.operand_size) mcu.r[opcode_reg] = data; else { mcu.r[opcode_reg] &= ~0xff; mcu.r[opcode_reg] |= data & 0xff; } - MCU_SetStatusCommon(mcu, data, operand_size); + MCU_SetStatusCommon(mcu, data, mcu.operand_size); } } } 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(mcu); uint32_t bit = opcode_reg | ((opcode & 1) << 3); @@ -1128,7 +1119,7 @@ void MCU_Opcode_BTSTI(mcu_t& mcu, 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(mcu); uint32_t bit = opcode_reg | ((opcode & 1) << 3); @@ -1146,14 +1137,14 @@ void MCU_Opcode_OR(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { uint32_t data = MCU_Operand_Read(mcu); mcu.r[opcode_reg] |= data; - MCU_SetStatusCommon(mcu, mcu.r[opcode_reg], operand_size); + MCU_SetStatusCommon(mcu, mcu.r[opcode_reg], mcu.operand_size); } 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); - MCU_SUB_Common(mcu, t1, t2, 0, operand_size); + MCU_SUB_Common(mcu, t1, t2, 0, mcu.operand_size); } void MCU_Opcode_ADDQ(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) @@ -1178,7 +1169,7 @@ void MCU_Opcode_ADDQ(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) MCU_ErrorTrap(mcu); break; } - t1 = MCU_ADD_Common(mcu, t1, t2, 0, operand_size); + t1 = MCU_ADD_Common(mcu, t1, t2, 0, mcu.operand_size); MCU_Operand_Write(mcu, t1); } @@ -1186,8 +1177,8 @@ 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(mcu); - t1 = MCU_ADD_Common(mcu, t1, t2, 0, operand_size); - if (operand_size) + t1 = MCU_ADD_Common(mcu, t1, t2, 0, mcu.operand_size); + if (mcu.operand_size) mcu.r[opcode_reg] = t1; else { @@ -1200,8 +1191,8 @@ 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(mcu); - t1 = MCU_SUB_Common(mcu, t1, t2, 0, operand_size); - if (operand_size) + t1 = MCU_SUB_Common(mcu, t1, t2, 0, mcu.operand_size); + if (mcu.operand_size) mcu.r[opcode_reg] = t1; else { @@ -1214,7 +1205,7 @@ 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(mcu); - if (operand_size) + if (mcu.operand_size) mcu.r[opcode_reg] = t1 - t2; else mcu.r[opcode_reg] = t1 - (int8_t)t2; @@ -1224,46 +1215,46 @@ 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(mcu); - if (operand_size) + if (mcu.operand_size) mcu.r[opcode_reg] = data; else { mcu.r[opcode_reg] &= ~0xff; mcu.r[opcode_reg] |= data & 0xff; } - MCU_SetStatusCommon(mcu, mcu.r[opcode_reg], operand_size); + MCU_SetStatusCommon(mcu, mcu.r[opcode_reg], mcu.operand_size); } 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(mcu); uint32_t C = data & 1; data >>= 1; MCU_Operand_Write(mcu, data); MCU_SetStatus(mcu, C, STATUS_C); - MCU_SetStatusCommon(mcu, data, operand_size); + 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(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(mcu, data); MCU_SetStatus(mcu, C, STATUS_C); - MCU_SetStatusCommon(mcu, data, operand_size); + 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(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; @@ -1271,13 +1262,13 @@ void MCU_Opcode_SHLR(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) data |= bit; MCU_Operand_Write(mcu, data); MCU_SetStatus(mcu, C, STATUS_C); - MCU_SetStatusCommon(mcu, data, operand_size); + 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(mcu); uint32_t C; - if (operand_size) + if (mcu.operand_size) C = (data & 0x8000) != 0; else C = (data & 0x80) != 0; @@ -1285,27 +1276,27 @@ void MCU_Opcode_SHLR(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) data |= C; MCU_Operand_Write(mcu, data); MCU_SetStatus(mcu, C, STATUS_C); - MCU_SetStatusCommon(mcu, data, operand_size); + 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(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(mcu, data); MCU_SetStatus(mcu, C, STATUS_C); - MCU_SetStatusCommon(mcu, data, operand_size); + 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(mcu); uint32_t C = data & 0x1; uint32_t msb; - if (operand_size) + if (mcu.operand_size) { msb = data & 0x8000; data &= 0x7fff; @@ -1319,20 +1310,20 @@ void MCU_Opcode_SHLR(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) data |= msb; MCU_Operand_Write(mcu, data); MCU_SetStatus(mcu, C, STATUS_C); - MCU_SetStatusCommon(mcu, data, operand_size); + 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(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(mcu, data); MCU_SetStatus(mcu, C, STATUS_C); - MCU_SetStatusCommon(mcu, data, operand_size); + MCU_SetStatusCommon(mcu, data, mcu.operand_size); } else { @@ -1345,11 +1336,11 @@ void MCU_Opcode_MULXU(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) 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; @@ -1385,7 +1376,7 @@ void MCU_Opcode_DIVXU(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) return; } - if (operand_size) + if (mcu.operand_size) { opcode_reg &= ~1; t2 = mcu.r[opcode_reg | 0] << 16; @@ -1437,7 +1428,7 @@ void MCU_Opcode_DIVXU(mcu_t& mcu, 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(mcu); - if (!operand_size) + if (!mcu.operand_size) data = (int8_t)data; mcu.r[opcode_reg] += data; } @@ -1446,7 +1437,7 @@ void MCU_Opcode_XOR(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) { uint32_t data = MCU_Operand_Read(mcu); mcu.r[opcode_reg] ^= data; - MCU_SetStatusCommon(mcu, mcu.r[opcode_reg], operand_size); + MCU_SetStatusCommon(mcu, mcu.r[opcode_reg], mcu.operand_size); } void MCU_Opcode_ADDX(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) @@ -1455,11 +1446,11 @@ void MCU_Opcode_ADDX(mcu_t& mcu, uint8_t opcode, uint8_t opcode_reg) 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(mcu, t1, t2, C, operand_size); + t1 = MCU_ADD_Common(mcu, t1, t2, C, mcu.operand_size); if (!Z) MCU_SetStatus(mcu, 0, STATUS_Z); - if (operand_size) + if (mcu.operand_size) mcu.r[opcode_reg] = t1; else { @@ -1473,8 +1464,8 @@ 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(mcu); int32_t C = (mcu.sr & STATUS_C) != 0; - t1 = MCU_SUB_Common(mcu, 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 { From c7d8f25e868012e4956cdf1ca4dc9566bf98e0f5 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Thu, 25 Apr 2024 03:08:09 -0400 Subject: [PATCH 16/35] Move window, renderer, texture into lcd_t --- src/lcd.cpp | 23 +++++++++-------------- src/lcd.h | 5 +++++ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/lcd.cpp b/src/lcd.cpp index 588260e4..f8c63134 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -35,7 +35,6 @@ #include #include #include -#include "SDL.h" #include "SDL_mutex.h" #include "lcd.h" #include "lcd_font.h" @@ -152,10 +151,6 @@ void LCD_Write(lcd_t& lcd, uint32_t address, uint8_t data) // printf("\n"); } -static SDL_Window *window; -static SDL_Renderer *renderer; -static SDL_Texture *texture; - const int button_map_sc55[][2] = { SDL_SCANCODE_Q, MCU_BUTTON_POWER, @@ -231,17 +226,17 @@ void LCD_Init(lcd_t& lcd, mcu_t& mcu) title += rs_name[mcu.romset]; - window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, lcd.lcd_width, lcd.lcd_height, SDL_WINDOW_SHOWN); - if (!window) + 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; - renderer = SDL_CreateRenderer(window, -1, 0); - if (!renderer) + lcd.renderer = SDL_CreateRenderer(lcd.window, -1, 0); + if (!lcd.renderer) return; - texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_BGR888, SDL_TEXTUREACCESS_STREAMING, lcd.lcd_width, lcd.lcd_height); + lcd.texture = SDL_CreateTexture(lcd.renderer, SDL_PIXELFORMAT_BGR888, SDL_TEXTUREACCESS_STREAMING, lcd.lcd_width, lcd.lcd_height); - if (!texture) + if (!lcd.texture) return; raw = Files::utf8_fopen(lcd.m_back_path.c_str(), "rb"); @@ -506,9 +501,9 @@ void LCD_Update(lcd_t& lcd) MCU_WorkThread_Unlock(); - SDL_UpdateTexture(texture, NULL, lcd.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; diff --git a/src/lcd.h b/src/lcd.h index 0cc4ff63..7645e3cd 100644 --- a/src/lcd.h +++ b/src/lcd.h @@ -35,6 +35,7 @@ #include #include +#include "SDL.h" struct mcu_t; @@ -62,6 +63,10 @@ struct lcd_t { 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; }; From 17d24298285bebd8fbda4fe239c9040e47734393 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Thu, 25 Apr 2024 03:13:42 -0400 Subject: [PATCH 17/35] Extract event loop from LCD update in preparation for multi-LCD --- src/lcd.cpp | 38 ++++++++++++++++++-------------------- src/lcd.h | 1 + src/mcu.cpp | 7 +++++++ 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/lcd.cpp b/src/lcd.cpp index f8c63134..1f11d1c4 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -505,30 +505,30 @@ void LCD_Update(lcd_t& lcd) 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) +{ + if (sdl_event.type == SDL_KEYDOWN) { - 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); - } + 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; + switch (sdl_event.type) + { + case SDL_QUIT: + lcd.lcd_quit_requested = true; + break; - case SDL_KEYDOWN: - case SDL_KEYUP: + case SDL_KEYDOWN: + case SDL_KEYUP: { if (sdl_event.key.repeat) - continue; - + break; + int mask = 0; uint32_t button_pressed = (uint32_t)SDL_AtomicGet(&lcd.mcu->mcu_button_pressed); @@ -644,7 +644,5 @@ void LCD_Update(lcd_t& lcd) #endif break; } - } } } - diff --git a/src/lcd.h b/src/lcd.h index 7645e3cd..c9531bbd 100644 --- a/src/lcd.h +++ b/src/lcd.h @@ -78,3 +78,4 @@ void LCD_Enable(lcd_t& lcd, uint32_t enable); bool LCD_QuitRequested(lcd_t& lcd); void LCD_Sync(void); void LCD_Update(lcd_t& lcd); +void LCD_HandleEvent(lcd_t& lcd, const SDL_Event& sdl_event); diff --git a/src/mcu.cpp b/src/mcu.cpp index acec0ee6..5e9d8763 100644 --- a/src/mcu.cpp +++ b/src/mcu.cpp @@ -1029,6 +1029,13 @@ static void MCU_Run(mcu_t& mcu) working = false; LCD_Update(*mcu.lcd); + + SDL_Event sdl_event; + while (SDL_PollEvent(&sdl_event)) + { + LCD_HandleEvent(*mcu.lcd, sdl_event); + } + SDL_Delay(15); } From 94f248b6d68738f8a862738c68e4a9e43da52ce7 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Thu, 25 Apr 2024 05:06:27 -0400 Subject: [PATCH 18/35] Split into frontend and backend The existing SDL application becomes the frontend. The backend consists of all the emulator modules (mcu, timer, pcm, etc). The goal here is to make the backend reusable between different frontend applications as a library. --- CMakeLists.txt | 19 +- src/lcd.cpp | 4 +- src/main_frontend.cpp | 803 +++++++++++++++++++++++++++++++++++++++++ src/mcu.cpp | 815 +++--------------------------------------- src/mcu.h | 24 +- src/pcm.cpp | 4 +- 6 files changed, 888 insertions(+), 781 deletions(-) create mode 100644 src/main_frontend.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f4143fc..82bf3ad9 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 @@ -200,13 +200,19 @@ set(SC55_SRC 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 +220,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/lcd.cpp b/src/lcd.cpp index 1f11d1c4..8978278a 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -401,7 +401,7 @@ void LCD_Update(lcd_t& lcd) if (!lcd.mcu->mcu_cm300 && !lcd.mcu->mcu_st && !lcd.mcu->mcu_scb55) { - MCU_WorkThread_Lock(); + MCU_WorkThread_Lock(*lcd.mcu); if (!lcd.lcd_enable && !lcd.mcu->mcu_jv880) { @@ -499,7 +499,7 @@ void LCD_Update(lcd_t& lcd) } } - MCU_WorkThread_Unlock(); + MCU_WorkThread_Unlock(*lcd.mcu); SDL_UpdateTexture(lcd.texture, NULL, lcd.lcd_buffer, lcd_width_max * 4); SDL_RenderCopy(lcd.renderer, lcd.texture, NULL, NULL); diff --git a/src/main_frontend.cpp b/src/main_frontend.cpp new file mode 100644 index 00000000..cf5b87f4 --- /dev/null +++ b/src/main_frontend.cpp @@ -0,0 +1,803 @@ +/* + * 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" + +#if __linux__ +#include +#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", +}; + +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 FE_StepBegin(void* userdata) +{ + mcu_t& mcu = *(mcu_t*)userdata; + if (mcu.pcm->config_reg_3c & 0x40) + sample_write_ptr &= ~3; + else + sample_write_ptr &= ~1; +} + +bool FE_Wait(void* userdata) +{ + return sample_read_ptr == sample_write_ptr; +} + +void FE_ReceiveSample(void* userdata, 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; +} + +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 FE_CloseAudio(void) +{ + SDL_CloseAudio(); + if (sample_buffer) free(sample_buffer); +} + + +static const size_t rf_num = 5; +static FILE *s_rf[rf_num] = +{ + nullptr, + nullptr, + nullptr, + nullptr, + nullptr +}; + +static void closeAllR() +{ + for(size_t i = 0; i < rf_num; ++i) + { + if(s_rf[i]) + fclose(s_rf[i]); + s_rf[i] = nullptr; + } +} + +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]); + } + } + +} + +static bool work_thread_run = false; + +int SDLCALL FE_RunMCU(void* data) +{ + mcu_t& mcu = *(mcu_t*)data; + + MCU_WorkThread_Lock(mcu); + while (work_thread_run) + { + MCU_Step(mcu); + } + MCU_WorkThread_Unlock(mcu); + + return 0; +} + +void FE_Run(mcu_t& mcu) +{ + bool working = true; + + work_thread_run = true; + SDL_Thread *thread = SDL_CreateThread(FE_RunMCU, "work thread", &mcu); + + while (working) + { + if (LCD_QuitRequested(*mcu.lcd)) + working = false; + + LCD_Update(*mcu.lcd); + + SDL_Event sdl_event; + while (SDL_PollEvent(&sdl_event)) + { + LCD_HandleEvent(*mcu.lcd, sdl_event); + } + + SDL_Delay(15); + } + + work_thread_run = false; + SDL_WaitThread(thread, 0); +} + +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 romset = ROM_SET_MK2; + + mcu_t mcu; + submcu_t sm; + mcu_timer_t timer; + // allocate pcm because the bitmaps will overflow the stack + lcd_t* lcd = (lcd_t*)malloc(sizeof(lcd_t)); + // allocate pcm because the waveroms will overflow the stack + pcm_t* pcm = (pcm_t*)malloc(sizeof(pcm_t)); + PCM_Reset(*pcm, mcu); + MCU_Init(mcu, sm, *pcm, timer, *lcd); + mcu.callback_userdata = &mcu; + mcu.step_begin_callback = FE_StepBegin; + mcu.sample_callback = FE_ReceiveSample; + mcu.wait_callback = FE_Wait; + TIMER_Init(timer, mcu); + + { + 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.romset = romset; + mcu.mcu_mk1 = false; + mcu.mcu_cm300 = false; + mcu.mcu_st = false; + mcu.mcu_jv880 = false; + mcu.mcu_scb55 = false; + mcu.mcu_sc155 = false; + switch (romset) + { + case ROM_SET_MK2: + case ROM_SET_SC155MK2: + if (romset == ROM_SET_SC155MK2) + mcu.mcu_sc155 = true; + break; + case ROM_SET_ST: + mcu.mcu_st = true; + break; + case ROM_SET_MK1: + case ROM_SET_SC155: + mcu.mcu_mk1 = true; + mcu.mcu_st = false; + if (romset == ROM_SET_SC155) + mcu.mcu_sc155 = true; + break; + case ROM_SET_CM300: + mcu.mcu_mk1 = true; + mcu.mcu_cm300 = true; + break; + case ROM_SET_JV880: + mcu.mcu_jv880 = true; + mcu.rom2_mask /= 2; // rom is half the size + break; + case ROM_SET_SCB55: + case ROM_SET_RLP3237: + 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 = 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); + closeAllR(); + return 1; + } + + LCD_SetBackPath(*lcd, basePath + "/back.data"); + + if (fread(mcu.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(mcu.rom2, 1, ROM2_SIZE, s_rf[1]); + + if (rom2_read == ROM2_SIZE || rom2_read == ROM2_SIZE / 2) + { + mcu.rom2_mask = rom2_read - 1; + } + else + { + fprintf(stderr, "FATAL ERROR: Failed to read the mcu ROM2.\n"); + fflush(stderr); + closeAllR(); + return 1; + } + + if (mcu.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, pcm->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, pcm->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, pcm->waverom3, 0x100000); + } + else if (mcu.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, pcm->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, pcm->waverom2, 0x200000); + + if (s_rf[4] && fread(tempbuf, 1, 0x800000, s_rf[4])) + unscramble(tempbuf, 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); + closeAllR(); + return 1; + } + + unscramble(tempbuf, 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); + closeAllR(); + return 1; + } + + unscramble(tempbuf, mcu.mcu_scb55 ? pcm->waverom3 : pcm->waverom2, 0x100000); + } + + if (s_rf[4] && fread(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); + 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 (!FE_OpenAudio(mcu, audioDeviceIndex, pageSize, pageNum)) + { + fprintf(stderr, "FATAL ERROR: Failed to open the audio stream.\n"); + fflush(stderr); + return 2; + } + + if(!MIDI_Init(mcu, port)) + { + fprintf(stderr, "ERROR: Failed to initialize the MIDI Input.\nWARNING: Continuing without MIDI Input...\n"); + fflush(stderr); + } + + LCD_Init(*lcd, mcu); + MCU_PatchROM(mcu); + MCU_Reset(mcu); + SM_Reset(sm, mcu); + + if (resetType != ResetType::NONE) MIDI_Reset(mcu, resetType); + + FE_Run(mcu); + + FE_CloseAudio(); + MIDI_Quit(); + LCD_UnInit(*lcd); + SDL_Quit(); + + free(pcm); + + return 0; +} diff --git a/src/mcu.cpp b/src/mcu.cpp index 5e9d8763..bb46f36c 100644 --- a/src/mcu.cpp +++ b/src/mcu.cpp @@ -51,84 +51,6 @@ #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", -}; - -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(mcu_t& mcu) { printf("%.2x %.4x\n", mcu.cp, mcu.pc); @@ -853,6 +775,12 @@ void MCU_Init(mcu_t& mcu, submcu_t& sm, pcm_t& pcm, mcu_timer_t& timer, lcd_t& l mcu.lcd = &lcd; mcu.romset = ROM_SET_MK2; mcu.rom2_mask = ROM2_SIZE - 1; + mcu.work_thread_lock = SDL_CreateMutex(); +} + +void MCU_Deinit(mcu_t& mcu) +{ + SDL_DestroyMutex(mcu.work_thread_lock); } void MCU_Reset(mcu_t& mcu) @@ -933,114 +861,69 @@ void MCU_UpdateUART_TX(mcu_t& mcu) // 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) { - mcu_t& mcu = *(mcu_t*)data; - work_thread_lock = SDL_CreateMutex(); + mcu.step_begin_callback(mcu.callback_userdata); - MCU_WorkThread_Lock(); - while (work_thread_run) + if (mcu.wait_callback(mcu.callback_userdata)) { - if (mcu.pcm->config_reg_3c & 0x40) - sample_write_ptr &= ~3; - else - sample_write_ptr &= ~1; - if (sample_read_ptr == sample_write_ptr) + MCU_WorkThread_Unlock(mcu); + while (mcu.wait_callback(mcu.callback_userdata)) { - MCU_WorkThread_Unlock(); - while (sample_read_ptr == sample_write_ptr) - { - SDL_Delay(1); - } - MCU_WorkThread_Lock(); + SDL_Delay(1); } + MCU_WorkThread_Lock(mcu); + } - if (!mcu.ex_ignore) - MCU_Interrupt_Handle(mcu); - else - mcu.ex_ignore = 0; - - if (!mcu.sleep) - MCU_ReadInstruction(mcu); - - mcu.cycles += 12; // FIXME: assume 12 cycles per instruction + if (!mcu.ex_ignore) + MCU_Interrupt_Handle(mcu); + else + mcu.ex_ignore = 0; - // if (mcu.cycles % 24000000 == 0) - // printf("seconds: %i\n", (int)(mcu.cycles / 24000000)); + if (!mcu.sleep) + MCU_ReadInstruction(mcu); - PCM_Update(*mcu.pcm, mcu.cycles); + mcu.cycles += 12; // FIXME: assume 12 cycles per instruction - TIMER_Clock(*mcu.timer, mcu.cycles); + // if (mcu.cycles % 24000000 == 0) + // printf("seconds: %i\n", (int)(mcu.cycles / 24000000)); - 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); - } + PCM_Update(*mcu.pcm, mcu.cycles); - MCU_UpdateAnalog(mcu, mcu.cycles); + TIMER_Clock(*mcu.timer, mcu.cycles); - if (mcu.mcu_mk1) - { - if (mcu.ga_lcd_counter) - { - mcu.ga_lcd_counter--; - if (mcu.ga_lcd_counter == 0) - { - MCU_GA_SetGAInt(mcu, 1, 0); - MCU_GA_SetGAInt(mcu, 1, 1); - } - } - } + 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_WorkThread_Unlock(); - - SDL_DestroyMutex(work_thread_lock); - - return 0; -} - -static void MCU_Run(mcu_t& mcu) -{ - bool working = true; - work_thread_run = true; - SDL_Thread *thread = SDL_CreateThread(work_thread, "work thread", &mcu); + MCU_UpdateAnalog(mcu, mcu.cycles); - while (working) + if (mcu.mcu_mk1) { - if(LCD_QuitRequested(*mcu.lcd)) - working = false; - - LCD_Update(*mcu.lcd); - - SDL_Event sdl_event; - while (SDL_PollEvent(&sdl_event)) + if (mcu.ga_lcd_counter) { - LCD_HandleEvent(*mcu.lcd, sdl_event); + mcu.ga_lcd_counter--; + if (mcu.ga_lcd_counter == 0) + { + MCU_GA_SetGAInt(mcu, 1, 0); + MCU_GA_SetGAInt(mcu, 1, 1); + } } - - SDL_Delay(15); } - - work_thread_run = false; - SDL_WaitThread(thread, 0); } void MCU_PatchROM(mcu_t& mcu) @@ -1082,157 +965,9 @@ void MCU_WriteP1(mcu_t& mcu, uint8_t data) mcu.mcu_p1_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) -{ - SDL_CloseAudio(); - if (sample_buffer) free(sample_buffer); -} - -void MCU_PostSample(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(mcu_t& mcu, int line, int value) @@ -1255,461 +990,3 @@ void MCU_EncoderTrigger(mcu_t& mcu, int dir) MCU_GA_SetGAInt(mcu, dir == 0 ? 3 : 4, 1); } - -static const size_t rf_num = 5; -static FILE *s_rf[rf_num] = -{ - nullptr, - nullptr, - nullptr, - nullptr, - nullptr -}; - -static void closeAllR() -{ - for(size_t i = 0; i < rf_num; ++i) - { - if(s_rf[i]) - fclose(s_rf[i]); - s_rf[i] = nullptr; - } -} - -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 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 romset = ROM_SET_MK2; - - mcu_t mcu; - submcu_t sm; - mcu_timer_t timer; - // allocate pcm because the bitmaps will overflow the stack - lcd_t* lcd = (lcd_t*)malloc(sizeof(lcd_t)); - // allocate pcm because the waveroms will overflow the stack - pcm_t* pcm = (pcm_t*)malloc(sizeof(pcm_t)); - PCM_Reset(*pcm, mcu); - MCU_Init(mcu, sm, *pcm, timer, *lcd); - TIMER_Init(timer, mcu); - - { - 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.romset = romset; - mcu.mcu_mk1 = false; - mcu.mcu_cm300 = false; - mcu.mcu_st = false; - mcu.mcu_jv880 = false; - mcu.mcu_scb55 = false; - mcu.mcu_sc155 = false; - switch (romset) - { - case ROM_SET_MK2: - case ROM_SET_SC155MK2: - if (romset == ROM_SET_SC155MK2) - mcu.mcu_sc155 = true; - break; - case ROM_SET_ST: - mcu.mcu_st = true; - break; - case ROM_SET_MK1: - case ROM_SET_SC155: - mcu.mcu_mk1 = true; - mcu.mcu_st = false; - if (romset == ROM_SET_SC155) - mcu.mcu_sc155 = true; - break; - case ROM_SET_CM300: - mcu.mcu_mk1 = true; - mcu.mcu_cm300 = true; - break; - case ROM_SET_JV880: - mcu.mcu_jv880 = true; - mcu.rom2_mask /= 2; // rom is half the size - break; - case ROM_SET_SCB55: - case ROM_SET_RLP3237: - 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 = 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); - closeAllR(); - return 1; - } - - LCD_SetBackPath(*lcd, basePath + "/back.data"); - - if (fread(mcu.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(mcu.rom2, 1, ROM2_SIZE, s_rf[1]); - - if (rom2_read == ROM2_SIZE || rom2_read == ROM2_SIZE / 2) - { - mcu.rom2_mask = rom2_read - 1; - } - else - { - fprintf(stderr, "FATAL ERROR: Failed to read the mcu ROM2.\n"); - fflush(stderr); - closeAllR(); - return 1; - } - - if (mcu.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, pcm->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, pcm->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, pcm->waverom3, 0x100000); - } - else if (mcu.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, pcm->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, pcm->waverom2, 0x200000); - - if (s_rf[4] && fread(tempbuf, 1, 0x800000, s_rf[4])) - unscramble(tempbuf, 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); - closeAllR(); - return 1; - } - - unscramble(tempbuf, 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); - closeAllR(); - return 1; - } - - unscramble(tempbuf, mcu.mcu_scb55 ? pcm->waverom3 : pcm->waverom2, 0x100000); - } - - if (s_rf[4] && fread(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); - 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(mcu, audioDeviceIndex, pageSize, pageNum)) - { - fprintf(stderr, "FATAL ERROR: Failed to open the audio stream.\n"); - fflush(stderr); - return 2; - } - - if(!MIDI_Init(mcu, port)) - { - fprintf(stderr, "ERROR: Failed to initialize the MIDI Input.\nWARNING: Continuing without MIDI Input...\n"); - fflush(stderr); - } - - LCD_Init(*lcd, mcu); - MCU_PatchROM(mcu); - MCU_Reset(mcu); - SM_Reset(sm, mcu); - - if (resetType != ResetType::NONE) MIDI_Reset(mcu, resetType); - - MCU_Run(mcu); - - MCU_CloseAudio(); - MIDI_Quit(); - LCD_UnInit(*lcd); - SDL_Quit(); - - free(pcm); - - return 0; -} diff --git a/src/mcu.h b/src/mcu.h index c4baf98a..afeccba0 100644 --- a/src/mcu.h +++ b/src/mcu.h @@ -36,6 +36,7 @@ #include #include "mcu_interrupt.h" #include "SDL_atomic.h" +#include "SDL.h" struct submcu_t; struct pcm_t; @@ -187,6 +188,10 @@ static const int ROMSM_SIZE = 0x1000; static const uint32_t uart_buffer_size = 8192; +typedef void(*mcu_step_begin_callback)(void* userdata); +typedef void(*mcu_sample_callback)(void* userdata, int* sample); +typedef bool(*mcu_wait_callback)(void* userdata); + struct mcu_t { uint16_t r[8]; uint16_t pc; @@ -261,8 +266,21 @@ struct mcu_t { uint8_t operand_status; uint16_t operand_data; uint8_t opcode_extended; + + void* callback_userdata; + mcu_step_begin_callback step_begin_callback; + // if FE doesn't need more samples, returns true to signal for the mcu to wait + mcu_wait_callback wait_callback; + mcu_sample_callback sample_callback; + + SDL_mutex *work_thread_lock; }; +void 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(mcu_t& mcu); uint8_t MCU_Read(mcu_t& mcu, uint32_t address); @@ -525,8 +543,8 @@ void MCU_GA_SetGAInt(mcu_t& mcu, int line, int value); void MCU_EncoderTrigger(mcu_t& mcu, int dir); -void MCU_PostSample(int *sample); +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/pcm.cpp b/src/pcm.cpp index 1fbdb9b9..548dfdfe 100644 --- a/src/pcm.cpp +++ b/src/pcm.cpp @@ -606,7 +606,7 @@ void PCM_Update(pcm_t& pcm, 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); @@ -631,7 +631,7 @@ void PCM_Update(pcm_t& pcm, 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); } } From e5314a914d258e1d1394290fa992ef8f03b23a0a Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Sun, 28 Apr 2024 05:12:38 -0400 Subject: [PATCH 19/35] Introduce emu abstraction emu is a collection of all the emulator subsystems that simplifies initialization and allows multiple emulators to be easily instantiated --- CMakeLists.txt | 1 + src/emu.cpp | 40 ++++++++++++ src/emu.h | 22 +++++++ src/lcd.cpp | 20 +++--- src/lcd.h | 2 +- src/main_frontend.cpp | 143 ++++++++++++++++++++++-------------------- 6 files changed, 148 insertions(+), 80 deletions(-) create mode 100644 src/emu.cpp create mode 100644 src/emu.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 82bf3ad9..6c762c4f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -196,6 +196,7 @@ set(SC55_BACKEND_SRC src/midi.h src/pcm.cpp src/pcm.h src/submcu.cpp src/submcu.h + src/emu.cpp src/emu.h src/utils/files.cpp src/utils/files.h ) diff --git a/src/emu.cpp b/src/emu.cpp new file mode 100644 index 00000000..8837d616 --- /dev/null +++ b/src/emu.cpp @@ -0,0 +1,40 @@ +#include "emu.h" +#include "mcu.h" +#include "submcu.h" +#include "mcu_timer.h" +#include "lcd.h" +#include "pcm.h" + +void EMU_Init(emu_backend_t& emu) +{ + emu.mcu = (mcu_t*)malloc(sizeof(mcu_t)); + emu.sm = (submcu_t*)malloc(sizeof(submcu_t)); + emu.timer = (mcu_timer_t*)malloc(sizeof(mcu_timer_t)); + emu.lcd = (lcd_t*)malloc(sizeof(lcd_t)); + emu.pcm = (pcm_t*)malloc(sizeof(pcm_t)); + + PCM_Reset(*emu.pcm, *emu.mcu); + MCU_Init(*emu.mcu, *emu.sm, *emu.pcm, *emu.timer, *emu.lcd); + TIMER_Init(*emu.timer, *emu.mcu); + + // TODO: LCD should be optional for use with other frontends + LCD_Init(*emu.lcd, *emu.mcu); +} + +void EMU_Free(emu_backend_t& emu) +{ + LCD_UnInit(*emu.lcd); + free(emu.pcm); + free(emu.lcd); + free(emu.timer); + free(emu.sm); + free(emu.mcu); +} + +// Should be called after loading roms +void EMU_Reset(emu_backend_t& emu) +{ + MCU_PatchROM(*emu.mcu); + MCU_Reset(*emu.mcu); + SM_Reset(*emu.sm, *emu.mcu); +} diff --git a/src/emu.h b/src/emu.h new file mode 100644 index 00000000..e6fdc500 --- /dev/null +++ b/src/emu.h @@ -0,0 +1,22 @@ +#pragma once + +struct mcu_t; +struct submcu_t; +struct mcu_timer_t; +struct lcd_t; +struct pcm_t; + +struct emu_backend_t { + mcu_t* mcu; + submcu_t* sm; + mcu_timer_t* timer; + lcd_t* lcd; + pcm_t* pcm; +}; + +void EMU_Init(emu_backend_t& emu); +void EMU_Free(emu_backend_t& emu); + +// Should be called after loading roms +void EMU_Reset(emu_backend_t& emu); + diff --git a/src/lcd.cpp b/src/lcd.cpp index 8978278a..4e28d769 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -195,15 +195,22 @@ const int button_map_jv880[][2] = }; -void LCD_SetBackPath(lcd_t& lcd, const std::string &path) +void LCD_LoadBack(lcd_t& lcd, const std::string& path) { lcd.m_back_path = path; + + FILE *raw; + + raw = Files::utf8_fopen(lcd.m_back_path.c_str(), "rb"); + if (!raw) + return; + + fread(lcd.lcd_background, 1, sizeof(lcd.lcd_background), raw); + fclose(raw); } void LCD_Init(lcd_t& lcd, mcu_t& mcu) { - FILE *raw; - if (lcd.lcd_init) return; @@ -239,13 +246,6 @@ void LCD_Init(lcd_t& lcd, mcu_t& mcu) if (!lcd.texture) return; - raw = Files::utf8_fopen(lcd.m_back_path.c_str(), "rb"); - if (!raw) - return; - - fread(lcd.lcd_background, 1, sizeof(lcd.lcd_background), raw); - fclose(raw); - lcd.lcd_init = 1; } diff --git a/src/lcd.h b/src/lcd.h index c9531bbd..c15abcf1 100644 --- a/src/lcd.h +++ b/src/lcd.h @@ -70,7 +70,7 @@ struct lcd_t { }; -void LCD_SetBackPath(lcd_t& lcd, const std::string &path); +void LCD_LoadBack(lcd_t& lcd, const std::string& path); void LCD_Init(lcd_t& lcd, mcu_t& mcu); void LCD_UnInit(lcd_t& lcd); void LCD_Write(lcd_t& lcd, uint32_t address, uint8_t data); diff --git a/src/main_frontend.cpp b/src/main_frontend.cpp index cf5b87f4..9f307ea9 100644 --- a/src/main_frontend.cpp +++ b/src/main_frontend.cpp @@ -45,6 +45,7 @@ #include "midi.h" #include "utf8main.h" #include "utils/files.h" +#include "emu.h" #if __linux__ #include @@ -388,6 +389,25 @@ void FE_Run(mcu_t& mcu) SDL_WaitThread(thread, 0); } +int 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 2; + } + + return 0; +} + +void FE_Quit() +{ + FE_CloseAudio(); + MIDI_Quit(); + SDL_Quit(); +} + int main(int argc, char *argv[]) { (void)argc; @@ -402,21 +422,6 @@ int main(int argc, char *argv[]) int romset = ROM_SET_MK2; - mcu_t mcu; - submcu_t sm; - mcu_timer_t timer; - // allocate pcm because the bitmaps will overflow the stack - lcd_t* lcd = (lcd_t*)malloc(sizeof(lcd_t)); - // allocate pcm because the waveroms will overflow the stack - pcm_t* pcm = (pcm_t*)malloc(sizeof(pcm_t)); - PCM_Reset(*pcm, mcu); - MCU_Init(mcu, sm, *pcm, timer, *lcd); - mcu.callback_userdata = &mcu; - mcu.step_begin_callback = FE_StepBegin; - mcu.sample_callback = FE_ReceiveSample; - mcu.wait_callback = FE_Wait; - TIMER_Init(timer, mcu); - { for (int i = 1; i < argc; i++) { @@ -572,41 +577,56 @@ int main(int argc, char *argv[]) printf("ROM set autodetect: %s\n", rs_name[romset]); } - mcu.romset = romset; - mcu.mcu_mk1 = false; - mcu.mcu_cm300 = false; - mcu.mcu_st = false; - mcu.mcu_jv880 = false; - mcu.mcu_scb55 = false; - mcu.mcu_sc155 = false; + if (FE_Init() != 0) + { + return 2; + } + + emu_backend_t emu; + EMU_Init(emu); + // TODO: Clean up, shouldn't need to reach into emu for this + emu.mcu->callback_userdata = emu.mcu; + emu.mcu->step_begin_callback = FE_StepBegin; + emu.mcu->sample_callback = FE_ReceiveSample; + emu.mcu->wait_callback = FE_Wait; + + LCD_LoadBack(*emu.lcd, basePath + "/back.data"); + + emu.mcu->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) - mcu.mcu_sc155 = true; + emu.mcu->mcu_sc155 = true; break; case ROM_SET_ST: - mcu.mcu_st = true; + emu.mcu->mcu_st = true; break; case ROM_SET_MK1: case ROM_SET_SC155: - mcu.mcu_mk1 = true; - mcu.mcu_st = false; + emu.mcu->mcu_mk1 = true; + emu.mcu->mcu_st = false; if (romset == ROM_SET_SC155) - mcu.mcu_sc155 = true; + emu.mcu->mcu_sc155 = true; break; case ROM_SET_CM300: - mcu.mcu_mk1 = true; - mcu.mcu_cm300 = true; + emu.mcu->mcu_mk1 = true; + emu.mcu->mcu_cm300 = true; break; case ROM_SET_JV880: - mcu.mcu_jv880 = true; - mcu.rom2_mask /= 2; // rom is half the size + emu.mcu->mcu_jv880 = true; + emu.mcu->rom2_mask /= 2; // rom is half the size break; case ROM_SET_SCB55: case ROM_SET_RLP3237: - mcu.mcu_scb55 = true; + emu.mcu->mcu_scb55 = true; break; } @@ -624,7 +644,7 @@ int main(int argc, char *argv[]) } rpaths[i] = basePath + "/" + roms[romset][i]; s_rf[i] = Files::utf8_fopen(rpaths[i].c_str(), "rb"); - bool optional = mcu.mcu_jv880 && i == 4; + bool optional = emu.mcu->mcu_jv880 && i == 4; r_ok &= optional || (s_rf[i] != nullptr); if(!s_rf[i]) { @@ -643,9 +663,7 @@ int main(int argc, char *argv[]) return 1; } - LCD_SetBackPath(*lcd, basePath + "/back.data"); - - if (fread(mcu.rom1, 1, ROM1_SIZE, s_rf[0]) != ROM1_SIZE) + 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); @@ -653,11 +671,11 @@ int main(int argc, char *argv[]) return 1; } - size_t rom2_read = fread(mcu.rom2, 1, ROM2_SIZE, s_rf[1]); + size_t rom2_read = fread(emu.mcu->rom2, 1, ROM2_SIZE, s_rf[1]); if (rom2_read == ROM2_SIZE || rom2_read == ROM2_SIZE / 2) { - mcu.rom2_mask = rom2_read - 1; + emu.mcu->rom2_mask = rom2_read - 1; } else { @@ -667,7 +685,7 @@ int main(int argc, char *argv[]) return 1; } - if (mcu.mcu_mk1) + if (emu.mcu->mcu_mk1) { if (fread(tempbuf, 1, 0x100000, s_rf[2]) != 0x100000) { @@ -677,7 +695,7 @@ int main(int argc, char *argv[]) return 1; } - unscramble(tempbuf, pcm->waverom1, 0x100000); + unscramble(tempbuf, emu.pcm->waverom1, 0x100000); if (fread(tempbuf, 1, 0x100000, s_rf[3]) != 0x100000) { @@ -687,7 +705,7 @@ int main(int argc, char *argv[]) return 1; } - unscramble(tempbuf, pcm->waverom2, 0x100000); + unscramble(tempbuf, emu.pcm->waverom2, 0x100000); if (fread(tempbuf, 1, 0x100000, s_rf[4]) != 0x100000) { @@ -697,9 +715,9 @@ int main(int argc, char *argv[]) return 1; } - unscramble(tempbuf, pcm->waverom3, 0x100000); + unscramble(tempbuf, emu.pcm->waverom3, 0x100000); } - else if (mcu.mcu_jv880) + else if (emu.mcu->mcu_jv880) { if (fread(tempbuf, 1, 0x200000, s_rf[2]) != 0x200000) { @@ -709,7 +727,7 @@ int main(int argc, char *argv[]) return 1; } - unscramble(tempbuf, pcm->waverom1, 0x200000); + unscramble(tempbuf, emu.pcm->waverom1, 0x200000); if (fread(tempbuf, 1, 0x200000, s_rf[3]) != 0x200000) { @@ -719,10 +737,10 @@ int main(int argc, char *argv[]) return 1; } - unscramble(tempbuf, pcm->waverom2, 0x200000); + unscramble(tempbuf, emu.pcm->waverom2, 0x200000); if (s_rf[4] && fread(tempbuf, 1, 0x800000, s_rf[4])) - unscramble(tempbuf, pcm->waverom_exp, 0x800000); + unscramble(tempbuf, emu.pcm->waverom_exp, 0x800000); else printf("WaveRom EXP not found, skipping it.\n"); } @@ -736,7 +754,7 @@ int main(int argc, char *argv[]) return 1; } - unscramble(tempbuf, pcm->waverom1, 0x200000); + unscramble(tempbuf, emu.pcm->waverom1, 0x200000); if (s_rf[3]) { @@ -748,10 +766,10 @@ int main(int argc, char *argv[]) return 1; } - unscramble(tempbuf, mcu.mcu_scb55 ? pcm->waverom3 : pcm->waverom2, 0x100000); + unscramble(tempbuf, emu.mcu->mcu_scb55 ? emu.pcm->waverom3 : emu.pcm->waverom2, 0x100000); } - if (s_rf[4] && fread(sm.sm_rom, 1, ROMSM_SIZE, s_rf[4]) != ROMSM_SIZE) + 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); @@ -763,41 +781,28 @@ int main(int argc, char *argv[]) // 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; - } + EMU_Reset(emu); - if (!FE_OpenAudio(mcu, audioDeviceIndex, pageSize, pageNum)) + if (!FE_OpenAudio(*emu.mcu, audioDeviceIndex, pageSize, pageNum)) { fprintf(stderr, "FATAL ERROR: Failed to open the audio stream.\n"); fflush(stderr); return 2; } - if(!MIDI_Init(mcu, port)) + if(!MIDI_Init(*emu.mcu, port)) { fprintf(stderr, "ERROR: Failed to initialize the MIDI Input.\nWARNING: Continuing without MIDI Input...\n"); fflush(stderr); } - LCD_Init(*lcd, mcu); - MCU_PatchROM(mcu); - MCU_Reset(mcu); - SM_Reset(sm, mcu); - - if (resetType != ResetType::NONE) MIDI_Reset(mcu, resetType); + if (resetType != ResetType::NONE) MIDI_Reset(*emu.mcu, resetType); - FE_Run(mcu); + FE_Run(*emu.mcu); - FE_CloseAudio(); - MIDI_Quit(); - LCD_UnInit(*lcd); - SDL_Quit(); + EMU_Free(emu); - free(pcm); + FE_Quit(); return 0; } From c65d338e316d7b13bb351e9d81d10dac55e11612 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Mon, 29 Apr 2024 02:45:43 -0400 Subject: [PATCH 20/35] Turn global sample buffer into proper ringbuffer --- CMakeLists.txt | 1 + src/main_frontend.cpp | 39 ++++++------------- src/ringbuffer.h | 87 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 27 deletions(-) create mode 100644 src/ringbuffer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c762c4f..d3ab7603 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,6 +197,7 @@ set(SC55_BACKEND_SRC src/pcm.cpp src/pcm.h src/submcu.cpp src/submcu.h src/emu.cpp src/emu.h + src/ringbuffer.h src/utils/files.cpp src/utils/files.h ) diff --git a/src/main_frontend.cpp b/src/main_frontend.cpp index 9f307ea9..5dcd6c17 100644 --- a/src/main_frontend.cpp +++ b/src/main_frontend.cpp @@ -46,6 +46,7 @@ #include "utf8main.h" #include "utils/files.h" #include "emu.h" +#include "ringbuffer.h" #if __linux__ #include @@ -123,25 +124,20 @@ const char* roms[ROM_SET_COUNT][5] = 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; +ringbuffer_t buf; + void FE_StepBegin(void* userdata) { mcu_t& mcu = *(mcu_t*)userdata; - if (mcu.pcm->config_reg_3c & 0x40) - sample_write_ptr &= ~3; - else - sample_write_ptr &= ~1; + buf.oversampling = mcu.pcm->config_reg_3c & 0x40; } bool FE_Wait(void* userdata) { - return sample_read_ptr == sample_write_ptr; + return RB_IsFull(buf); } void FE_ReceiveSample(void* userdata, int *sample) @@ -156,9 +152,7 @@ void FE_ReceiveSample(void* userdata, int *sample) 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; + RB_Write(buf, sample[0], sample[1]); } uint8_t tempbuf[0x800000]; @@ -192,11 +186,9 @@ void unscramble(uint8_t *src, uint8_t *dst, int len) void audio_callback(void* /*userdata*/, Uint8* stream, int len) { - len /= 2; - memcpy(stream, &sample_buffer[sample_read_ptr], len * 2); - memset(&sample_buffer[sample_read_ptr], 0, len * 2); - sample_read_ptr += len; - sample_read_ptr %= audio_buffer_size; + const size_t num_samples = len / sizeof(int16_t); + memset(stream, 0, len); + RB_Read(buf, (int16_t*)stream, num_samples); } static const char* audio_format_to_str(int format) @@ -240,15 +232,8 @@ int FE_OpenAudio(mcu_t& mcu, int deviceIndex, int pageSize, int pageNum) spec.channels = 2; spec.callback = audio_callback; spec.samples = audio_page_size / 4; - - sample_buffer = (short*)calloc(audio_buffer_size, sizeof(short)); - if (!sample_buffer) - { - printf("Cannot allocate audio buffer.\n"); - return 0; - } - sample_read_ptr = 0; - sample_write_ptr = 0; + + RB_Init(buf, audio_buffer_size / 2); int num = SDL_GetNumAudioDevices(0); if (num == 0) @@ -294,7 +279,7 @@ int FE_OpenAudio(mcu_t& mcu, int deviceIndex, int pageSize, int pageNum) void FE_CloseAudio(void) { SDL_CloseAudio(); - if (sample_buffer) free(sample_buffer); + RB_Free(buf); } diff --git a/src/ringbuffer.h b/src/ringbuffer.h new file mode 100644 index 00000000..3f4ce138 --- /dev/null +++ b/src/ringbuffer.h @@ -0,0 +1,87 @@ +#pragma once + +#include +#include +#include + +const int RB_CHANNEL_COUNT = 2; + +struct ringbuffer_t { + int16_t* samples; + size_t frame_count; + size_t sample_count; + size_t read_head; + size_t write_head; + bool oversampling; +}; + +inline void RB_Init(ringbuffer_t& rb, size_t frame_count) +{ + rb.samples = (int16_t*)malloc(sizeof(int16_t) * RB_CHANNEL_COUNT * frame_count); + memset(rb.samples, 0, sizeof(int16_t) * RB_CHANNEL_COUNT * frame_count); + rb.frame_count = frame_count; + rb.sample_count = RB_CHANNEL_COUNT * frame_count; + rb.read_head = 0; + rb.write_head = 0; + rb.oversampling = false; +} + +inline void RB_Free(ringbuffer_t& rb) +{ + free(rb.samples); +} + +inline bool RB_IsFull(ringbuffer_t& rb) +{ + if (rb.oversampling) + { + return ((rb.write_head + 2 * RB_CHANNEL_COUNT) % rb.sample_count) == rb.read_head; + } + else + { + return ((rb.write_head + 1 * RB_CHANNEL_COUNT) % rb.sample_count) == rb.read_head; + } +} + +inline void RB_Write(ringbuffer_t& rb, int16_t left, int16_t right) +{ + if (RB_IsFull(rb)) + { + fprintf(stderr, "Ringbuffer overflow\n"); + exit(1); + } + rb.samples[rb.write_head + 0] = left; + rb.samples[rb.write_head + 1] = right; + rb.write_head = (rb.write_head + RB_CHANNEL_COUNT) % rb.sample_count; +} + +inline size_t RB_ReadableSampleCount(ringbuffer_t& rb) +{ + if (rb.read_head <= rb.write_head) + { + return rb.write_head - rb.read_head; + } + else + { + return rb.sample_count - (rb.read_head - rb.write_head); + } +} + +// Reads up to `sample_count` samples and returns the number of samples +// actually read +inline size_t RB_Read(ringbuffer_t& rb, int16_t* dest, size_t sample_count) +{ + size_t have_count = RB_ReadableSampleCount(rb); + size_t read_count = sample_count < have_count ? sample_count : have_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.samples[read_head]; + ++dest; + read_head = (read_head + 1) % rb.sample_count; + } + rb.read_head = read_head; + return read_count; +} + From 2ba5205e99fe2be06ca6750a562cf8ce856d62e9 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Mon, 29 Apr 2024 06:05:32 -0400 Subject: [PATCH 21/35] Support for multiple instances Pass `-instances:` to run `n` backend emulators. Up to 16 emulators are supported in a single process. Events are routed to the emulator modulo the number of instances, so if `n=2` even MIDI channels will go to the first emulator and odd MIDI channels to the second. - Rom loading code has been moved into emu module - LCDs now only handle events for their own window - MIDI module now forwards events to the frontend which in turn routes it to the correct backend emulator --- CMakeLists.txt | 1 + src/emu.cpp | 327 ++++++++++++++++++++++++++++ src/emu.h | 4 + src/lcd.cpp | 25 +++ src/main_frontend.cpp | 484 ++++++++++++------------------------------ src/math_util.h | 23 ++ src/midi.h | 4 +- src/midi_rtmidi.cpp | 15 +- src/midi_win32.cpp | 37 +++- src/ringbuffer.h | 38 +++- 10 files changed, 587 insertions(+), 371 deletions(-) create mode 100644 src/math_util.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d3ab7603..d8f8268f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -198,6 +198,7 @@ set(SC55_BACKEND_SRC 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 ) diff --git a/src/emu.cpp b/src/emu.cpp index 8837d616..efc28b64 100644 --- a/src/emu.cpp +++ b/src/emu.cpp @@ -4,6 +4,7 @@ #include "mcu_timer.h" #include "lcd.h" #include "pcm.h" +#include "utils/files.h" void EMU_Init(emu_backend_t& emu) { @@ -38,3 +39,329 @@ void EMU_Reset(emu_backend_t& emu) MCU_Reset(*emu.mcu); SM_Reset(*emu.sm, *emu.mcu); } + +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", +}; + +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<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); + closeAllR(); + return 1; + } + + 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); + closeAllR(); + return 1; + } + + 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); + closeAllR(); + return 1; + } + + 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); + closeAllR(); + return 1; + } + + 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); + closeAllR(); + return 1; + } + + 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); + closeAllR(); + return 1; + } + + 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); + closeAllR(); + return 1; + } + + 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); + closeAllR(); + return 1; + } + + 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); + closeAllR(); + return 1; + } + + 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); + closeAllR(); + return 1; + } + + 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); + closeAllR(); + return 1; + } + } + + // Close all files as they no longer needed being open + closeAllR(); + + return 0; +} diff --git a/src/emu.h b/src/emu.h index e6fdc500..9d9650a5 100644 --- a/src/emu.h +++ b/src/emu.h @@ -1,5 +1,7 @@ #pragma once +#include + struct mcu_t; struct submcu_t; struct mcu_timer_t; @@ -20,3 +22,5 @@ void EMU_Free(emu_backend_t& emu); // Should be called after loading roms void EMU_Reset(emu_backend_t& emu); +int EMU_DetectRoms(const std::string& basePath); +int EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath); diff --git a/src/lcd.cpp b/src/lcd.cpp index 4e28d769..dd51d9eb 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -211,6 +211,7 @@ void LCD_LoadBack(lcd_t& lcd, const std::string& path) void LCD_Init(lcd_t& lcd, mcu_t& mcu) { + lcd.lcd_init = 0; if (lcd.lcd_init) return; @@ -509,6 +510,23 @@ void LCD_Update(lcd_t& lcd) void LCD_HandleEvent(lcd_t& lcd, const SDL_Event& sdl_event) { + switch (sdl_event.type) + { + case SDL_KEYDOWN: + case SDL_KEYUP: + if (sdl_event.key.windowID != SDL_GetWindowID(lcd.window)) + { + return; + } + case SDL_WINDOWEVENT: + if (sdl_event.window.windowID != SDL_GetWindowID(lcd.window)) + { + return; + } + default: + break; + } + if (sdl_event.type == SDL_KEYDOWN) { if (sdl_event.key.keysym.scancode == SDL_SCANCODE_COMMA) @@ -523,6 +541,13 @@ void LCD_HandleEvent(lcd_t& lcd, const SDL_Event& sdl_event) lcd.lcd_quit_requested = true; break; + case SDL_WINDOWEVENT: + if (sdl_event.window.event == SDL_WINDOWEVENT_CLOSE) + { + lcd.lcd_quit_requested = true; + } + break; + case SDL_KEYDOWN: case SDL_KEYUP: { diff --git a/src/main_frontend.cpp b/src/main_frontend.cpp index 5dcd6c17..a36a62f9 100644 --- a/src/main_frontend.cpp +++ b/src/main_frontend.cpp @@ -47,6 +47,7 @@ #include "utils/files.h" #include "emu.h" #include "ringbuffer.h" +#include "math_util.h" #if __linux__ #include @@ -65,83 +66,59 @@ const char* rs_name[ROM_SET_COUNT] = { "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", -}; - static int audio_buffer_size; static int audio_page_size; static SDL_AudioDeviceID sdl_audio; -ringbuffer_t buf; +struct fe_emu_instance_t { + emu_backend_t emu; + ringbuffer_t sample_buffer; + SDL_Thread* thread; +}; + +const size_t FE_MAX_INSTANCES = 16; + +struct frontend_t { + fe_emu_instance_t instances[FE_MAX_INSTANCES]; + size_t instances_in_use = 0; +}; + +frontend_t global_fe; + +void FE_RouteMIDI(frontend_t& fe, uint8_t* first, uint8_t* last) +{ + if (*first >= 0x80) + { + uint8_t channel = *first & 0x0F; + + while (first != last) + { + MCU_PostUART(*fe.instances[channel % fe.instances_in_use].emu.mcu, *first); + ++first; + } + } + else + { + printf("data packet?!\n"); + } +} void FE_StepBegin(void* userdata) { - mcu_t& mcu = *(mcu_t*)userdata; - buf.oversampling = mcu.pcm->config_reg_3c & 0x40; + fe_emu_instance_t& fe = *(fe_emu_instance_t*)userdata; + RB_SetOversamplingEnabled(fe.sample_buffer, fe.emu.pcm->config_reg_3c & 0x40); } bool FE_Wait(void* userdata) { - return RB_IsFull(buf); + fe_emu_instance_t& fe = *(fe_emu_instance_t*)userdata; + return RB_IsFull(fe.sample_buffer); } void FE_ReceiveSample(void* userdata, int *sample) { + fe_emu_instance_t& fe = *(fe_emu_instance_t*)userdata; sample[0] >>= 15; if (sample[0] > INT16_MAX) sample[0] = INT16_MAX; @@ -152,43 +129,27 @@ void FE_ReceiveSample(void* userdata, int *sample) sample[1] = INT16_MAX; else if (sample[1] < INT16_MIN) sample[1] = INT16_MIN; - RB_Write(buf, sample[0], sample[1]); -} - -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<mcu_mk1 || fe.emu.mcu->mcu_jv880) ? 64000 : 66207; spec.channels = 2; spec.callback = audio_callback; spec.samples = audio_page_size / 4; - - RB_Init(buf, audio_buffer_size / 2); int num = SDL_GetNumAudioDevices(0); if (num == 0) @@ -279,28 +238,6 @@ int FE_OpenAudio(mcu_t& mcu, int deviceIndex, int pageSize, int pageNum) void FE_CloseAudio(void) { SDL_CloseAudio(); - RB_Free(buf); -} - - -static const size_t rf_num = 5; -static FILE *s_rf[rf_num] = -{ - nullptr, - nullptr, - nullptr, - nullptr, - nullptr -}; - -static void closeAllR() -{ - for(size_t i = 0; i < rf_num; ++i) - { - if(s_rf[i]) - fclose(s_rf[i]); - s_rf[i] = nullptr; - } } enum class ResetType { @@ -347,31 +284,44 @@ int SDLCALL FE_RunMCU(void* data) return 0; } -void FE_Run(mcu_t& mcu) +void FE_Run(frontend_t& fe) { bool working = true; work_thread_run = true; - SDL_Thread *thread = SDL_CreateThread(FE_RunMCU, "work thread", &mcu); + + for (int i = 0; i < fe.instances_in_use; ++i) + { + fe.instances[i].thread = SDL_CreateThread(FE_RunMCU, "work thread", fe.instances[i].emu.mcu); + } while (working) { - if (LCD_QuitRequested(*mcu.lcd)) - working = false; + for (int i = 0; i < fe.instances_in_use; ++i) + { + if (LCD_QuitRequested(*fe.instances[i].emu.lcd)) + working = false; - LCD_Update(*mcu.lcd); + LCD_Update(*fe.instances[i].emu.lcd); + } SDL_Event sdl_event; while (SDL_PollEvent(&sdl_event)) { - LCD_HandleEvent(*mcu.lcd, sdl_event); + for (int i = 0; i < fe.instances_in_use; ++i) + { + LCD_HandleEvent(*fe.instances[i].emu.lcd, sdl_event); + } } SDL_Delay(15); } work_thread_run = false; - SDL_WaitThread(thread, 0); + for (int i = 0; i < fe.instances_in_use; ++i) + { + SDL_WaitThread(fe.instances[i].thread, 0); + } } int FE_Init() @@ -386,8 +336,43 @@ int FE_Init() return 0; } +bool FE_CreateInstance(const std::string& basePath, int romset) +{ + fe_emu_instance_t& fe = global_fe.instances[global_fe.instances_in_use]; + ++global_fe.instances_in_use; + + EMU_Init(fe.emu); + // TODO: Clean up, shouldn't need to reach into emu for this + fe.emu.mcu->callback_userdata = &fe; + fe.emu.mcu->step_begin_callback = FE_StepBegin; + fe.emu.mcu->sample_callback = FE_ReceiveSample; + fe.emu.mcu->wait_callback = FE_Wait; + + LCD_LoadBack(*fe.emu.lcd, basePath + "/back.data"); + + if (EMU_LoadRoms(fe.emu, romset, basePath) != 0) + { + fprintf(stderr, "ERROR: Failed to load roms.\n"); + return false; + } + EMU_Reset(fe.emu); + + return true; +} + +void FE_DestroyInstance(fe_emu_instance_t& fe) +{ + EMU_Free(fe.emu); + RB_Free(fe.sample_buffer); + fe.thread = nullptr; +} + void FE_Quit() { + for (int i = 0; i < global_fe.instances_in_use; ++i) + { + FE_DestroyInstance(global_fe.instances[i]); + } FE_CloseAudio(); MIDI_Quit(); SDL_Quit(); @@ -404,6 +389,7 @@ int main(int argc, char *argv[]) int pageNum = 32; bool autodetect = true; ResetType resetType = ResetType::NONE; + int instance_count = 1; int romset = ROM_SET_MK2; @@ -439,6 +425,11 @@ int main(int argc, char *argv[]) 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; @@ -492,6 +483,7 @@ int main(int argc, char *argv[]) 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"); @@ -537,255 +529,55 @@ int main(int argc, char *argv[]) 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; - } - } + romset = EMU_DetectRoms(basePath); printf("ROM set autodetect: %s\n", rs_name[romset]); } if (FE_Init() != 0) { - return 2; - } - - emu_backend_t emu; - EMU_Init(emu); - // TODO: Clean up, shouldn't need to reach into emu for this - emu.mcu->callback_userdata = emu.mcu; - emu.mcu->step_begin_callback = FE_StepBegin; - emu.mcu->sample_callback = FE_ReceiveSample; - emu.mcu->wait_callback = FE_Wait; - - LCD_LoadBack(*emu.lcd, basePath + "/back.data"); - - emu.mcu->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; + return 1; } - - std::string rpaths[5]; - - bool r_ok = true; - std::string errors_list; - - for(size_t i = 0; i < 5; ++i) + + for (int i = 0; i < instance_count; ++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 (!FE_CreateInstance(basePath, romset)) { - if(!errors_list.empty()) - errors_list.append(", "); - - errors_list.append(rpaths[i]); + fprintf(stderr, "Failed to create instance %d\n", i); + return 1; } } - if (!r_ok) + // TODO: fix this hack, need to separate audio buffer size calculation + // to avoid passing single fe instance here - we actually want to use the + // same buffer size for all instances + if (!FE_OpenAudio(global_fe.instances[0], audioDeviceIndex, pageSize, pageNum)) { - fprintf(stderr, "FATAL ERROR: One of required data ROM files is missing: %s.\n", errors_list.c_str()); + fprintf(stderr, "FATAL ERROR: Failed to open the audio stream.\n"); fflush(stderr); - closeAllR(); return 1; } - if (fread(emu.mcu->rom1, 1, ROM1_SIZE, s_rf[0]) != ROM1_SIZE) + for (int i = 0; i < global_fe.instances_in_use; ++i) { - fprintf(stderr, "FATAL ERROR: Failed to read the mcu ROM1.\n"); - fflush(stderr); - closeAllR(); - return 1; + fe_emu_instance_t& fe = global_fe.instances[i]; + RB_Init(fe.sample_buffer, audio_buffer_size / 2); } - 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 + if (!MIDI_Init(global_fe, port)) { - fprintf(stderr, "FATAL ERROR: Failed to read the mcu ROM2.\n"); + fprintf(stderr, "ERROR: Failed to initialize the MIDI Input.\nWARNING: Continuing without MIDI Input...\n"); fflush(stderr); - closeAllR(); - return 1; - } - - 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); - closeAllR(); - return 1; - } - - 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); - closeAllR(); - return 1; - } - - 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); - closeAllR(); - return 1; - } - - 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); - closeAllR(); - return 1; - } - - 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); - closeAllR(); - return 1; - } - 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 (resetType != ResetType::NONE) { - 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, 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); - closeAllR(); - return 1; - } - - 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) + for (int i = 0; i < global_fe.instances_in_use; ++i) { - fprintf(stderr, "FATAL ERROR: Failed to read the sub mcu ROM.\n"); - fflush(stderr); - closeAllR(); - return 1; + MIDI_Reset(*global_fe.instances[i].emu.mcu, resetType); } } - // Close all files as they no longer needed being open - closeAllR(); - - EMU_Reset(emu); - - if (!FE_OpenAudio(*emu.mcu, audioDeviceIndex, pageSize, pageNum)) - { - fprintf(stderr, "FATAL ERROR: Failed to open the audio stream.\n"); - fflush(stderr); - return 2; - } - - if(!MIDI_Init(*emu.mcu, port)) - { - fprintf(stderr, "ERROR: Failed to initialize the MIDI Input.\nWARNING: Continuing without MIDI Input...\n"); - fflush(stderr); - } - - if (resetType != ResetType::NONE) MIDI_Reset(*emu.mcu, resetType); - - FE_Run(*emu.mcu); - - EMU_Free(emu); + FE_Run(global_fe); FE_Quit(); diff --git a/src/math_util.h b/src/math_util.h new file mode 100644 index 00000000..16ed468f --- /dev/null +++ b/src/math_util.h @@ -0,0 +1,23 @@ +#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/midi.h b/src/midi.h index 4a62f933..da7f68d1 100644 --- a/src/midi.h +++ b/src/midi.h @@ -33,8 +33,8 @@ */ #pragma once -struct mcu_t; +struct frontend_t; -int MIDI_Init(mcu_t& mcu, int port); +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 a9dca649..757b2703 100644 --- a/src/midi_rtmidi.cpp +++ b/src/midi_rtmidi.cpp @@ -1,19 +1,20 @@ #include #include "mcu.h" +#include "emu.h" #include "midi.h" #include static RtMidiIn *s_midi_in = nullptr; -static mcu_t* midi_mcu_instance = 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(*midi_mcu_instance, *beg++); + FE_RouteMIDI(*midi_frontend, beg, end); } static void MidiOnError(RtMidiError::Type, const std::string &errorText, void *) @@ -22,7 +23,7 @@ static void MidiOnError(RtMidiError::Type, const std::string &errorText, void *) fflush(stderr); } -int MIDI_Init(mcu_t& mcu, int port) +int MIDI_Init(frontend_t& frontend, int port) { if (s_midi_in) { @@ -30,7 +31,7 @@ int MIDI_Init(mcu_t& mcu, int port) return 0; // Already running } - midi_mcu_instance = &mcu; + midi_frontend = &frontend; s_midi_in = new RtMidiIn(RtMidi::UNSPECIFIED, "Nuked SC55", 1024); s_midi_in->ignoreTypes(false, false, false); // SysEx disabled by default @@ -65,6 +66,6 @@ void MIDI_Quit() s_midi_in->closePort(); delete s_midi_in; s_midi_in = nullptr; - midi_mcu_instance = nullptr; + midi_frontend = nullptr; } } diff --git a/src/midi_win32.cpp b/src/midi_win32.cpp index 4d6a40ac..d830a671 100644 --- a/src/midi_win32.cpp +++ b/src/midi_win32.cpp @@ -43,7 +43,9 @@ static MIDIHDR midi_buffer; static char midi_in_buffer[1024]; -static mcu_t* midi_mcu_instance = nullptr; +static frontend_t* midi_frontend = nullptr; + +void FE_RouteMIDI(frontend_t& fe, uint8_t* first, uint8_t* last); void CALLBACK MIDI_Callback( HMIDIIN hMidiIn, @@ -67,14 +69,24 @@ void CALLBACK MIDI_Callback( case 0xa0: case 0xb0: case 0xe0: - MCU_PostUART(*midi_mcu_instance, b1); - MCU_PostUART(*midi_mcu_instance, (dwParam1 >> 8) & 0xff); - MCU_PostUART(*midi_mcu_instance, (dwParam1 >> 16) & 0xff); + { + uint8_t buf[3] = { + b1, + (dwParam1 >> 8) & 0xff, + (dwParam1 >> 16) & 0xff, + }; + FE_RouteMIDI(*midi_frontend, (uint8_t*)buf, (uint8_t*)(buf + 3)); + } break; case 0xc0: case 0xd0: - MCU_PostUART(*midi_mcu_instance, b1); - MCU_PostUART(*midi_mcu_instance, (dwParam1 >> 8) & 0xff); + { + uint8_t buf[2] = { + b1, + (dwParam1 >> 8) & 0xff, + }; + FE_RouteMIDI(*midi_frontend, (uint8_t*)buf, (uint8_t*)(buf + 2)); + } break; } break; @@ -88,7 +100,12 @@ void CALLBACK MIDI_Callback( { for (int i = 0; i < midi_buffer.dwBytesRecorded; i++) { - MCU_PostUART(*midi_mcu_instance, midi_in_buffer[i]); + //MCU_PostUART(*midi_mcu_instance, midi_in_buffer[i]); + FE_RouteMIDI( + *midi_frontend, + (uint8_t*)midi_in_buffer, + (uint8_t*)midi_in_buffer + midi_buffer.dwBytesRecorded + ); } } @@ -103,9 +120,9 @@ void CALLBACK MIDI_Callback( } } -int MIDI_Init(mcu_t& mcu, int port) +int MIDI_Init(frontend_t& frontend, int port) { - midi_mcu_instance = &mcu; + midi_frontend = &frontend; int num = midiInGetNumDevs(); @@ -153,5 +170,5 @@ void MIDI_Quit() midiInClose(midi_handle); midi_handle = 0; } - midi_mcu_instance = nullptr; + midi_frontend = nullptr; } diff --git a/src/ringbuffer.h b/src/ringbuffer.h index 3f4ce138..68341c84 100644 --- a/src/ringbuffer.h +++ b/src/ringbuffer.h @@ -3,6 +3,7 @@ #include #include #include +#include "math_util.h" const int RB_CHANNEL_COUNT = 2; @@ -31,6 +32,19 @@ inline void RB_Free(ringbuffer_t& rb) free(rb.samples); } +inline void RB_SetOversamplingEnabled(ringbuffer_t& rb, bool enabled) +{ + rb.oversampling = enabled; + if (rb.oversampling) + { + rb.write_head &= ~3; + } + else + { + rb.write_head &= ~1; + } +} + inline bool RB_IsFull(ringbuffer_t& rb) { if (rb.oversampling) @@ -45,11 +59,6 @@ inline bool RB_IsFull(ringbuffer_t& rb) inline void RB_Write(ringbuffer_t& rb, int16_t left, int16_t right) { - if (RB_IsFull(rb)) - { - fprintf(stderr, "Ringbuffer overflow\n"); - exit(1); - } rb.samples[rb.write_head + 0] = left; rb.samples[rb.write_head + 1] = right; rb.write_head = (rb.write_head + RB_CHANNEL_COUNT) % rb.sample_count; @@ -68,7 +77,7 @@ inline size_t RB_ReadableSampleCount(ringbuffer_t& rb) } // Reads up to `sample_count` samples and returns the number of samples -// actually read +// actually read. inline size_t RB_Read(ringbuffer_t& rb, int16_t* dest, size_t sample_count) { size_t have_count = RB_ReadableSampleCount(rb); @@ -85,3 +94,20 @@ inline size_t RB_Read(ringbuffer_t& rb, int16_t* dest, size_t sample_count) return read_count; } +// Reads up to `sample_count` samples and returns the number of samples +// actually read. Mixes samples into dest by adding and clipping. +inline size_t RB_ReadMix(ringbuffer_t& rb, int16_t* dest, size_t sample_count) +{ + size_t have_count = RB_ReadableSampleCount(rb); + size_t read_count = sample_count < have_count ? sample_count : have_count; + size_t read_head = rb.read_head; + for (size_t i = 0; i < read_count; ++i) + { + *dest = saturating_add(*dest, rb.samples[read_head]); + ++dest; + read_head = (read_head + 1) % rb.sample_count; + } + rb.read_head = read_head; + return read_count; +} + From 73e98241bba769959a40337d4b2622938acc3fa3 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Mon, 29 Apr 2024 15:36:53 -0400 Subject: [PATCH 22/35] Fix sysex handling This commit routes sysex messages to all emulators and fixes a bug in the win32 midi input where sysex messages would be duplicated. --- src/main_frontend.cpp | 36 ++++++++++++++++++++++++++++-------- src/midi_win32.cpp | 14 +++++--------- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/main_frontend.cpp b/src/main_frontend.cpp index a36a62f9..2f2bccc4 100644 --- a/src/main_frontend.cpp +++ b/src/main_frontend.cpp @@ -86,21 +86,41 @@ struct frontend_t { frontend_t global_fe; +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) + if (*first < 0x80) { - uint8_t channel = *first & 0x0F; + printf("FE_RouteMIDI received data byte %02x\n", *first); + return; + } - while (first != last) - { - MCU_PostUART(*fe.instances[channel % fe.instances_in_use].emu.mcu, *first); - ++first; - } + const bool is_sysex = *first == 0xF0; + const uint8_t channel = *first & 0x0F; + + if (is_sysex) + { + FE_BroadcastMIDI(fe, first, last); } else { - printf("data packet?!\n"); + FE_SendMIDI(fe, channel % fe.instances_in_use, first, last); } } diff --git a/src/midi_win32.cpp b/src/midi_win32.cpp index d830a671..aa58379b 100644 --- a/src/midi_win32.cpp +++ b/src/midi_win32.cpp @@ -98,15 +98,11 @@ void CALLBACK MIDI_Callback( if (wMsg == MIM_LONGDATA) { - for (int i = 0; i < midi_buffer.dwBytesRecorded; i++) - { - //MCU_PostUART(*midi_mcu_instance, midi_in_buffer[i]); - FE_RouteMIDI( - *midi_frontend, - (uint8_t*)midi_in_buffer, - (uint8_t*)midi_in_buffer + midi_buffer.dwBytesRecorded - ); - } + FE_RouteMIDI( + *midi_frontend, + (uint8_t*)midi_in_buffer, + (uint8_t*)midi_in_buffer + midi_buffer.dwBytesRecorded + ); } midiInPrepareHeader(midi_handle, &midi_buffer, sizeof(MIDIHDR)); From 5fae2bc2b5731dd4c7c4bc997da4419149a2af9a Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Mon, 29 Apr 2024 19:21:59 -0400 Subject: [PATCH 23/35] Remove global_fe and the last of the global state --- src/main_frontend.cpp | 124 ++++++++++++++++++++++++++---------------- 1 file changed, 76 insertions(+), 48 deletions(-) diff --git a/src/main_frontend.cpp b/src/main_frontend.cpp index 2f2bccc4..684694e3 100644 --- a/src/main_frontend.cpp +++ b/src/main_frontend.cpp @@ -66,11 +66,6 @@ const char* rs_name[ROM_SET_COUNT] = { "SC-155mk2" }; -static int audio_buffer_size; -static int audio_page_size; - -static SDL_AudioDeviceID sdl_audio; - struct fe_emu_instance_t { emu_backend_t emu; ringbuffer_t sample_buffer; @@ -82,9 +77,30 @@ 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; }; -frontend_t global_fe; +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]; + ++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) { @@ -152,23 +168,25 @@ void FE_ReceiveSample(void* userdata, int *sample) RB_Write(fe.sample_buffer, sample[0], sample[1]); } -void audio_callback(void* /*userdata*/, Uint8* stream, int len) +void FE_AudioCallback(void* userdata, Uint8* stream, int len) { + frontend_t& frontend = *(frontend_t*)userdata; + const size_t num_samples = len / sizeof(int16_t); memset(stream, 0, len); size_t renderable_count = num_samples; - for (int i = 0; i < global_fe.instances_in_use; ++i) + for (int i = 0; i < frontend.instances_in_use; ++i) { renderable_count = min( renderable_count, - RB_ReadableSampleCount(global_fe.instances[i].sample_buffer) + RB_ReadableSampleCount(frontend.instances[i].sample_buffer) ); } - for (int i = 0; i < global_fe.instances_in_use; ++i) + for (int i = 0; i < frontend.instances_in_use; ++i) { - RB_ReadMix(global_fe.instances[i].sample_buffer, (int16_t*)stream, renderable_count); + RB_ReadMix(frontend.instances[i].sample_buffer, (int16_t*)stream, renderable_count); } } @@ -200,19 +218,25 @@ static const char* audio_format_to_str(int format) return "UNK"; } -int FE_OpenAudio(fe_emu_instance_t& fe, int deviceIndex, int pageSize, int pageNum) +int FE_OpenAudio(frontend_t& fe, int deviceIndex, int pageSize, int pageNum) { SDL_AudioSpec spec = {}; SDL_AudioSpec spec_actual = {}; - audio_page_size = (pageSize/2)*2; // must be even - audio_buffer_size = audio_page_size*pageNum; + 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 = (fe.emu.mcu->mcu_mk1 || fe.emu.mcu->mcu_jv880) ? 64000 : 66207; + spec.freq = (mcu.mcu_mk1 || mcu.mcu_jv880) ? 64000 : 66207; spec.channels = 2; - spec.callback = audio_callback; - spec.samples = audio_page_size / 4; + spec.callback = FE_AudioCallback; + spec.userdata = &fe; + spec.samples = fe.audio_page_size / 4; int num = SDL_GetNumAudioDevices(0); if (num == 0) @@ -229,8 +253,8 @@ int FE_OpenAudio(fe_emu_instance_t& fe, int deviceIndex, int pageSize, int pageN 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) + fe.sdl_audio = SDL_OpenAudioDevice(deviceIndex == -1 ? NULL : audioDevicename, 0, &spec, &spec_actual, 0); + if (!fe.sdl_audio) { return 0; } @@ -250,7 +274,7 @@ int FE_OpenAudio(fe_emu_instance_t& fe, int deviceIndex, int pageSize, int pageN spec_actual.samples); fflush(stdout); - SDL_PauseAudioDevice(sdl_audio, 0); + SDL_PauseAudioDevice(fe.sdl_audio, 0); return 1; } @@ -356,26 +380,31 @@ int FE_Init() return 0; } -bool FE_CreateInstance(const std::string& basePath, int romset) +bool FE_CreateInstance(frontend_t& container, const std::string& basePath, int romset) { - fe_emu_instance_t& fe = global_fe.instances[global_fe.instances_in_use]; - ++global_fe.instances_in_use; + fe_emu_instance_t* fe = nullptr; + + if (!FE_AllocateInstance(container, &fe)) + { + fprintf(stderr, "ERROR: Failed to allocate instance.\n"); + return false; + } - EMU_Init(fe.emu); + EMU_Init(fe->emu); // TODO: Clean up, shouldn't need to reach into emu for this - fe.emu.mcu->callback_userdata = &fe; - fe.emu.mcu->step_begin_callback = FE_StepBegin; - fe.emu.mcu->sample_callback = FE_ReceiveSample; - fe.emu.mcu->wait_callback = FE_Wait; + fe->emu.mcu->callback_userdata = fe; + fe->emu.mcu->step_begin_callback = FE_StepBegin; + fe->emu.mcu->sample_callback = FE_ReceiveSample; + fe->emu.mcu->wait_callback = FE_Wait; - LCD_LoadBack(*fe.emu.lcd, basePath + "/back.data"); + LCD_LoadBack(*fe->emu.lcd, basePath + "/back.data"); - if (EMU_LoadRoms(fe.emu, romset, basePath) != 0) + if (EMU_LoadRoms(fe->emu, romset, basePath) != 0) { fprintf(stderr, "ERROR: Failed to load roms.\n"); return false; } - EMU_Reset(fe.emu); + EMU_Reset(fe->emu); return true; } @@ -387,11 +416,11 @@ void FE_DestroyInstance(fe_emu_instance_t& fe) fe.thread = nullptr; } -void FE_Quit() +void FE_Quit(frontend_t& container) { - for (int i = 0; i < global_fe.instances_in_use; ++i) + for (int i = 0; i < container.instances_in_use; ++i) { - FE_DestroyInstance(global_fe.instances[i]); + FE_DestroyInstance(container.instances[i]); } FE_CloseAudio(); MIDI_Quit(); @@ -413,6 +442,8 @@ int main(int argc, char *argv[]) int romset = ROM_SET_MK2; + frontend_t frontend; + { for (int i = 1; i < argc; i++) { @@ -557,33 +588,30 @@ int main(int argc, char *argv[]) { return 1; } - + for (int i = 0; i < instance_count; ++i) { - if (!FE_CreateInstance(basePath, romset)) + if (!FE_CreateInstance(frontend, basePath, romset)) { fprintf(stderr, "Failed to create instance %d\n", i); return 1; } } - // TODO: fix this hack, need to separate audio buffer size calculation - // to avoid passing single fe instance here - we actually want to use the - // same buffer size for all instances - if (!FE_OpenAudio(global_fe.instances[0], audioDeviceIndex, pageSize, pageNum)) + if (!FE_OpenAudio(frontend, audioDeviceIndex, pageSize, pageNum)) { fprintf(stderr, "FATAL ERROR: Failed to open the audio stream.\n"); fflush(stderr); return 1; } - for (int i = 0; i < global_fe.instances_in_use; ++i) + for (int i = 0; i < frontend.instances_in_use; ++i) { - fe_emu_instance_t& fe = global_fe.instances[i]; - RB_Init(fe.sample_buffer, audio_buffer_size / 2); + fe_emu_instance_t& fe = frontend.instances[i]; + RB_Init(fe.sample_buffer, frontend.audio_buffer_size / 2); } - if (!MIDI_Init(global_fe, port)) + if (!MIDI_Init(frontend, port)) { fprintf(stderr, "ERROR: Failed to initialize the MIDI Input.\nWARNING: Continuing without MIDI Input...\n"); fflush(stderr); @@ -591,15 +619,15 @@ int main(int argc, char *argv[]) if (resetType != ResetType::NONE) { - for (int i = 0; i < global_fe.instances_in_use; ++i) + for (int i = 0; i < frontend.instances_in_use; ++i) { - MIDI_Reset(*global_fe.instances[i].emu.mcu, resetType); + MIDI_Reset(*frontend.instances[i].emu.mcu, resetType); } } - FE_Run(global_fe); + FE_Run(frontend); - FE_Quit(); + FE_Quit(frontend); return 0; } From d5a6382ad4491260e8bce5ed96ff6a63da39c859 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Wed, 1 May 2024 04:44:50 -0400 Subject: [PATCH 24/35] Last minute cleanup - Proper error handling - Deal with all the warnings these changes introduced --- src/emu.cpp | 144 +++++++++++++++++++++++++++++++++--------- src/emu.h | 7 +- src/lcd.cpp | 29 +++++---- src/lcd.h | 17 ++--- src/main_frontend.cpp | 61 ++++++++---------- src/mcu.cpp | 9 ++- src/mcu.h | 22 +++---- src/midi_win32.cpp | 14 ++-- src/pcm.cpp | 2 +- src/pcm.h | 2 +- src/ringbuffer.h | 10 ++- src/submcu.cpp | 26 ++------ src/submcu.h | 3 +- 13 files changed, 211 insertions(+), 135 deletions(-) diff --git a/src/emu.cpp b/src/emu.cpp index efc28b64..8183e071 100644 --- a/src/emu.cpp +++ b/src/emu.cpp @@ -6,40 +6,117 @@ #include "pcm.h" #include "utils/files.h" -void EMU_Init(emu_backend_t& emu) +bool EMU_Init(emu_backend_t& emu) { - emu.mcu = (mcu_t*)malloc(sizeof(mcu_t)); - emu.sm = (submcu_t*)malloc(sizeof(submcu_t)); + memset(&emu, 0, sizeof(emu_backend_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)); - emu.lcd = (lcd_t*)malloc(sizeof(lcd_t)); - emu.pcm = (pcm_t*)malloc(sizeof(pcm_t)); + if (!emu.timer) + { + EMU_Free(emu); + return false; + } - PCM_Reset(*emu.pcm, *emu.mcu); - MCU_Init(*emu.mcu, *emu.sm, *emu.pcm, *emu.timer, *emu.lcd); + 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); // TODO: LCD should be optional for use with other frontends - LCD_Init(*emu.lcd, *emu.mcu); + if (!LCD_Init(*emu.lcd, *emu.mcu)) + { + EMU_Free(emu); + return false; + } + + return true; } void EMU_Free(emu_backend_t& emu) { - LCD_UnInit(*emu.lcd); - free(emu.pcm); - free(emu.lcd); - free(emu.timer); - free(emu.sm); - free(emu.mcu); + 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; + } } -// Should be called after loading roms void EMU_Reset(emu_backend_t& emu) { MCU_PatchROM(*emu.mcu); MCU_Reset(*emu.mcu); - SM_Reset(*emu.sm, *emu.mcu); + SM_Reset(*emu.sm); } +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", @@ -146,7 +223,7 @@ static void closeAllR() } } -int EMU_DetectRoms(const std::string& basePath) +int EMU_DetectRomset(const std::string& basePath) { for (size_t i = 0; i < ROM_SET_COUNT; i++) { @@ -169,10 +246,10 @@ int EMU_DetectRoms(const std::string& basePath) return i; } } - return 0; + return ROM_SET_MK2; } -int EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) +bool EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) { emu.mcu->romset = romset; emu.mcu->mcu_mk1 = false; @@ -242,7 +319,7 @@ int EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) fprintf(stderr, "FATAL ERROR: One of required data ROM files is missing: %s.\n", errors_list.c_str()); fflush(stderr); closeAllR(); - return 1; + return false; } if (fread(emu.mcu->rom1, 1, ROM1_SIZE, s_rf[0]) != ROM1_SIZE) @@ -250,7 +327,7 @@ int EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) fprintf(stderr, "FATAL ERROR: Failed to read the mcu ROM1.\n"); fflush(stderr); closeAllR(); - return 1; + return false; } size_t rom2_read = fread(emu.mcu->rom2, 1, ROM2_SIZE, s_rf[1]); @@ -264,7 +341,7 @@ int EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) fprintf(stderr, "FATAL ERROR: Failed to read the mcu ROM2.\n"); fflush(stderr); closeAllR(); - return 1; + return false; } if (emu.mcu->mcu_mk1) @@ -274,7 +351,7 @@ int EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom1.\n"); fflush(stderr); closeAllR(); - return 1; + return false; } unscramble(tempbuf, emu.pcm->waverom1, 0x100000); @@ -284,7 +361,7 @@ int EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom2.\n"); fflush(stderr); closeAllR(); - return 1; + return false; } unscramble(tempbuf, emu.pcm->waverom2, 0x100000); @@ -294,7 +371,7 @@ int EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom3.\n"); fflush(stderr); closeAllR(); - return 1; + return false; } unscramble(tempbuf, emu.pcm->waverom3, 0x100000); @@ -306,7 +383,7 @@ int EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom1.\n"); fflush(stderr); closeAllR(); - return 1; + return false; } unscramble(tempbuf, emu.pcm->waverom1, 0x200000); @@ -316,7 +393,7 @@ int EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom2.\n"); fflush(stderr); closeAllR(); - return 1; + return false; } unscramble(tempbuf, emu.pcm->waverom2, 0x200000); @@ -333,7 +410,7 @@ int EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom1.\n"); fflush(stderr); closeAllR(); - return 1; + return false; } unscramble(tempbuf, emu.pcm->waverom1, 0x200000); @@ -345,7 +422,7 @@ int EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom2.\n"); fflush(stderr); closeAllR(); - return 1; + return false; } unscramble(tempbuf, emu.mcu->mcu_scb55 ? emu.pcm->waverom3 : emu.pcm->waverom2, 0x100000); @@ -356,12 +433,17 @@ int EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) fprintf(stderr, "FATAL ERROR: Failed to read the sub mcu ROM.\n"); fflush(stderr); closeAllR(); - return 1; + return false; } } // Close all files as they no longer needed being open closeAllR(); - return 0; + return true; +} + +const char* EMU_RomsetName(int romset) +{ + return rs_name[romset]; } diff --git a/src/emu.h b/src/emu.h index 9d9650a5..bf442226 100644 --- a/src/emu.h +++ b/src/emu.h @@ -16,11 +16,12 @@ struct emu_backend_t { pcm_t* pcm; }; -void EMU_Init(emu_backend_t& emu); +bool EMU_Init(emu_backend_t& emu); void EMU_Free(emu_backend_t& emu); // Should be called after loading roms void EMU_Reset(emu_backend_t& emu); -int EMU_DetectRoms(const std::string& basePath); -int EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath); +int EMU_DetectRomset(const std::string& basePath); +bool EMU_LoadRoms(emu_backend_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 dd51d9eb..4dfea5dc 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -35,12 +35,14 @@ #include #include #include +#include "SDL.h" #include "SDL_mutex.h" #include "lcd.h" #include "lcd_font.h" #include "mcu.h" #include "submcu.h" #include "utils/files.h" +#include "emu.h" void LCD_Enable(lcd_t& lcd, uint32_t enable) { @@ -197,11 +199,9 @@ const int button_map_jv880[][2] = void LCD_LoadBack(lcd_t& lcd, const std::string& path) { - lcd.m_back_path = path; - FILE *raw; - raw = Files::utf8_fopen(lcd.m_back_path.c_str(), "rb"); + raw = Files::utf8_fopen(path.c_str(), "rb"); if (!raw) return; @@ -209,11 +209,13 @@ void LCD_LoadBack(lcd_t& lcd, const std::string& path) fclose(raw); } -void LCD_Init(lcd_t& lcd, mcu_t& mcu) +bool LCD_Init(lcd_t& lcd, mcu_t& mcu) { - lcd.lcd_init = 0; if (lcd.lcd_init) - return; + return false; + + memset(&lcd, 0, sizeof(lcd_t)); + lcd.mcu = &mcu; if (mcu.romset == ROM_SET_JV880) { @@ -226,28 +228,25 @@ void LCD_Init(lcd_t& lcd, mcu_t& mcu) lcd.lcd_height = 268; } - lcd.mcu = &mcu; - - lcd.lcd_quit_requested = false; - std::string title = "Nuked SC-55: "; - title += rs_name[mcu.romset]; + title += EMU_RomsetName(mcu.romset); 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; + return false; lcd.renderer = SDL_CreateRenderer(lcd.window, -1, 0); if (!lcd.renderer) - return; + return false; lcd.texture = SDL_CreateTexture(lcd.renderer, SDL_PIXELFORMAT_BGR888, SDL_TEXTUREACCESS_STREAMING, lcd.lcd_width, lcd.lcd_height); if (!lcd.texture) - return; + return false; lcd.lcd_init = 1; + return true; } void LCD_UnInit(lcd_t& lcd) @@ -518,11 +517,13 @@ void LCD_HandleEvent(lcd_t& lcd, const SDL_Event& sdl_event) { return; } + break; case SDL_WINDOWEVENT: if (sdl_event.window.windowID != SDL_GetWindowID(lcd.window)) { return; } + break; default: break; } diff --git a/src/lcd.h b/src/lcd.h index c15abcf1..442831f3 100644 --- a/src/lcd.h +++ b/src/lcd.h @@ -35,10 +35,13 @@ #include #include -#include "SDL.h" 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; @@ -48,18 +51,16 @@ struct lcd_t { int lcd_width; int lcd_height; - uint32_t lcd_init = 0; + uint32_t lcd_init; 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 = 0; + uint32_t LCD_RAM_MODE; uint8_t LCD_Data[80]; uint8_t LCD_CG[64]; - uint8_t lcd_enable = 1; - bool lcd_quit_requested = false; - - std::string m_back_path = "back.data"; + uint8_t lcd_enable; + bool lcd_quit_requested; uint32_t lcd_buffer[lcd_height_max][lcd_width_max]; uint32_t lcd_background[268][741]; @@ -71,7 +72,7 @@ struct lcd_t { void LCD_LoadBack(lcd_t& lcd, const std::string& path); -void LCD_Init(lcd_t& lcd, mcu_t& mcu); +bool LCD_Init(lcd_t& lcd, mcu_t& mcu); 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); diff --git a/src/main_frontend.cpp b/src/main_frontend.cpp index 684694e3..22993372 100644 --- a/src/main_frontend.cpp +++ b/src/main_frontend.cpp @@ -54,18 +54,6 @@ #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" -}; - struct fe_emu_instance_t { emu_backend_t emu; ringbuffer_t sample_buffer; @@ -176,7 +164,7 @@ void FE_AudioCallback(void* userdata, Uint8* stream, int len) memset(stream, 0, len); size_t renderable_count = num_samples; - for (int i = 0; i < frontend.instances_in_use; ++i) + for (size_t i = 0; i < frontend.instances_in_use; ++i) { renderable_count = min( renderable_count, @@ -184,7 +172,7 @@ void FE_AudioCallback(void* userdata, Uint8* stream, int len) ); } - for (int i = 0; i < frontend.instances_in_use; ++i) + for (size_t i = 0; i < frontend.instances_in_use; ++i) { RB_ReadMix(frontend.instances[i].sample_buffer, (int16_t*)stream, renderable_count); } @@ -218,7 +206,7 @@ static const char* audio_format_to_str(int format) return "UNK"; } -int FE_OpenAudio(frontend_t& fe, int deviceIndex, int pageSize, int pageNum) +bool FE_OpenAudio(frontend_t& fe, int deviceIndex, int pageSize, int pageNum) { SDL_AudioSpec spec = {}; SDL_AudioSpec spec_actual = {}; @@ -242,7 +230,7 @@ int FE_OpenAudio(frontend_t& fe, int deviceIndex, int pageSize, int pageNum) if (num == 0) { printf("No audio output device found.\n"); - return 0; + return false; } if (deviceIndex < -1 || deviceIndex >= num) @@ -256,7 +244,7 @@ int FE_OpenAudio(frontend_t& fe, int deviceIndex, int pageSize, int pageNum) fe.sdl_audio = SDL_OpenAudioDevice(deviceIndex == -1 ? NULL : audioDevicename, 0, &spec, &spec_actual, 0); if (!fe.sdl_audio) { - return 0; + return false; } printf("Audio device: %s\n", audioDevicename); @@ -276,7 +264,7 @@ int FE_OpenAudio(frontend_t& fe, int deviceIndex, int pageSize, int pageNum) SDL_PauseAudioDevice(fe.sdl_audio, 0); - return 1; + return true; } void FE_CloseAudio(void) @@ -334,14 +322,14 @@ void FE_Run(frontend_t& fe) work_thread_run = true; - for (int i = 0; i < fe.instances_in_use; ++i) + for (size_t i = 0; i < fe.instances_in_use; ++i) { fe.instances[i].thread = SDL_CreateThread(FE_RunMCU, "work thread", fe.instances[i].emu.mcu); } while (working) { - for (int i = 0; i < fe.instances_in_use; ++i) + for (size_t i = 0; i < fe.instances_in_use; ++i) { if (LCD_QuitRequested(*fe.instances[i].emu.lcd)) working = false; @@ -352,7 +340,7 @@ void FE_Run(frontend_t& fe) SDL_Event sdl_event; while (SDL_PollEvent(&sdl_event)) { - for (int i = 0; i < fe.instances_in_use; ++i) + for (size_t i = 0; i < fe.instances_in_use; ++i) { LCD_HandleEvent(*fe.instances[i].emu.lcd, sdl_event); } @@ -362,22 +350,22 @@ void FE_Run(frontend_t& fe) } work_thread_run = false; - for (int i = 0; i < fe.instances_in_use; ++i) + for (size_t i = 0; i < fe.instances_in_use; ++i) { SDL_WaitThread(fe.instances[i].thread, 0); } } -int FE_Init() +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 2; + return false; } - return 0; + return true; } bool FE_CreateInstance(frontend_t& container, const std::string& basePath, int romset) @@ -399,7 +387,7 @@ bool FE_CreateInstance(frontend_t& container, const std::string& basePath, int r LCD_LoadBack(*fe->emu.lcd, basePath + "/back.data"); - if (EMU_LoadRoms(fe->emu, romset, basePath) != 0) + if (!EMU_LoadRoms(fe->emu, romset, basePath)) { fprintf(stderr, "ERROR: Failed to load roms.\n"); return false; @@ -418,7 +406,7 @@ void FE_DestroyInstance(fe_emu_instance_t& fe) void FE_Quit(frontend_t& container) { - for (int i = 0; i < container.instances_in_use; ++i) + for (size_t i = 0; i < container.instances_in_use; ++i) { FE_DestroyInstance(container.instances[i]); } @@ -580,12 +568,13 @@ int main(int argc, char *argv[]) if (autodetect) { - romset = EMU_DetectRoms(basePath); - printf("ROM set autodetect: %s\n", rs_name[romset]); + romset = EMU_DetectRomset(basePath); + printf("ROM set autodetect: %s\n", EMU_RomsetName(romset)); } - if (FE_Init() != 0) + if (!FE_Init()) { + fprintf(stderr, "FATAL ERROR: Failed to initialize frontend\n"); return 1; } @@ -593,7 +582,7 @@ int main(int argc, char *argv[]) { if (!FE_CreateInstance(frontend, basePath, romset)) { - fprintf(stderr, "Failed to create instance %d\n", i); + fprintf(stderr, "FATAL ERROR: Failed to create instance %d\n", i); return 1; } } @@ -605,10 +594,14 @@ int main(int argc, char *argv[]) return 1; } - for (int i = 0; i < frontend.instances_in_use; ++i) + for (size_t i = 0; i < frontend.instances_in_use; ++i) { fe_emu_instance_t& fe = frontend.instances[i]; - RB_Init(fe.sample_buffer, frontend.audio_buffer_size / 2); + 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)) @@ -619,7 +612,7 @@ int main(int argc, char *argv[]) if (resetType != ResetType::NONE) { - for (int i = 0; i < frontend.instances_in_use; ++i) + for (size_t i = 0; i < frontend.instances_in_use; ++i) { MIDI_Reset(*frontend.instances[i].emu.mcu, resetType); } diff --git a/src/mcu.cpp b/src/mcu.cpp index bb46f36c..48f3c43b 100644 --- a/src/mcu.cpp +++ b/src/mcu.cpp @@ -765,7 +765,7 @@ void MCU_ReadInstruction(mcu_t& mcu) } } -void MCU_Init(mcu_t& mcu, submcu_t& sm, pcm_t& pcm, mcu_timer_t& timer, lcd_t& lcd) +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; @@ -776,6 +776,11 @@ void MCU_Init(mcu_t& mcu, submcu_t& sm, pcm_t& pcm, mcu_timer_t& timer, lcd_t& l mcu.romset = ROM_SET_MK2; mcu.rom2_mask = ROM2_SIZE - 1; mcu.work_thread_lock = SDL_CreateMutex(); + if (!mcu.work_thread_lock) + { + return false; + } + return true; } void MCU_Deinit(mcu_t& mcu) @@ -928,6 +933,7 @@ void MCU_Step(mcu_t& mcu) void MCU_PatchROM(mcu_t& mcu) { + (void)mcu; //rom2[0x1333] = 0x11; //rom2[0x1334] = 0x19; //rom1[0x622d] = 0x19; @@ -935,6 +941,7 @@ void MCU_PatchROM(mcu_t& mcu) uint8_t MCU_ReadP0(mcu_t& mcu) { + (void)mcu; return 0xff; } diff --git a/src/mcu.h b/src/mcu.h index afeccba0..9ed872de 100644 --- a/src/mcu.h +++ b/src/mcu.h @@ -240,23 +240,23 @@ struct mcu_t { 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 = ROM2_SIZE - 1; + int rom2_mask; int ga_int[8]; - int ga_int_enable = 0; - int ga_int_trigger = 0; - int ga_lcd_counter = 0; + int ga_int_enable; + int ga_int_trigger; + int ga_lcd_counter; - SDL_atomic_t mcu_button_pressed = { 0 }; + SDL_atomic_t mcu_button_pressed; - uint8_t mcu_p0_data = 0x00; - uint8_t mcu_p1_data = 0x00; + uint8_t mcu_p0_data; + uint8_t mcu_p1_data; - int adf_rd = 0; + int adf_rd; uint64_t analog_end_time; - int ssr_rd = 0; + int ssr_rd; uint32_t operand_type; uint16_t operand_ea; @@ -276,7 +276,7 @@ struct mcu_t { SDL_mutex *work_thread_lock; }; -void MCU_Init(mcu_t& mcu, submcu_t& sm, pcm_t& pcm, mcu_timer_t& timer, lcd_t& lcd); +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); @@ -533,8 +533,6 @@ enum { ROM_SET_COUNT }; -extern const char* rs_name[ROM_SET_COUNT]; - uint8_t MCU_ReadP0(mcu_t& mcu); uint8_t MCU_ReadP1(mcu_t& mcu); void MCU_WriteP0(mcu_t& mcu, uint8_t data); diff --git a/src/midi_win32.cpp b/src/midi_win32.cpp index aa58379b..836f8007 100644 --- a/src/midi_win32.cpp +++ b/src/midi_win32.cpp @@ -71,21 +71,21 @@ void CALLBACK MIDI_Callback( case 0xe0: { uint8_t buf[3] = { - b1, - (dwParam1 >> 8) & 0xff, - (dwParam1 >> 16) & 0xff, + (uint8_t)b1, + (uint8_t)((dwParam1 >> 8) & 0xff), + (uint8_t)((dwParam1 >> 16) & 0xff), }; - FE_RouteMIDI(*midi_frontend, (uint8_t*)buf, (uint8_t*)(buf + 3)); + FE_RouteMIDI(*midi_frontend, (uint8_t*)buf, (uint8_t*)buf + sizeof(buf)); } break; case 0xc0: case 0xd0: { uint8_t buf[2] = { - b1, - (dwParam1 >> 8) & 0xff, + (uint8_t)b1, + (uint8_t)((dwParam1 >> 8) & 0xff), }; - FE_RouteMIDI(*midi_frontend, (uint8_t*)buf, (uint8_t*)(buf + 2)); + FE_RouteMIDI(*midi_frontend, (uint8_t*)buf, (uint8_t*)buf + sizeof(buf)); } break; } diff --git a/src/pcm.cpp b/src/pcm.cpp index 548dfdfe..ac0f0500 100644 --- a/src/pcm.cpp +++ b/src/pcm.cpp @@ -261,7 +261,7 @@ uint8_t PCM_Read(pcm_t& pcm, uint32_t address) return 0; } -void PCM_Reset(pcm_t& pcm, mcu_t& mcu) +void PCM_Init(pcm_t& pcm, mcu_t& mcu) { memset(&pcm, 0, sizeof(pcm)); pcm.mcu = &mcu; diff --git a/src/pcm.h b/src/pcm.h index d45b01a9..ad894732 100644 --- a/src/pcm.h +++ b/src/pcm.h @@ -74,5 +74,5 @@ struct pcm_t { void PCM_Write(pcm_t& pcm, uint32_t address, uint8_t data); uint8_t PCM_Read(pcm_t& pcm, uint32_t address); -void PCM_Reset(pcm_t& pcm, mcu_t& mcu); +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 index 68341c84..3f43a8ee 100644 --- a/src/ringbuffer.h +++ b/src/ringbuffer.h @@ -16,15 +16,19 @@ struct ringbuffer_t { bool oversampling; }; -inline void RB_Init(ringbuffer_t& rb, size_t frame_count) +inline bool RB_Init(ringbuffer_t& rb, size_t frame_count) { - rb.samples = (int16_t*)malloc(sizeof(int16_t) * RB_CHANNEL_COUNT * frame_count); - memset(rb.samples, 0, sizeof(int16_t) * RB_CHANNEL_COUNT * frame_count); + rb.samples = (int16_t*)calloc(RB_CHANNEL_COUNT * frame_count, sizeof(int16_t)); + if (!rb.samples) + { + return false; + } rb.frame_count = frame_count; rb.sample_count = RB_CHANNEL_COUNT * frame_count; rb.read_head = 0; rb.write_head = 0; rb.oversampling = false; + return true; } inline void RB_Free(ringbuffer_t& rb) diff --git a/src/submcu.cpp b/src/submcu.cpp index db0d040c..e26350e4 100644 --- a/src/submcu.cpp +++ b/src/submcu.cpp @@ -308,7 +308,13 @@ void SM_SetStatus(submcu_t& sm, uint32_t condition, uint32_t mask) sm.sr &= ~mask; } -void SM_Reset(submcu_t& sm, mcu_t& mcu) +void SM_Init(submcu_t& sm, mcu_t& mcu) +{ + memset(&sm, 0, sizeof(submcu_t)); + sm.mcu = &mcu; +} + +void SM_Reset(submcu_t& sm) { sm.pc = SM_GetVectorAddress(sm, SM_VECTOR_RESET); sm.a = 0; @@ -318,24 +324,6 @@ void SM_Reset(submcu_t& sm, mcu_t& mcu) sm.sr = 0; sm.cycles = 0; sm.sleep = 0; - sm.mcu = &mcu; - - memset(sm.sm_ram, 0, sizeof(sm.sm_ram)); - memset(sm.sm_shared_ram, 0, sizeof(sm.sm_shared_ram)); - memset(sm.sm_access, 0, sizeof(sm.sm_access)); - - sm.sm_p0_dir = 0; - sm.sm_p1_dir = 0; - - memset(sm.sm_device_mode, 0, sizeof(sm.sm_device_mode)); - - sm.sm_cts = 0; - - sm.sm_timer_cycles = 0; - sm.sm_timer_prescaler = 0; - sm.sm_timer_counter = 0; - - sm.uart_rx_gotbyte = 0; } uint8_t SM_ReadAdvance(submcu_t& sm) diff --git a/src/submcu.h b/src/submcu.h index c8121f85..eaf86a81 100644 --- a/src/submcu.h +++ b/src/submcu.h @@ -76,7 +76,8 @@ struct submcu_t { uint8_t uart_rx_gotbyte; }; -void SM_Reset(submcu_t& sm, mcu_t& mcu); +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); From 6a5255e94543b641217f126ea1e3d5f13f4969e2 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Wed, 1 May 2024 05:45:27 -0400 Subject: [PATCH 25/35] Remove lcd_init It is not always zero when LCD_Init is called with memory from malloc() --- src/lcd.cpp | 10 +--------- src/lcd.h | 2 -- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/lcd.cpp b/src/lcd.cpp index 4dfea5dc..66b44f98 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -211,9 +211,6 @@ void LCD_LoadBack(lcd_t& lcd, const std::string& path) bool LCD_Init(lcd_t& lcd, mcu_t& mcu) { - if (lcd.lcd_init) - return false; - memset(&lcd, 0, sizeof(lcd_t)); lcd.mcu = &mcu; @@ -245,14 +242,12 @@ bool LCD_Init(lcd_t& lcd, mcu_t& mcu) if (!lcd.texture) return false; - lcd.lcd_init = 1; return true; } void LCD_UnInit(lcd_t& lcd) { - if (!lcd.lcd_init) - return; + (void)lcd; } uint32_t lcd_col1 = 0x000000; @@ -396,9 +391,6 @@ void LCD_FontRenderLR(lcd_t& lcd, uint8_t ch) void LCD_Update(lcd_t& lcd) { - if (!lcd.lcd_init) - return; - if (!lcd.mcu->mcu_cm300 && !lcd.mcu->mcu_st && !lcd.mcu->mcu_scb55) { MCU_WorkThread_Lock(*lcd.mcu); diff --git a/src/lcd.h b/src/lcd.h index 442831f3..b90e4414 100644 --- a/src/lcd.h +++ b/src/lcd.h @@ -51,8 +51,6 @@ struct lcd_t { int lcd_width; int lcd_height; - uint32_t lcd_init; - 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; From aa214cec74a55e524e84093da10ba5373c86b1f6 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Wed, 1 May 2024 05:46:58 -0400 Subject: [PATCH 26/35] Remove global state from rom loader This allows roms to be loaded on multiple threads simultaneously. --- src/emu.cpp | 86 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 34 deletions(-) diff --git a/src/emu.cpp b/src/emu.cpp index 8183e071..4bc85302 100644 --- a/src/emu.cpp +++ b/src/emu.cpp @@ -174,8 +174,6 @@ const char* roms[ROM_SET_COUNT][5] = "rom_sm.bin", }; -uint8_t tempbuf[0x800000]; - void unscramble(uint8_t *src, uint8_t *dst, int len) { for (int i = 0; i < len; i++) @@ -203,26 +201,6 @@ void unscramble(uint8_t *src, uint8_t *dst, int len) } } -static const size_t rf_num = 5; -static FILE *s_rf[rf_num] = -{ - nullptr, - nullptr, - nullptr, - nullptr, - nullptr -}; - -static void closeAllR() -{ - for(size_t i = 0; i < rf_num; ++i) - { - if(s_rf[i]) - fclose(s_rf[i]); - s_rf[i] = nullptr; - } -} - int EMU_DetectRomset(const std::string& basePath) { for (size_t i = 0; i < ROM_SET_COUNT; i++) @@ -249,8 +227,36 @@ int EMU_DetectRomset(const std::string& basePath) return ROM_SET_MK2; } +void EMU_CloseAll(FILE** files, size_t count) +{ + for (size_t i = 0; i < count; ++i) + { + if (files[i]) + fclose(files[i]); + files[i] = nullptr; + } +} + bool EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) { + uint8_t* tempbuf = (uint8_t*)malloc(0x800000); + if (!tempbuf) + { + fprintf(stderr, "FATAL ERROR: Failed to allocate tempbuf\n"); + fflush(stderr); + return false; + } + + const size_t rf_num = 5; + FILE *s_rf[rf_num] = + { + nullptr, + nullptr, + nullptr, + nullptr, + nullptr + }; + emu.mcu->romset = romset; emu.mcu->mcu_mk1 = false; emu.mcu->mcu_cm300 = false; @@ -318,7 +324,8 @@ bool EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) { fprintf(stderr, "FATAL ERROR: One of required data ROM files is missing: %s.\n", errors_list.c_str()); fflush(stderr); - closeAllR(); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); return false; } @@ -326,7 +333,8 @@ bool EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) { fprintf(stderr, "FATAL ERROR: Failed to read the mcu ROM1.\n"); fflush(stderr); - closeAllR(); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); return false; } @@ -340,7 +348,8 @@ bool EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) { fprintf(stderr, "FATAL ERROR: Failed to read the mcu ROM2.\n"); fflush(stderr); - closeAllR(); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); return false; } @@ -350,7 +359,8 @@ bool EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) { fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom1.\n"); fflush(stderr); - closeAllR(); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); return false; } @@ -360,7 +370,8 @@ bool EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) { fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom2.\n"); fflush(stderr); - closeAllR(); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); return false; } @@ -370,7 +381,8 @@ bool EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) { fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom3.\n"); fflush(stderr); - closeAllR(); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); return false; } @@ -382,7 +394,8 @@ bool EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) { fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom1.\n"); fflush(stderr); - closeAllR(); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); return false; } @@ -392,7 +405,8 @@ bool EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) { fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom2.\n"); fflush(stderr); - closeAllR(); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); return false; } @@ -409,7 +423,8 @@ bool EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) { fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom1.\n"); fflush(stderr); - closeAllR(); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); return false; } @@ -421,7 +436,8 @@ bool EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) { fprintf(stderr, "FATAL ERROR: Failed to read the WaveRom2.\n"); fflush(stderr); - closeAllR(); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); return false; } @@ -432,13 +448,15 @@ bool EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) { fprintf(stderr, "FATAL ERROR: Failed to read the sub mcu ROM.\n"); fflush(stderr); - closeAllR(); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); return false; } } // Close all files as they no longer needed being open - closeAllR(); + EMU_CloseAll(s_rf, rf_num); + free(tempbuf); return true; } From 109fa7f70c0273ad64585d198f84f1a60256deb9 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Wed, 1 May 2024 05:47:49 -0400 Subject: [PATCH 27/35] Check EMU_Init return --- src/main_frontend.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main_frontend.cpp b/src/main_frontend.cpp index 22993372..43e765ce 100644 --- a/src/main_frontend.cpp +++ b/src/main_frontend.cpp @@ -378,7 +378,11 @@ bool FE_CreateInstance(frontend_t& container, const std::string& basePath, int r return false; } - EMU_Init(fe->emu); + if (!EMU_Init(fe->emu)) + { + fprintf(stderr, "ERROR: Failed to init emulator.\n"); + return false; + } // TODO: Clean up, shouldn't need to reach into emu for this fe->emu.mcu->callback_userdata = fe; fe->emu.mcu->step_begin_callback = FE_StepBegin; From 4059d320c10673e25fd4aeb8489adee785f87c69 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Wed, 1 May 2024 05:50:48 -0400 Subject: [PATCH 28/35] Add license headers --- src/emu.cpp | 33 +++++++++++++++++++++++++++++++++ src/emu.h | 33 +++++++++++++++++++++++++++++++++ src/math_util.h | 33 +++++++++++++++++++++++++++++++++ src/ringbuffer.h | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 132 insertions(+) diff --git a/src/emu.cpp b/src/emu.cpp index 4bc85302..2b43b220 100644 --- a/src/emu.cpp +++ b/src/emu.cpp @@ -1,3 +1,36 @@ +/* + * 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" diff --git a/src/emu.h b/src/emu.h index bf442226..ca335703 100644 --- a/src/emu.h +++ b/src/emu.h @@ -1,3 +1,36 @@ +/* + * 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 diff --git a/src/math_util.h b/src/math_util.h index 16ed468f..5e1847c4 100644 --- a/src/math_util.h +++ b/src/math_util.h @@ -1,3 +1,36 @@ +/* + * 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 diff --git a/src/ringbuffer.h b/src/ringbuffer.h index 3f43a8ee..53bcbbd8 100644 --- a/src/ringbuffer.h +++ b/src/ringbuffer.h @@ -1,3 +1,36 @@ +/* + * 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 From 75836b351afaca102f9c60ea8bd8b3b424a935fc Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Wed, 1 May 2024 06:23:10 -0400 Subject: [PATCH 29/35] Shorten emu_backend_t to emu_t --- src/emu.cpp | 10 +++++----- src/emu.h | 10 +++++----- src/main_frontend.cpp | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/emu.cpp b/src/emu.cpp index 2b43b220..b2fddc27 100644 --- a/src/emu.cpp +++ b/src/emu.cpp @@ -39,9 +39,9 @@ #include "pcm.h" #include "utils/files.h" -bool EMU_Init(emu_backend_t& emu) +bool EMU_Init(emu_t& emu) { - memset(&emu, 0, sizeof(emu_backend_t)); + memset(&emu, 0, sizeof(emu_t)); emu.mcu = (mcu_t*)malloc(sizeof(mcu_t)); if (!emu.mcu) @@ -98,7 +98,7 @@ bool EMU_Init(emu_backend_t& emu) return true; } -void EMU_Free(emu_backend_t& emu) +void EMU_Free(emu_t& emu) { if (emu.lcd) { @@ -131,7 +131,7 @@ void EMU_Free(emu_backend_t& emu) } } -void EMU_Reset(emu_backend_t& emu) +void EMU_Reset(emu_t& emu) { MCU_PatchROM(*emu.mcu); MCU_Reset(*emu.mcu); @@ -270,7 +270,7 @@ void EMU_CloseAll(FILE** files, size_t count) } } -bool EMU_LoadRoms(emu_backend_t& emu, int romset, const std::string& basePath) +bool EMU_LoadRoms(emu_t& emu, int romset, const std::string& basePath) { uint8_t* tempbuf = (uint8_t*)malloc(0x800000); if (!tempbuf) diff --git a/src/emu.h b/src/emu.h index ca335703..94a5499e 100644 --- a/src/emu.h +++ b/src/emu.h @@ -41,7 +41,7 @@ struct mcu_timer_t; struct lcd_t; struct pcm_t; -struct emu_backend_t { +struct emu_t { mcu_t* mcu; submcu_t* sm; mcu_timer_t* timer; @@ -49,12 +49,12 @@ struct emu_backend_t { pcm_t* pcm; }; -bool EMU_Init(emu_backend_t& emu); -void EMU_Free(emu_backend_t& emu); +bool EMU_Init(emu_t& emu); +void EMU_Free(emu_t& emu); // Should be called after loading roms -void EMU_Reset(emu_backend_t& emu); +void EMU_Reset(emu_t& emu); int EMU_DetectRomset(const std::string& basePath); -bool EMU_LoadRoms(emu_backend_t& emu, int romset, 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/main_frontend.cpp b/src/main_frontend.cpp index 43e765ce..77340c9a 100644 --- a/src/main_frontend.cpp +++ b/src/main_frontend.cpp @@ -55,9 +55,9 @@ #endif struct fe_emu_instance_t { - emu_backend_t emu; - ringbuffer_t sample_buffer; - SDL_Thread* thread; + emu_t emu; + ringbuffer_t sample_buffer; + SDL_Thread* thread; }; const size_t FE_MAX_INSTANCES = 16; From 51e204efd6ca302f92447ee1a644836daaf2d26c Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Wed, 1 May 2024 19:07:11 -0400 Subject: [PATCH 30/35] Fix race condition that was causing UB The midi input callback might be invoked after MIDI_Quit(). If this happens, midi_frontend is null and is not valid for FE_RouteMidi. --- src/midi_win32.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/midi_win32.cpp b/src/midi_win32.cpp index 836f8007..21e2c0ad 100644 --- a/src/midi_win32.cpp +++ b/src/midi_win32.cpp @@ -94,7 +94,15 @@ 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) { From 6d2a6c62813499e107ec1754519eb9343e320360 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Wed, 1 May 2024 20:00:39 -0400 Subject: [PATCH 31/35] Remove work_thread_run global Missed this one, this state is now part of fe_emu_instance_t. --- src/main_frontend.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main_frontend.cpp b/src/main_frontend.cpp index 77340c9a..5930fa4c 100644 --- a/src/main_frontend.cpp +++ b/src/main_frontend.cpp @@ -58,6 +58,7 @@ struct fe_emu_instance_t { emu_t emu; ringbuffer_t sample_buffer; SDL_Thread* thread; + bool running; }; const size_t FE_MAX_INSTANCES = 16; @@ -80,6 +81,7 @@ bool FE_AllocateInstance(frontend_t& container, fe_emu_instance_t** result) } 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) @@ -300,18 +302,16 @@ void MIDI_Reset(mcu_t& mcu, ResetType resetType) } -static bool work_thread_run = false; - -int SDLCALL FE_RunMCU(void* data) +int SDLCALL FE_RunInstance(void* userdata) { - mcu_t& mcu = *(mcu_t*)data; + fe_emu_instance_t& instance = *(fe_emu_instance_t*)userdata; - MCU_WorkThread_Lock(mcu); - while (work_thread_run) + MCU_WorkThread_Lock(*instance.emu.mcu); + while (instance.running) { - MCU_Step(mcu); + MCU_Step(*instance.emu.mcu); } - MCU_WorkThread_Unlock(mcu); + MCU_WorkThread_Unlock(*instance.emu.mcu); return 0; } @@ -320,11 +320,10 @@ void FE_Run(frontend_t& fe) { bool working = true; - work_thread_run = true; - for (size_t i = 0; i < fe.instances_in_use; ++i) { - fe.instances[i].thread = SDL_CreateThread(FE_RunMCU, "work thread", fe.instances[i].emu.mcu); + fe.instances[i].running = true; + fe.instances[i].thread = SDL_CreateThread(FE_RunInstance, "work thread", &fe.instances[i]); } while (working) @@ -349,9 +348,9 @@ void FE_Run(frontend_t& fe) SDL_Delay(15); } - work_thread_run = false; for (size_t i = 0; i < fe.instances_in_use; ++i) { + fe.instances[i].running = false; SDL_WaitThread(fe.instances[i].thread, 0); } } @@ -406,6 +405,7 @@ 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) From 43a09ffc2acab3d05157153f348207e1ee69c1e2 Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Wed, 1 May 2024 20:30:43 -0400 Subject: [PATCH 32/35] Finalize callback situation begin_step and wait callbacks are needlessly complicated, and controlling how often to step the MCU is really the responsibility of the frontend. These two callbacks have been removed and the logic baked into FE_RunInstance. The sample callback is fine since it provides a zero-copy way to get sample data out of the emulator. --- src/emu.cpp | 6 ++++++ src/emu.h | 4 +++- src/main_frontend.cpp | 30 +++++++++++++----------------- src/mcu.cpp | 19 +++++++------------ src/mcu.h | 5 ----- 5 files changed, 29 insertions(+), 35 deletions(-) diff --git a/src/emu.cpp b/src/emu.cpp index b2fddc27..105b16ac 100644 --- a/src/emu.cpp +++ b/src/emu.cpp @@ -138,6 +138,12 @@ void EMU_Reset(emu_t& emu) 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", diff --git a/src/emu.h b/src/emu.h index 94a5499e..8ea99146 100644 --- a/src/emu.h +++ b/src/emu.h @@ -33,9 +33,9 @@ */ #pragma once +#include "mcu.h" #include -struct mcu_t; struct submcu_t; struct mcu_timer_t; struct lcd_t; @@ -55,6 +55,8 @@ 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/main_frontend.cpp b/src/main_frontend.cpp index 5930fa4c..093155f9 100644 --- a/src/main_frontend.cpp +++ b/src/main_frontend.cpp @@ -130,18 +130,6 @@ void FE_RouteMIDI(frontend_t& fe, uint8_t* first, uint8_t* last) } } -void FE_StepBegin(void* userdata) -{ - fe_emu_instance_t& fe = *(fe_emu_instance_t*)userdata; - RB_SetOversamplingEnabled(fe.sample_buffer, fe.emu.pcm->config_reg_3c & 0x40); -} - -bool FE_Wait(void* userdata) -{ - fe_emu_instance_t& fe = *(fe_emu_instance_t*)userdata; - return RB_IsFull(fe.sample_buffer); -} - void FE_ReceiveSample(void* userdata, int *sample) { fe_emu_instance_t& fe = *(fe_emu_instance_t*)userdata; @@ -309,6 +297,17 @@ int SDLCALL FE_RunInstance(void* 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); @@ -382,11 +381,8 @@ bool FE_CreateInstance(frontend_t& container, const std::string& basePath, int r fprintf(stderr, "ERROR: Failed to init emulator.\n"); return false; } - // TODO: Clean up, shouldn't need to reach into emu for this - fe->emu.mcu->callback_userdata = fe; - fe->emu.mcu->step_begin_callback = FE_StepBegin; - fe->emu.mcu->sample_callback = FE_ReceiveSample; - fe->emu.mcu->wait_callback = FE_Wait; + + EMU_SetSampleCallback(fe->emu, FE_ReceiveSample, fe); LCD_LoadBack(*fe->emu.lcd, basePath + "/back.data"); diff --git a/src/mcu.cpp b/src/mcu.cpp index 48f3c43b..e27d1d71 100644 --- a/src/mcu.cpp +++ b/src/mcu.cpp @@ -765,6 +765,12 @@ void MCU_ReadInstruction(mcu_t& mcu) } } +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)); @@ -775,6 +781,7 @@ bool MCU_Init(mcu_t& mcu, submcu_t& sm, pcm_t& pcm, mcu_timer_t& timer, lcd_t& l 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) { @@ -878,18 +885,6 @@ void MCU_WorkThread_Unlock(mcu_t& mcu) void MCU_Step(mcu_t& mcu) { - mcu.step_begin_callback(mcu.callback_userdata); - - if (mcu.wait_callback(mcu.callback_userdata)) - { - MCU_WorkThread_Unlock(mcu); - while (mcu.wait_callback(mcu.callback_userdata)) - { - SDL_Delay(1); - } - MCU_WorkThread_Lock(mcu); - } - if (!mcu.ex_ignore) MCU_Interrupt_Handle(mcu); else diff --git a/src/mcu.h b/src/mcu.h index 9ed872de..2921dca1 100644 --- a/src/mcu.h +++ b/src/mcu.h @@ -188,9 +188,7 @@ static const int ROMSM_SIZE = 0x1000; static const uint32_t uart_buffer_size = 8192; -typedef void(*mcu_step_begin_callback)(void* userdata); typedef void(*mcu_sample_callback)(void* userdata, int* sample); -typedef bool(*mcu_wait_callback)(void* userdata); struct mcu_t { uint16_t r[8]; @@ -268,9 +266,6 @@ struct mcu_t { uint8_t opcode_extended; void* callback_userdata; - mcu_step_begin_callback step_begin_callback; - // if FE doesn't need more samples, returns true to signal for the mcu to wait - mcu_wait_callback wait_callback; mcu_sample_callback sample_callback; SDL_mutex *work_thread_lock; From 5166d2ec8de90bf675985a6953fc6bc4104b79fd Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Wed, 1 May 2024 20:49:02 -0400 Subject: [PATCH 33/35] Fix UAF freeing things in the wrong order --- src/main_frontend.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main_frontend.cpp b/src/main_frontend.cpp index 093155f9..5f3c2674 100644 --- a/src/main_frontend.cpp +++ b/src/main_frontend.cpp @@ -257,11 +257,6 @@ bool FE_OpenAudio(frontend_t& fe, int deviceIndex, int pageSize, int pageNum) return true; } -void FE_CloseAudio(void) -{ - SDL_CloseAudio(); -} - enum class ResetType { NONE, GS_RESET, @@ -406,11 +401,14 @@ void FE_DestroyInstance(fe_emu_instance_t& fe) 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]); } - FE_CloseAudio(); MIDI_Quit(); SDL_Quit(); } From 47335507403d981e5522815e71effc06fe64424c Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Sun, 5 May 2024 03:34:09 -0400 Subject: [PATCH 34/35] Work in frames instead of samples --- src/main_frontend.cpp | 23 +++++++--------- src/ringbuffer.h | 64 ++++++++++++++++++++----------------------- 2 files changed, 40 insertions(+), 47 deletions(-) diff --git a/src/main_frontend.cpp b/src/main_frontend.cpp index 5f3c2674..7e8aea98 100644 --- a/src/main_frontend.cpp +++ b/src/main_frontend.cpp @@ -134,37 +134,34 @@ void FE_ReceiveSample(void* userdata, int *sample) { fe_emu_instance_t& fe = *(fe_emu_instance_t*)userdata; 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; - RB_Write(fe.sample_buffer, sample[0], sample[1]); + + 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_samples = len / sizeof(int16_t); + const size_t num_frames = len / sizeof(audio_frame_t); memset(stream, 0, len); - size_t renderable_count = num_samples; + size_t renderable_count = num_frames; for (size_t i = 0; i < frontend.instances_in_use; ++i) { renderable_count = min( renderable_count, - RB_ReadableSampleCount(frontend.instances[i].sample_buffer) + 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, (int16_t*)stream, renderable_count); + RB_ReadMix(frontend.instances[i].sample_buffer, (audio_frame_t*)stream, renderable_count); } } diff --git a/src/ringbuffer.h b/src/ringbuffer.h index 53bcbbd8..a51b9beb 100644 --- a/src/ringbuffer.h +++ b/src/ringbuffer.h @@ -38,12 +38,14 @@ #include #include "math_util.h" -const int RB_CHANNEL_COUNT = 2; +struct audio_frame_t { + int16_t left; + int16_t right; +}; struct ringbuffer_t { - int16_t* samples; + audio_frame_t* frames; size_t frame_count; - size_t sample_count; size_t read_head; size_t write_head; bool oversampling; @@ -51,13 +53,12 @@ struct ringbuffer_t { inline bool RB_Init(ringbuffer_t& rb, size_t frame_count) { - rb.samples = (int16_t*)calloc(RB_CHANNEL_COUNT * frame_count, sizeof(int16_t)); - if (!rb.samples) + rb.frames = (audio_frame_t*)calloc(frame_count, sizeof(audio_frame_t)); + if (!rb.frames) { return false; } rb.frame_count = frame_count; - rb.sample_count = RB_CHANNEL_COUNT * frame_count; rb.read_head = 0; rb.write_head = 0; rb.oversampling = false; @@ -66,17 +67,13 @@ inline bool RB_Init(ringbuffer_t& rb, size_t frame_count) inline void RB_Free(ringbuffer_t& rb) { - free(rb.samples); + free(rb.frames); } inline void RB_SetOversamplingEnabled(ringbuffer_t& rb, bool enabled) { rb.oversampling = enabled; if (rb.oversampling) - { - rb.write_head &= ~3; - } - else { rb.write_head &= ~1; } @@ -86,22 +83,21 @@ inline bool RB_IsFull(ringbuffer_t& rb) { if (rb.oversampling) { - return ((rb.write_head + 2 * RB_CHANNEL_COUNT) % rb.sample_count) == rb.read_head; + return ((rb.write_head + 2) % rb.frame_count) == rb.read_head; } else { - return ((rb.write_head + 1 * RB_CHANNEL_COUNT) % rb.sample_count) == rb.read_head; + return ((rb.write_head + 1) % rb.frame_count) == rb.read_head; } } -inline void RB_Write(ringbuffer_t& rb, int16_t left, int16_t right) +inline void RB_Write(ringbuffer_t& rb, const audio_frame_t& frame) { - rb.samples[rb.write_head + 0] = left; - rb.samples[rb.write_head + 1] = right; - rb.write_head = (rb.write_head + RB_CHANNEL_COUNT) % rb.sample_count; + rb.frames[rb.write_head] = frame; + rb.write_head = (rb.write_head + 1) % rb.frame_count; } -inline size_t RB_ReadableSampleCount(ringbuffer_t& rb) +inline size_t RB_ReadableFrameCount(ringbuffer_t& rb) { if (rb.read_head <= rb.write_head) { @@ -109,40 +105,40 @@ inline size_t RB_ReadableSampleCount(ringbuffer_t& rb) } else { - return rb.sample_count - (rb.read_head - rb.write_head); + return rb.frame_count - (rb.read_head - rb.write_head); } } -// Reads up to `sample_count` samples and returns the number of samples -// actually read. -inline size_t RB_Read(ringbuffer_t& rb, int16_t* dest, size_t sample_count) +// 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) { - size_t have_count = RB_ReadableSampleCount(rb); - size_t read_count = sample_count < have_count ? sample_count : have_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.samples[read_head]; + *dest = rb.frames[read_head]; ++dest; - read_head = (read_head + 1) % rb.sample_count; + read_head = (read_head + 1) % rb.frame_count; } rb.read_head = read_head; return read_count; } -// Reads up to `sample_count` samples and returns the number of samples -// actually read. Mixes samples into dest by adding and clipping. -inline size_t RB_ReadMix(ringbuffer_t& rb, int16_t* dest, size_t sample_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) { - size_t have_count = RB_ReadableSampleCount(rb); - size_t read_count = sample_count < have_count ? sample_count : have_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 = saturating_add(*dest, rb.samples[read_head]); - ++dest; - read_head = (read_head + 1) % rb.sample_count; + 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; From ca10a5583730a9b73602b966960905e04582d76f Mon Sep 17 00:00:00 2001 From: "J.C. Moyer" Date: Fri, 24 May 2024 20:10:05 -0400 Subject: [PATCH 35/35] Create window after loading roms --- src/emu.cpp | 8 +------- src/lcd.cpp | 25 +++++++++++++++++++++---- src/lcd.h | 3 ++- src/main_frontend.cpp | 6 ++++++ 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/emu.cpp b/src/emu.cpp index 105b16ac..24c4b422 100644 --- a/src/emu.cpp +++ b/src/emu.cpp @@ -87,13 +87,7 @@ bool EMU_Init(emu_t& emu) SM_Init(*emu.sm, *emu.mcu); PCM_Init(*emu.pcm, *emu.mcu); TIMER_Init(*emu.timer, *emu.mcu); - - // TODO: LCD should be optional for use with other frontends - if (!LCD_Init(*emu.lcd, *emu.mcu)) - { - EMU_Free(emu); - return false; - } + LCD_Init(*emu.lcd, *emu.mcu); return true; } diff --git a/src/lcd.cpp b/src/lcd.cpp index 66b44f98..10332305 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -209,12 +209,15 @@ void LCD_LoadBack(lcd_t& lcd, const std::string& path) fclose(raw); } -bool LCD_Init(lcd_t& lcd, mcu_t& mcu) +void LCD_Init(lcd_t& lcd, mcu_t& mcu) { memset(&lcd, 0, sizeof(lcd_t)); lcd.mcu = &mcu; +} - if (mcu.romset == ROM_SET_JV880) +bool LCD_CreateWindow(lcd_t& lcd) +{ + if (lcd.mcu->romset == ROM_SET_JV880) { lcd.lcd_width = 820; lcd.lcd_height = 100; @@ -227,7 +230,7 @@ bool LCD_Init(lcd_t& lcd, mcu_t& mcu) std::string title = "Nuked SC-55: "; - title += EMU_RomsetName(mcu.romset); + title += EMU_RomsetName(lcd.mcu->romset); 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) @@ -247,7 +250,21 @@ bool LCD_Init(lcd_t& lcd, mcu_t& mcu) void LCD_UnInit(lcd_t& lcd) { - (void)lcd; + 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; diff --git a/src/lcd.h b/src/lcd.h index b90e4414..c3bd7682 100644 --- a/src/lcd.h +++ b/src/lcd.h @@ -70,7 +70,8 @@ struct lcd_t { void LCD_LoadBack(lcd_t& lcd, const std::string& path); -bool LCD_Init(lcd_t& lcd, mcu_t& mcu); +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); diff --git a/src/main_frontend.cpp b/src/main_frontend.cpp index 7e8aea98..59c560ce 100644 --- a/src/main_frontend.cpp +++ b/src/main_frontend.cpp @@ -385,6 +385,12 @@ bool FE_CreateInstance(frontend_t& container, const std::string& basePath, int r } EMU_Reset(fe->emu); + if (!LCD_CreateWindow(*fe->emu.lcd)) + { + fprintf(stderr, "ERROR: Failed to create window.\n"); + return false; + } + return true; }