diff --git a/Assets/dll/virtualjaguar.wbx.zst b/Assets/dll/virtualjaguar.wbx.zst index 6754c9057d..1ddde9803d 100644 Binary files a/Assets/dll/virtualjaguar.wbx.zst and b/Assets/dll/virtualjaguar.wbx.zst differ diff --git a/waterbox/virtualjaguar/BizInterface.cpp b/waterbox/virtualjaguar/BizInterface.cpp index 856629eedf..ea89ea087c 100644 --- a/waterbox/virtualjaguar/BizInterface.cpp +++ b/waterbox/virtualjaguar/BizInterface.cpp @@ -88,9 +88,13 @@ EXPORT void SetCdCallbacks(void (*ctc)(void * dest), void (*cdrc)(int32_t lba, v cd_read_callback = cdrc; } -EXPORT void InitWithCd(BizSettings* bizSettings, u8* boot) +EXPORT void InitWithCd(BizSettings* bizSettings, u8* boot, u8* memtrack) { InitCommon(bizSettings); + if (memtrack) + { + JaguarLoadFile(memtrack, 0x20000); + } vjs.hardwareTypeAlpine = false; SET32(jaguarMainRAM, 0, 0x00200000); @@ -99,24 +103,50 @@ EXPORT void InitWithCd(BizSettings* bizSettings, u8* boot) JaguarReset(); } +// standard cart eeprom extern u16 eeprom_ram[64]; extern bool eeprom_dirty; +// memtrack ram (used for jagcd) +extern u8 mtMem[0x20000]; +extern bool mtDirty; + +static inline bool IsMemTrack() +{ + return jaguarMainROMCRC32 == 0xFDF37F47; +} + EXPORT bool SaveRamIsDirty() { - return eeprom_dirty; + return IsMemTrack() ? mtDirty : eeprom_dirty; } EXPORT void GetSaveRam(u8* dst) { - memcpy(dst, eeprom_ram, sizeof(eeprom_ram)); - eeprom_dirty = false; + if (IsMemTrack()) + { + memcpy(dst, mtMem, sizeof(mtMem)); + mtDirty = false; + } + else + { + memcpy(dst, eeprom_ram, sizeof(eeprom_ram)); + eeprom_dirty = false; + } } EXPORT void PutSaveRam(u8* src) { - memcpy(eeprom_ram, src, sizeof(eeprom_ram)); - eeprom_dirty = false; + if (IsMemTrack()) + { + memcpy(mtMem, src, sizeof(mtMem)); + mtDirty = false; + } + else + { + memcpy(eeprom_ram, src, sizeof(eeprom_ram)); + eeprom_dirty = false; + } } extern u8 gpu_ram_8[0x1000]; @@ -173,10 +203,20 @@ EXPORT void GetMemoryAreas(MemoryArea* m) m[0].Size = 0x200000; m[0].Flags = MEMORYAREA_FLAGS_WORDSIZE2 | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_YUGEENDIAN | MEMORYAREA_FLAGS_PRIMARY; - m[1].Data = eeprom_ram; - m[1].Name = "EEPROM"; - m[1].Size = sizeof(eeprom_ram); - m[1].Flags = MEMORYAREA_FLAGS_WORDSIZE2 | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_YUGEENDIAN | MEMORYAREA_FLAGS_SAVERAMMABLE; + if (IsMemTrack()) + { + m[1].Data = mtMem; + m[1].Name = "MEMTRACK RAM"; + m[1].Size = sizeof(mtMem); + m[1].Flags = MEMORYAREA_FLAGS_WORDSIZE2 | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_YUGEENDIAN | MEMORYAREA_FLAGS_SAVERAMMABLE; + } + else + { + m[1].Data = jaguarCartInserted ? eeprom_ram : NULL; + m[1].Name = "EEPROM"; + m[1].Size = sizeof(eeprom_ram); + m[1].Flags = MEMORYAREA_FLAGS_WORDSIZE2 | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_YUGEENDIAN | MEMORYAREA_FLAGS_SAVERAMMABLE; + } m[2].Data = gpu_ram_8; m[2].Name = "GPU RAM"; @@ -291,14 +331,11 @@ void (*ReadCallback)(u32) = 0; void (*WriteCallback)(u32) = 0; void (*ExecuteCallback)(u32) = 0; -EXPORT void SetMemoryCallback(u32 which, void (*callback)(u32)) +EXPORT void SetMemoryCallbacks(void (*rcb)(u32), void (*wcb)(u32), void (*ecb)(u32)) { - switch (which) - { - case 0: ReadCallback = callback; break; - case 1: WriteCallback = callback; break; - case 2: ExecuteCallback = callback; break; - } + ReadCallback = rcb; + WriteCallback = wcb; + ExecuteCallback = ecb; } void (*CPUTraceCallback)(u32*) = 0; diff --git a/waterbox/virtualjaguar/src/cdhle.cpp b/waterbox/virtualjaguar/src/cdhle.cpp index 7bf0ae8369..dbd2a34dd1 100644 --- a/waterbox/virtualjaguar/src/cdhle.cpp +++ b/waterbox/virtualjaguar/src/cdhle.cpp @@ -3,6 +3,9 @@ #include "memory.h" #include "jaguar.h" #include "jerry.h" +#include "tom.h" +#include "dac.h" +#include "dsp.h" #include "event.h" #include "m68000/m68kinterface.h" @@ -21,6 +24,7 @@ static bool cd_setup; static bool cd_initm; static bool cd_muted; static bool cd_paused; +bool cd_jerry; static uint8_t cd_mode; static uint8_t cd_osamp; @@ -144,9 +148,20 @@ void CDHLEReset(void) cd_initm = false; cd_muted = false; cd_paused = false; + cd_jerry = false; cd_mode = 0; cd_osamp = 0; + cd_is_reading = false; + cd_read_orig_addr_start = 0; + cd_read_addr_start = 0; + cd_read_addr_end = 0; + cd_read_lba = 0; + memset(cd_buf2352, 0, sizeof(cd_buf2352)); + cd_buf_pos = 0; + cd_buf_rm = 0; + cd_buf_circular_size = 0; + if (cd_read_callback) { // copy TOC to RAM @@ -208,6 +223,12 @@ void CDHLEReset(void) SET32(jaguarMainRAM, 4, cd_boot_addr); SET16(jaguarMainRAM, 0x3004, 0x0403); // BIOS VER + DACWriteByte(0xF1A153, 9); // set SCLK to 9 + if (jaguarMainROMCRC32 == 0xFDF37F47) + { + TOMWriteWord(0xF00000, (TOMGetMEMCON1() & ~6u) | 4); // set ROM width to 32 bit + memcpy(&jaguarMainRAM[0x2400], &jaguarMainROM[0x6D60], 0x790); // copy memtrack "bios" to ram + } } } @@ -215,58 +236,35 @@ void CDHLEDone(void) { } -static void CDSendBlock(void) +static void RefillCDBuf() { - if (cd_buf_rm < 64) - { - memmove(&cd_buf2352[0], &cd_buf2352[cd_buf_pos], cd_buf_rm); - cd_read_callback(cd_read_lba++, &cd_buf2352[cd_buf_rm]); + memmove(&cd_buf2352[0], &cd_buf2352[cd_buf_pos], cd_buf_rm); + cd_read_callback(cd_read_lba++, &cd_buf2352[cd_buf_rm]); - // hack to force word alignment - if (cd_word_alignment) + // hack to force word alignment + if (cd_word_alignment) + { + uint8_t temp2352[2352]; + cd_read_callback(cd_read_lba, temp2352); + memmove(&cd_buf2352[cd_buf_rm], &cd_buf2352[cd_buf_rm + cd_word_alignment], 2352 - cd_word_alignment); + memcpy(&cd_buf2352[cd_buf_rm + 2352 - cd_word_alignment], &temp2352[0], cd_word_alignment); + } + + if (cd_byte_swapped) + { + uint16_t* cd16buf = (uint16_t*)&cd_buf2352[cd_buf_rm]; + for (uint32_t i = 0; i < (2352 / 2); i++) { - uint8_t temp2352[2352]; - cd_read_callback(cd_read_lba, temp2352); - memmove(&cd_buf2352[cd_buf_rm], &cd_buf2352[cd_buf_rm + cd_word_alignment], 2352 - cd_word_alignment); - memcpy(&cd_buf2352[cd_buf_rm + 2352 - cd_word_alignment], &temp2352[0], cd_word_alignment); + cd16buf[i] = __builtin_bswap16(cd16buf[i]); } - - if (cd_byte_swapped) - { - uint16_t* cd16buf = (uint16_t*)&cd_buf2352[cd_buf_rm]; - for (uint32_t i = 0; i < (2352 / 2); i++) - { - cd16buf[i] = __builtin_bswap16(cd16buf[i]); - } - } - - cd_buf_pos = 0; - cd_buf_rm += 2352; } - // send one block of data, one long at a time - for (uint32_t i = 0; i < 64; i += 4) - { - GPUWriteLong(cd_read_addr_start + i, GET32(cd_buf2352, cd_buf_pos + i), GPU); - } - - cd_read_addr_start += 64; - cd_buf_pos += 64; - cd_buf_rm -= 64; - - if (cd_read_addr_start >= cd_read_addr_end) - { - cd_is_reading = false; - } - else if (cd_buf_circular_size && (cd_read_addr_start - cd_read_orig_addr_start) >= cd_buf_circular_size) - { - cd_read_addr_start = cd_read_orig_addr_start; - } + cd_buf_pos = 0; + cd_buf_rm += 2352; } static void CDHLECallback(void) { - RemoveCallback(CDHLECallback); if (cd_is_reading) { if (!GPURunning()) @@ -274,14 +272,69 @@ static void CDHLECallback(void) if (GPURunning() && !cd_paused) { - CDSendBlock(); + if (cd_buf_rm < 64) + { + RefillCDBuf(); + } + + // send one block of data, one long at a time + for (uint32_t i = 0; i < 64; i += 4) + { + GPUWriteLong(cd_read_addr_start + i, GET32(cd_buf2352, cd_buf_pos + i), GPU); + } + + cd_read_addr_start += 64; + cd_buf_pos += 64; + cd_buf_rm -= 64; + + if (cd_read_addr_start >= cd_read_addr_end) + { + cd_is_reading = false; + } + else if (cd_buf_circular_size && (cd_read_addr_start - cd_read_orig_addr_start) >= cd_buf_circular_size) + { + cd_read_addr_start = cd_read_orig_addr_start; + } + //GPUSetIRQLine(GPUIRQ_DSP, ASSERT_LINE); } + SetCallbackTime(CDHLECallback, 285 >> (cd_mode & 1)); } } -static void LoadISRStub() +// called from JERRYI2SCallback +bool CDHLEJerryCallback(void) +{ + if (!cd_is_reading || !cd_jerry || cd_paused) + { + return false; + } + + if (cd_buf_rm < 4) + { + RefillCDBuf(); + } + + DACWriteWord(0xF1A14A, GET16(cd_buf2352, cd_buf_pos + 0)); + DACWriteWord(0xF1A14E, GET16(cd_buf2352, cd_buf_pos + 2)); + + cd_buf_pos += 4; + cd_buf_rm -= 4; + + return true; +} + +static void ResetCallbacks(void) +{ + RemoveCallback(CDHLECallback); + if (!cd_jerry) + { + SetCallbackTime(CDHLECallback, 285 >> (cd_mode & 1)); + } +} + +static void LoadISRStub(void) { uint32_t isrAddr = m68k_get_reg(NULL, M68K_REG_A0); uint32_t addr = 0xF03010; @@ -373,7 +426,13 @@ static void CD_ack(void) static void CD_jeri(void) { - fprintf(stderr, "CD_jeri called %d!!!\n", m68k_get_reg(NULL, M68K_REG_D0) & 1); + bool njerry = m68k_get_reg(NULL, M68K_REG_D0) & 1; + if (cd_jerry ^ njerry) + { + fprintf(stderr, "changing jerry mode %d -> %d\n", cd_jerry, njerry); + cd_jerry = njerry; + ResetCallbacks(); + } } static void CD_spin(void) @@ -514,8 +573,7 @@ static void CD_read(void) cd_buf_pos = 0; cd_buf_rm = bufRm; cd_buf_circular_size = circBufSz ? (1 << circBufSz) : 0; - RemoveCallback(CDHLECallback); - SetCallbackTime(CDHLECallback, 285 >> (cd_mode & 1)); + ResetCallbacks(); JERRYWriteWord(0xF10020, 0, M68K); //GPUWriteLong(0xF02100, GPUReadLong(0xF02100, M68K) | 0x20, M68K); break; @@ -536,8 +594,7 @@ static void CD_read(void) cd_buf_pos = 0; cd_buf_rm = 0; cd_buf_circular_size = 0; - RemoveCallback(CDHLECallback); - SetCallbackTime(CDHLECallback, 285 >> (cd_mode & 1)); + ResetCallbacks(); JERRYWriteWord(0xF10020, 0, M68K); //GPUWriteLong(0xF02100, GPUReadLong(0xF02100, M68K) | 0x20, M68K); } diff --git a/waterbox/virtualjaguar/src/cdhle.h b/waterbox/virtualjaguar/src/cdhle.h index a9f056fad9..fea516e24b 100644 --- a/waterbox/virtualjaguar/src/cdhle.h +++ b/waterbox/virtualjaguar/src/cdhle.h @@ -8,5 +8,6 @@ void CDHLEReset(void); void CDHLEDone(void); void CDHLEHook(uint32_t which); +bool CDHLEJerryCallback(void); #endif // __CDHLE_H__ diff --git a/waterbox/virtualjaguar/src/dac.cpp b/waterbox/virtualjaguar/src/dac.cpp index 9a05bb9f1d..a868cf65cb 100644 --- a/waterbox/virtualjaguar/src/dac.cpp +++ b/waterbox/virtualjaguar/src/dac.cpp @@ -69,10 +69,8 @@ void DSPSampleCallback(void); void DACInit(void) { ltxd = lrxd = 0; - sclk = 19; - uint32_t riscClockRate = (vjs.hardwareTypeNTSC ? RISC_CLOCK_RATE_NTSC : RISC_CLOCK_RATE_PAL); - uint32_t cyclesPerSample = riscClockRate / DAC_AUDIO_RATE; + sclk = 19; } // diff --git a/waterbox/virtualjaguar/src/event.cpp b/waterbox/virtualjaguar/src/event.cpp index df08603687..2a25abe939 100644 --- a/waterbox/virtualjaguar/src/event.cpp +++ b/waterbox/virtualjaguar/src/event.cpp @@ -19,7 +19,9 @@ #include "event.h" +#include #include +#include #define EVENT_LIST_SIZE 32 @@ -145,10 +147,10 @@ double GetTimeToNextEvent(int type) { if (type == EVENT_MAIN) { - double time = eventList[0].eventTime; - nextEvent = 0; + double time = DBL_MAX; + nextEvent = EVENT_LIST_SIZE; - for(uint32_t i=1; i> 2] = (uint8_t)(data & 0xFF); + mtDirty = true; return; }