From 8be842aa43927681773c7194bc70064f95ba0177 Mon Sep 17 00:00:00 2001 From: Extrems Date: Sat, 9 May 2020 01:20:15 -0400 Subject: [PATCH] Added SD2SP2 support. Improved IDE-EXI support. Changed 16Kbit EEPROM list to use ROM ID. Updated 16Kbit EEPROM list from Project64. Updated Mupen64Plus RSP HLE plugin. --- Makefile.menu2_gc | 3 +- Makefile.menu2_wii | 3 +- fileBrowser/fileBrowser-libfat.c | 8 +- gc_memory/dma.c | 10 +- gc_memory/flashram.c | 2 +- libgui/FocusManager.cpp | 18 +- libgui/InputManager.cpp | 10 +- libgui/InputManager.h | 5 - main/ata.c | 81 +++---- main/rom.h | 3 +- main/rom_gc.c | 127 +++++------ menu/FileBrowserFrame.cpp | 13 +- menu/LoadRomFrame.cpp | 8 +- menu/MainFrame.cpp | 3 +- menu/SettingsFrame.cpp | 13 +- rsp_hle/alist.c | 12 +- rsp_hle/alist.h | 2 +- rsp_hle/alist_audio.c | 2 +- rsp_hle/alist_naudio.c | 2 +- rsp_hle/alist_nead.c | 24 ++- rsp_hle/arithmetics.h | 2 +- rsp_hle/audio.c | 2 +- rsp_hle/audio.h | 2 +- rsp_hle/cicx105.c | 2 +- rsp_hle/common.h | 2 +- rsp_hle/hle.c | 337 ++++++++++++++++------------- rsp_hle/hle.h | 2 +- rsp_hle/hle_external.h | 16 +- rsp_hle/hle_internal.h | 6 +- rsp_hle/hvqm.c | 354 +++++++++++++++++++++++++++++++ rsp_hle/jpeg.c | 4 +- rsp_hle/memory.c | 2 +- rsp_hle/memory.h | 2 +- rsp_hle/mp3.c | 2 +- rsp_hle/musyx.c | 2 +- rsp_hle/plugin.c | 17 +- rsp_hle/re2.c | 46 +++- rsp_hle/ucodes.h | 24 ++- 38 files changed, 819 insertions(+), 354 deletions(-) create mode 100644 rsp_hle/hvqm.c diff --git a/Makefile.menu2_gc b/Makefile.menu2_gc index f485f88..85899bc 100644 --- a/Makefile.menu2_gc +++ b/Makefile.menu2_gc @@ -4,7 +4,7 @@ CC =powerpc-eabi-gcc CXX =powerpc-eabi-g++ AS =powerpc-eabi-as -CFLAGS = -pipe -Ofast -Wall -mogc -flto=jobserver \ +CFLAGS = -pipe -Ofast -Wall -Wno-multichar -mogc -fgnu89-inline -flto=jobserver \ -DNGC -DRELEASE -DMENU_V2 -DGLN64_GX \ -DUSE_TLB_CACHE -DARAM_BLOCKCACHE -DARAM_TLBCACHE \ -DPPC_DYNAREC -DUSE_RECOMP_CACHE -DFASTMEM -DNDEBUG @@ -102,6 +102,7 @@ OBJ_RSPHLE =rsp_hle/alist.o \ rsp_hle/audio.o \ rsp_hle/cicx105.o \ rsp_hle/hle.o \ + rsp_hle/hvqm.o \ rsp_hle/jpeg.o \ rsp_hle/memory.o \ rsp_hle/mp3.o \ diff --git a/Makefile.menu2_wii b/Makefile.menu2_wii index cd2de07..b80817f 100644 --- a/Makefile.menu2_wii +++ b/Makefile.menu2_wii @@ -4,7 +4,7 @@ CC =powerpc-eabi-gcc CXX =powerpc-eabi-g++ AS =powerpc-eabi-as -CFLAGS = -pipe -Ofast -Wall -mrvl -flto=jobserver \ +CFLAGS = -pipe -Ofast -Wall -Wno-multichar -mrvl -fgnu89-inline -flto=jobserver \ -DWII -DRELEASE -DMENU_V2 -DGLN64_GX -DUSE_EXPANSION \ -DPPC_DYNAREC -DUSE_RECOMP_CACHE -DFASTMEM -DNDEBUG @@ -105,6 +105,7 @@ OBJ_RSPHLE =rsp_hle/alist.o \ rsp_hle/audio.o \ rsp_hle/cicx105.o \ rsp_hle/hle.o \ + rsp_hle/hvqm.o \ rsp_hle/jpeg.o \ rsp_hle/memory.o \ rsp_hle/mp3.o \ diff --git a/fileBrowser/fileBrowser-libfat.c b/fileBrowser/fileBrowser-libfat.c index eecddf3..1cf42bc 100644 --- a/fileBrowser/fileBrowser-libfat.c +++ b/fileBrowser/fileBrowser-libfat.c @@ -46,6 +46,7 @@ const DISC_INTERFACE* usbmsd = &__io_usbstorage; #endif const DISC_INTERFACE* carda = &__io_gcsda; const DISC_INTERFACE* cardb = &__io_gcsdb; +const DISC_INTERFACE* cardc = &__io_gcsd2; const DISC_INTERFACE* ideexia = &__io_ataa; const DISC_INTERFACE* ideexib = &__io_atab; @@ -53,6 +54,7 @@ const DISC_INTERFACE* ideexib = &__io_atab; #define THREAD_SLEEP 100 #define CARD_A 1 #define CARD_B 2 +#define CARD_C 3 #define FRONTSD 3 #define USBMSD 3 static lwp_t removalThread = LWP_THREAD_NULL; @@ -309,7 +311,11 @@ int fileBrowser_libfat_init(fileBrowser_file* f){ #else if(f->name[0] == 's') { if(!sdMounted) { - if(fatMountSimple ("sd", cardb)) { + if(fatMountSimple ("sd", cardc)) { + sdMounted = CARD_C; + res = 1; + } + else if(fatMountSimple ("sd", cardb)) { sdMounted = CARD_B; res = 1; } diff --git a/gc_memory/dma.c b/gc_memory/dma.c index 28997a5..10eb34a 100644 --- a/gc_memory/dma.c +++ b/gc_memory/dma.c @@ -148,7 +148,7 @@ void dma_pi_read() } longueur = (pi_register.pi_rd_len_reg & 0xFFFFFE)+2; - i = (pi_register.pi_cart_addr_reg-0x10000000)&0x3FFFFFF; + i = (pi_register.pi_cart_addr_reg-0x10000000)&0x3FFFFFE; longueur = (i + longueur) > rom_length ? (rom_length - i) : longueur; longueur = (pi_register.pi_dram_addr_reg + longueur) > MEMMASK ? @@ -162,7 +162,7 @@ void dma_pi_read() return; } - ROMCache_write(rdramb + pi_register.pi_dram_addr_reg, (pi_register.pi_cart_addr_reg-0x10000000)&0x3FFFFFF, longueur); + ROMCache_write(rdramb + pi_register.pi_dram_addr_reg, i, longueur); if(!interpcore) { @@ -197,7 +197,7 @@ void dma_pi_write() for (i=0; i<(pi_register.pi_wr_len_reg & 0xFFFFFE)+2; i++) ((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]= - sram[(((pi_register.pi_cart_addr_reg-0x08000000)&0xFFFF)+i)^S8]; + sram[(((pi_register.pi_cart_addr_reg-0x08000000)&0xFFFE)+i)^S8]; use_flashram = -1; } else @@ -226,7 +226,7 @@ void dma_pi_write() } longueur = (pi_register.pi_wr_len_reg & 0xFFFFFE)+2; - i = (pi_register.pi_cart_addr_reg-0x10000000)&0x3FFFFFF; + i = (pi_register.pi_cart_addr_reg-0x10000000)&0x3FFFFFE; longueur = (i + longueur) > rom_length ? (rom_length - i) : longueur; longueur = (pi_register.pi_dram_addr_reg + longueur) > MEMMASK ? @@ -240,7 +240,7 @@ void dma_pi_write() return; } - ROMCache_read(rdramb + pi_register.pi_dram_addr_reg, (pi_register.pi_cart_addr_reg-0x10000000)&0x3FFFFFF, longueur); + ROMCache_read(rdramb + pi_register.pi_dram_addr_reg, i, longueur); if(!interpcore) { diff --git a/gc_memory/flashram.c b/gc_memory/flashram.c index 1ac970f..e0af5c6 100644 --- a/gc_memory/flashram.c +++ b/gc_memory/flashram.c @@ -221,7 +221,7 @@ void dma_read_flashram() for (i=0; i<(pi_register.pi_wr_len_reg & 0x0FFFFFE)+2; i++) ((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]= - flashram[(((pi_register.pi_cart_addr_reg-0x08000000)&0xFFFF)*2+i)^S8]; + flashram[(((pi_register.pi_cart_addr_reg-0x08000000)&0xFFFE)*2+i)^S8]; break; default: printf("unknown dma_read_flashram:%x\n", mode); diff --git a/libgui/FocusManager.cpp b/libgui/FocusManager.cpp index 8c8fe42..fcce8a9 100644 --- a/libgui/FocusManager.cpp +++ b/libgui/FocusManager.cpp @@ -51,9 +51,8 @@ void Focus::updateFocus() int focusDirection = 0; int buttonsDown = 0; #ifdef HW_RVL - WPADData* wiiPad = Input::getInstance().getWpad(); + WPADData* wpad = Input::getInstance().getWpad(); #endif -// PADStatus* gcPad = Input::getInstance().getPad(); if (!focusActive) return; @@ -71,7 +70,7 @@ void Focus::updateFocus() { previousButtonsGC[i] = PAD_ButtonsHeld(i); #ifdef HW_RVL - previousButtonsWii[i] = wiiPad[i].btns_h; + previousButtonsWii[i] = WPAD_ButtonsHeld(i); #endif } clearInput = false; @@ -80,9 +79,13 @@ void Focus::updateFocus() for (int i=0; i<4; i++) { u16 currentButtonsGC = PAD_ButtonsHeld(i); +#ifdef HW_RVL + u32 currentButtonsWii = WPAD_ButtonsHeld(i); +#endif if (currentButtonsGC ^ previousButtonsGC[i]) { u16 currentButtonsDownGC = (currentButtonsGC ^ previousButtonsGC[i]) & currentButtonsGC; + previousButtonsGC[i] = currentButtonsGC; switch (currentButtonsDownGC & 0xf) { case PAD_BUTTON_LEFT: focusDirection = DIRECTION_LEFT; @@ -108,14 +111,14 @@ void Focus::updateFocus() } if (primaryFocusOwner) primaryFocusOwner = primaryFocusOwner->updateFocus(focusDirection,buttonsDown); else primaryFocusOwner = currentFrame->updateFocus(focusDirection,buttonsDown); - previousButtonsGC[i] = currentButtonsGC; break; } #ifdef HW_RVL - else if (wiiPad[i].btns_h ^ previousButtonsWii[i]) + else if (currentButtonsWii ^ previousButtonsWii[i]) { - u32 currentButtonsDownWii = (wiiPad[i].btns_h ^ previousButtonsWii[i]) & wiiPad[i].btns_h; - switch (wiiPad[i].exp.type) + u32 currentButtonsDownWii = (currentButtonsWii ^ previousButtonsWii[i]) & currentButtonsWii; + previousButtonsWii[i] = currentButtonsWii; + switch (wpad[i].exp.type) { case WPAD_EXP_CLASSIC: case WPAD_EXP_WIIUPRO: @@ -208,7 +211,6 @@ void Focus::updateFocus() } if (primaryFocusOwner) primaryFocusOwner = primaryFocusOwner->updateFocus(focusDirection,buttonsDown); else primaryFocusOwner = currentFrame->updateFocus(focusDirection,buttonsDown); - previousButtonsWii[i] = wiiPad[i].btns_h; break; } #endif diff --git a/libgui/InputManager.cpp b/libgui/InputManager.cpp index 0d270e9..4a0324f 100644 --- a/libgui/InputManager.cpp +++ b/libgui/InputManager.cpp @@ -52,23 +52,17 @@ void Input::refreshInput() { PAD_ScanPads(); #ifdef HW_RVL - WPAD_ScanPads(); - wiiPad = WPAD_Data(0); + WPAD_ScanPads(); #endif } #ifdef HW_RVL WPADData* Input::getWpad() { - return wiiPad; + return WPAD_Data(0); } #endif -PADStatus* Input::getPad() -{ - return &gcPad[0]; -} - void Input::clearInputData() { Focus::getInstance().clearInputData(); diff --git a/libgui/InputManager.h b/libgui/InputManager.h index f07a06a..f248d66 100644 --- a/libgui/InputManager.h +++ b/libgui/InputManager.h @@ -32,7 +32,6 @@ public: #ifdef HW_RVL WPADData* getWpad(); #endif - PADStatus* getPad(); void clearInputData(); static Input& getInstance() { @@ -43,10 +42,6 @@ public: private: Input(); ~Input(); - PADStatus gcPad[4]; -#ifdef HW_RVL - WPADData *wiiPad; -#endif }; diff --git a/main/ata.c b/main/ata.c index e3820eb..00a9b19 100644 --- a/main/ata.c +++ b/main/ata.c @@ -92,10 +92,10 @@ static inline u16 ataReadu16(int chn) } -// Reads up to 0xFFFF * 4 bytes of data (255kb) from the hdd at the given offset -static inline void ata_read_blocks(int chn, u16 numSectors, u32 *dst) +// Reads 512 bytes +static inline void ata_read_buffer(int chn, u32 *dst) { - u16 dwords = (numSectors<<7); + u16 dwords = 128; // 128 * 4 = 512 bytes // (31:29) 011b | (28:24) 10000b | (23:16) | (15:8) | (7:0) 00h (4 bytes) u32 dat = 0x70000000 | ((dwords&0xff) << 16) | (((dwords>>8)&0xff) << 8); EXI_Lock(chn, 0, NULL); @@ -123,21 +123,21 @@ static inline void ata_read_blocks(int chn, u16 numSectors, u32 *dst) } else { // IDE_EXI_V2, no need to select / deselect all the time - EXI_ImmEx(chn,dst,numSectors*512,EXI_READ); + EXI_ImmEx(chn,dst,512,EXI_READ); EXI_Deselect(chn); EXI_Unlock(chn); } } -static inline void ata_write_blocks(int chn, u16 numSectors, u32 *src) +static inline void ata_write_buffer(int chn, u32 *src) { - u16 dwords = (numSectors<<7); + u16 dwords = 128; // 128 * 4 = 512 bytes // (23:21) 111b | (20:16) 10000b | (15:8) | (7:0) (3 bytes) u32 dat = 0xF0000000 | ((dwords&0xff) << 16) | (((dwords>>8)&0xff) << 8); EXI_Lock(chn, 0, NULL); EXI_Select(chn,0,EXI_SPEED32MHZ); EXI_ImmEx(chn,&dat,3,EXI_WRITE); - EXI_ImmEx(chn, src,numSectors*512,EXI_WRITE); + EXI_ImmEx(chn, src,512,EXI_WRITE); dat = 0; EXI_ImmEx(chn,&dat,1,EXI_WRITE); // Burn an extra cycle for the IDE-EXI to know to stop serving data EXI_Deselect(chn); @@ -280,7 +280,7 @@ int ataUnlock(int chn, int useMaster, char *password) // Reads sectors from the specified lba, for the specified slot // Returns 0 on success, -1 on failure. -int _ataReadSectors(int chn, u64 lba, u16 numsectors, u32 *Buffer) +int _ataReadSector(int chn, u64 lba, u32 *Buffer) { u32 temp = 0; @@ -299,17 +299,17 @@ int _ataReadSectors(int chn, u64 lba, u16 numsectors, u32 *Buffer) // check if drive supports LBA 48-bit if(ataDriveInfo.lba48Support) { - ataWriteByte(chn, ATA_REG_SECCOUNT, (u8)((numsectors>>8) & 0xFF)); // Sector count (Hi) + ataWriteByte(chn, ATA_REG_SECCOUNT, 0); // Sector count (Hi) ataWriteByte(chn, ATA_REG_LBALO, (u8)((lba>>24)& 0xFF)); // LBA 4 ataWriteByte(chn, ATA_REG_LBAMID, (u8)((lba>>32) & 0xFF)); // LBA 5 ataWriteByte(chn, ATA_REG_LBAHI, (u8)((lba>>40) & 0xFF)); // LBA 6 - ataWriteByte(chn, ATA_REG_SECCOUNT, (u8)(numsectors & 0xFF)); // Sector count (Lo) + ataWriteByte(chn, ATA_REG_SECCOUNT, 1); // Sector count (Lo) ataWriteByte(chn, ATA_REG_LBALO, (u8)(lba & 0xFF)); // LBA 1 ataWriteByte(chn, ATA_REG_LBAMID, (u8)((lba>>8) & 0xFF)); // LBA 2 ataWriteByte(chn, ATA_REG_LBAHI, (u8)((lba>>16) & 0xFF)); // LBA 3 } else { - ataWriteByte(chn, ATA_REG_SECCOUNT, (u8)(numsectors & 0xFF)); // Sector count + ataWriteByte(chn, ATA_REG_SECCOUNT, 1); // Sector count ataWriteByte(chn, ATA_REG_LBALO, (u8)(lba & 0xFF)); // LBA Lo ataWriteByte(chn, ATA_REG_LBAMID, (u8)((lba>>8) & 0xFF)); // LBA Mid ataWriteByte(chn, ATA_REG_LBAHI, (u8)((lba>>16) & 0xFF)); // LBA Hi @@ -330,7 +330,7 @@ int _ataReadSectors(int chn, u64 lba, u16 numsectors, u32 *Buffer) while(!(ataReadStatusReg(chn) & ATA_SR_DRQ)); // read data from drive - ata_read_blocks(chn, numsectors, Buffer); + ata_read_buffer(chn, Buffer); temp = ataReadStatusReg(chn); // If the error bit was set, fail. @@ -342,9 +342,9 @@ int _ataReadSectors(int chn, u64 lba, u16 numsectors, u32 *Buffer) // Writes sectors to the specified lba, for the specified slot // Returns 0 on success, -1 on failure. -int _ataWriteSectors(int chn, u64 lba, u16 numsectors, u32 *Buffer) +int _ataWriteSector(int chn, u64 lba, u32 *Buffer) { - u32 temp; + u32 i, temp; // Wait for drive to be ready (BSY to clear) while(ataReadStatusReg(chn) & ATA_SR_BSY); @@ -361,17 +361,17 @@ int _ataWriteSectors(int chn, u64 lba, u16 numsectors, u32 *Buffer) // check if drive supports LBA 48-bit if(ataDriveInfo.lba48Support) { - ataWriteByte(chn, ATA_REG_SECCOUNT, (u8)((numsectors>>8) & 0xFF)); // Sector count (Hi) + ataWriteByte(chn, ATA_REG_SECCOUNT, 0); // Sector count (Hi) ataWriteByte(chn, ATA_REG_LBALO, (u8)((lba>>24)& 0xFF)); // LBA 4 ataWriteByte(chn, ATA_REG_LBAMID, (u8)((lba>>32) & 0xFF)); // LBA 4 ataWriteByte(chn, ATA_REG_LBAHI, (u8)((lba>>40) & 0xFF)); // LBA 5 - ataWriteByte(chn, ATA_REG_SECCOUNT, (u8)(numsectors & 0xFF)); // Sector count (Lo) + ataWriteByte(chn, ATA_REG_SECCOUNT, 1); // Sector count (Lo) ataWriteByte(chn, ATA_REG_LBALO, (u8)(lba & 0xFF)); // LBA 1 ataWriteByte(chn, ATA_REG_LBAMID, (u8)((lba>>8) & 0xFF)); // LBA 2 ataWriteByte(chn, ATA_REG_LBAHI, (u8)((lba>>16) & 0xFF)); // LBA 3 } else { - ataWriteByte(chn, ATA_REG_SECCOUNT, (u8)(numsectors & 0xFF)); // Sector count + ataWriteByte(chn, ATA_REG_SECCOUNT, 1); // Sector count ataWriteByte(chn, ATA_REG_LBALO, (u8)(lba & 0xFF)); // LBA Lo ataWriteByte(chn, ATA_REG_LBAMID, (u8)((lba>>8) & 0xFF)); // LBA Mid ataWriteByte(chn, ATA_REG_LBAHI, (u8)((lba>>16) & 0xFF)); // LBA Hi @@ -391,28 +391,14 @@ int _ataWriteSectors(int chn, u64 lba, u16 numsectors, u32 *Buffer) while(!(ataReadStatusReg(chn) & ATA_SR_DRQ)); // Write data to the drive - if(_ideexi_version == IDE_EXI_V1) { - // IDE_EXI_V1, select / deselect for every 4 bytes - u16 *ptr = (u16*)Buffer; - int i = 0; - for (i=0; i<(numsectors*256); i++) { - ataWriteu16(chn, ptr[i]); - } - } - else { - // IDE_EXI_V2, blocks with single select/deselect - ata_write_blocks(chn, numsectors, Buffer); + u16 *ptr = (u16*)Buffer; + for (i=0; i<256; i++) { + ataWriteu16(chn, ptr[i]); } // Wait for the write to finish while(ataReadStatusReg(chn) & ATA_SR_BSY); - // Send Flush command to flush cache to hdd - ataWriteByte(chn, ATA_REG_COMMAND, 0xE7); - - // Wait for the cache flush - while(ataReadStatusReg(chn) & ATA_SR_BSY); - temp = ataReadStatusReg(chn); // If the error bit was set, fail. if(temp & ATA_SR_ERR) { @@ -426,19 +412,13 @@ int _ataWriteSectors(int chn, u64 lba, u16 numsectors, u32 *Buffer) int ataReadSectors(int chn, u64 sector, unsigned int numSectors, unsigned char *dest) { int ret = 0; - int sectorchunks = 1; - while(numSectors > sectorchunks) { - if((ret=_ataReadSectors(chn,sector,sectorchunks,(u32*)dest))) { - return -1; - } - dest+=(sectorchunks*512); - sector+=sectorchunks; - numSectors-=sectorchunks; - } - if(numSectors) { - if((ret=_ataReadSectors(chn,sector,numSectors,(u32*)dest))) { + while(numSectors) { + if((ret=_ataReadSector(chn,sector,(u32*)dest))) { return -1; } + dest+=512; + sector++; + numSectors--; } return 0; } @@ -448,14 +428,13 @@ int ataReadSectors(int chn, u64 sector, unsigned int numSectors, unsigned char * int ataWriteSectors(int chn, u64 sector,unsigned int numSectors, unsigned char *src) { int ret = 0; - int sectorchunks = 1; - while(numSectors > sectorchunks) { - if((ret=_ataWriteSectors(chn,sector,sectorchunks,(u32*)src))) { + while(numSectors) { + if((ret=_ataWriteSector(chn,sector,(u32*)src))) { return -1; } - src+=(sectorchunks*512); - sector+=sectorchunks; - numSectors-=sectorchunks; + src+=512; + sector++; + numSectors--; } return 0; } diff --git a/main/rom.h b/main/rom.h index 1a1d317..f938baf 100644 --- a/main/rom.h +++ b/main/rom.h @@ -58,7 +58,8 @@ typedef struct _rom_header unsigned int unknown; unsigned int Manufacturer_ID; unsigned short Cartridge_ID; - unsigned short Country_code; + unsigned char Country_code; + unsigned char Version; } rom_header; extern rom_header ROM_HEADER; diff --git a/main/rom_gc.c b/main/rom_gc.c index 4adcf59..587c2fd 100644 --- a/main/rom_gc.c +++ b/main/rom_gc.c @@ -62,82 +62,6 @@ int init_byte_swap(unsigned int magicWord) return rom_byte_swap; } -#define TOTAL_NUM_16KBIT 56 -static unsigned int CRC_TABLE[TOTAL_NUM_16KBIT][2] = { - { 0x514B6900, 0xB4B19881 }, // Banjo to Kazooie no Daibouken 2 (J) - { 0x155B7CDF, 0xF0DA7325 }, // Banjo-Tooie (A) - { 0xC9176D39, 0xEA4779D1 }, // Banjo-Tooie (E) (M4) - { 0xC2E9AA9A, 0x475D70AA }, // Banjo-Tooie (U) - { 0x373F5889, 0x9A6CA80A }, // Conker's Bad Fur Day (E) - { 0x8BC3A47A, 0x74221294 }, // Conker's Bad Fur Day (U) (Debug Version) - { 0xA08D0F77, 0x6F82E38C }, // Conker's Bad Fur Day (U) (ECTS Demo) - { 0x30C7AC50, 0x7704072D }, // Conker's Bad Fur Day (U) - { 0x83F3931E, 0xCB72223D }, // Cruis'n World (E) - { 0xDFE61153, 0xD76118E6 }, // Cruis'n World (U) - { 0x079501B9, 0xAB0232AB }, // Custom Robo V2 (J) - { 0x17C54A61, 0x4A83F2E7 }, // Densha de GO! 64 (J) - { 0x68D128AE, 0x67D60F21 }, // Densha de GO! 64 (J) [T] - { 0x11936D8C, 0x6F2C4B43 }, // Donkey Kong 64 (E) - { 0x053C89A7, 0xA5064302 }, // Donkey Kong 64 (J) - { 0xEC58EABF, 0xAD7C7169 }, // Donkey Kong 64 (U) - { 0x0DD4ABAB, 0xB5A2A91E }, // Donkey Kong 64 (U) (Kiosk Demo) - { 0xB6306E99, 0xB63ED2B2 }, // Doraemon 2 - Nobita to Hikari no Shinden (J) - { 0xA8275140, 0xB9B056E8 }, // Doraemon 3 - Nobita no Machi SOS! (J) - { 0x202A8EE4, 0x83F88B89 }, // Excitebike 64 (E) - { 0x861C3519, 0xF6091CE5 }, // Excitebike 64 (J) - { 0x07861842, 0xA12EBC9F }, // Excitebike 64 (U) (V1.0) - { 0xF9D411E3, 0x7CB29BC0 }, // Excitebike 64 (U) (V1.1) - { 0xAF754F7B, 0x1DD17381 }, // Excitebike 64 (U) (Kiosk Demo) - { 0xFF42BE66, 0x91CA9B1D }, // GoldenEye X 5d - { 0xA4844AA2, 0x8E13A961 }, // GoldenEye X 5d (Cloudless) - { 0x0C581C7A, 0x3D6E20E4 }, // Hoshi no Kirby 64 (J) (V1.2) - { 0xBCB1F89F, 0x060752A2 }, // Hoshi no Kirby 64 (J) (V1.3) - { 0x0D93BA11, 0x683868A6 }, // Kirby 64 - The Crystal Shards (E) - { 0x46039FB4, 0x0337822C }, // Kirby 64 - The Crystal Shards (U) - { 0x1739EFBA, 0xD0B43A68 }, // Kobe Bryant's NBA Courtside (E) - { 0x616B8494, 0x8A509210 }, // Kobe Bryant's NBA Courtside (U) - { 0xD7134F8D, 0xC11A00B5 }, // Madden NFL 2002 (U) - { 0xC5674160, 0x0F5F453C }, // Mario Party 3 (E) (M4) - { 0x0B0AB4CD, 0x7B158937 }, // Mario Party 3 (J) - { 0x7C3829D9, 0x6E8247CE }, // Mario Party 3 (U) - { 0x839F3AD5, 0x406D15FA }, // Mario Tennis (E) - { 0x5001CF4F, 0xF30CB3BD }, // Mario Tennis (U) - { 0x3A6C42B5, 0x1ACADA1B }, // Mario Tennis 64 (J) - { 0x147E0EDB, 0x36C5B12C }, // Neon Genesis Evangelion (J) - { 0xCFE2CB31, 0x4D6B1E1D }, // Parlor! Pro 64 - Pachinko Jikki Simulation Game (J) - { 0xF468118C, 0xE32EE44E }, // PD Ultraman Battle Collection 64 (J) - { 0xE4B08007, 0xA602FF33 }, // Perfect Dark (E) (M5) - { 0x96747EB4, 0x104BB243 }, // Perfect Dark (J) - { 0xDDF460CC, 0x3CA634C0 }, // Perfect Dark (U) (v1.0) - { 0x41F2B98F, 0xB458B466 }, // Perfect Dark (U) (v1.1) - { 0x766309EA, 0x3F64A369 }, // Perfect Dark XBLA Mp3 (1.0) - { 0x272B690F, 0xAD0A7A77 }, // Robot Ponkottsu 64 - 7tsu no Umi no Caramel (J) - { 0xFEE97010, 0x4E94A9A0 }, // RR64 - Ridge Racer 64 (E) - { 0x2500267E, 0x2A7EC3CE }, // RR64 - Ridge Racer 64 (U) - { 0x53ED2DC4, 0x06258002 }, // Star Wars Episode I - Racer (E) (M3) - { 0x61F5B152, 0x046122AB }, // Star Wars Episode I - Racer (J) - { 0x72F70398, 0x6556A98B }, // Star Wars Episode I - Racer (U) - { 0x2DCFCA60, 0x8354B147 }, // Yoshi Story (J) - { 0xD3F97D49, 0x6924135B }, // Yoshi's Story (E) (M3) - { 0x2337D8E8, 0x6B8E7CEC }, // Yoshi's Story (U) (M2) -}; - -// Checks if the current game is in the CRC list for 16kbit eeprom save type -// cause it's cheaper to have a CRC list than an entire .ini file :) -bool isEEPROM16k() -{ - int i; - - for (i = 0; i < TOTAL_NUM_16KBIT; i++) - { - if (ROM_HEADER.CRC1 == CRC_TABLE[i][0] && - ROM_HEADER.CRC2 == CRC_TABLE[i][1]) - return true; - } - - return false; -} - void byte_swap(char* buffer, unsigned int length) { int i; @@ -151,6 +75,55 @@ void byte_swap(char* buffer, unsigned int length) } } +static struct { + int Cartridge_ID; + char* Country_codes; +} ROM_TABLE[] = { + { 'D3', "J", }, // Akumajou Dracula Mokushiroku - Real Action Adventure + { 'D4', "J", }, // Akumajou Dracula Mokushiroku Gaiden - Legend of Cornell + { 'B7', "EJPU" }, // Banjo-Tooie + { 'GT', "J", }, // City Tour Grandprix - Zennihon GT Senshuken + { 'FU', "EP", }, // Conker's Bad Fur Day + { 'CW', "EP" }, // Cruis'n World + { 'CZ', "J", }, // Custom Robo V2 + { 'D6', "J", }, // Densha de GO! 64 + { 'DO', "EJP" }, // Donkey Kong 64 + { 'D2', "J", }, // Doraemon 2 - Nobita to Hikari no Shinden + { '3D', "J", }, // Doraemon 3 - Nobita no Machi SOS! + { 'MX', "EJP" }, // Excitebike 64 + { 'X7', "E" }, // GoldenEye X 5d + { 'GC', "EP" }, // GT 64 - Championship Edition + { 'IM', "J", }, // Ide Yousuke no Mahjong Juku + { 'K4', "EJP" }, // Kirby 64 - The Crystal Shards + { 'NB', "EP" }, // Kobe Bryant in NBA Courtside + { 'MV', "EJP" }, // Mario Party 3 + { 'M8', "EJP" }, // Mario Tennis + { 'EV', "J" }, // Neon Genesis Evangelion + { 'PP', "J" }, // Parlor! Pro 64 - Pachinko Jikki Simulation Game + { 'UB', "J" }, // PD Ultraman Battle Collection 64 + { 'PD', "EJP" }, // Perfect Dark + { 'R7', "J" }, // Robot Ponkottsu 64 - 7tsu no Umi no Caramel + { 'RZ', "EP" }, // RR64 - Ridge Racer 64 + { 'EP', "EJP" }, // Star Wars Episode I - Racer + { 'YS', "EJP" }, // Yoshi's Story +}; + +// Checks if the current game is in the ID list for 16kbit eeprom save type +// cause it's cheaper to have a ID list than an entire .ini file :) +bool isEEPROM16k() +{ + int i; + + for (i = 0; i < sizeof(ROM_TABLE) / sizeof(ROM_TABLE[0]); i++) + { + if (ROM_TABLE[i].Cartridge_ID == ROM_HEADER.Cartridge_ID && + strchr(ROM_TABLE[i].Country_codes, ROM_HEADER.Country_code)) + return true; + } + + return false; +} + /* Loads the ROM into the ROM cache */ int rom_read(fileBrowser_file* file){ @@ -165,8 +138,6 @@ int rom_read(fileBrowser_file* file){ } ROMCache_read(&ROM_HEADER, 0, sizeof(rom_header)); - // Swap country code back since I know the emulator relies on this being little endian. - ROM_HEADER.Country_code = bswap16(ROM_HEADER.Country_code); //Copy header name as Goodname (in the .ini we can use CRC to identify ROMS) memset((char*)buffer,0,1024); strncpy(buffer, (char*)ROM_HEADER.Name,32); diff --git a/menu/FileBrowserFrame.cpp b/menu/FileBrowserFrame.cpp index b44a249..b731f47 100644 --- a/menu/FileBrowserFrame.cpp +++ b/menu/FileBrowserFrame.cpp @@ -155,11 +155,14 @@ void FileBrowserFrame::drawChildren(menu::Graphics &gfx) if(isVisible()) { #ifdef HW_RVL - WPADData* wiiPad = menu::Input::getInstance().getWpad(); + WPADData* wpad = menu::Input::getInstance().getWpad(); #endif for (int i=0; i<4; i++) { u16 currentButtonsGC = PAD_ButtonsHeld(i); +#ifdef HW_RVL + u32 currentButtonsWii = WPAD_ButtonsHeld(i); +#endif if (currentButtonsGC ^ previousButtonsGC[i]) { u16 currentButtonsDownGC = (currentButtonsGC ^ previousButtonsGC[i]) & currentButtonsGC; @@ -181,11 +184,11 @@ void FileBrowserFrame::drawChildren(menu::Graphics &gfx) break; } #ifdef HW_RVL - else if (wiiPad[i].btns_h ^ previousButtonsWii[i]) + else if (currentButtonsWii ^ previousButtonsWii[i]) { - u32 currentButtonsDownWii = (wiiPad[i].btns_h ^ previousButtonsWii[i]) & wiiPad[i].btns_h; - previousButtonsWii[i] = wiiPad[i].btns_h; - switch (wiiPad[i].exp.type) + u32 currentButtonsDownWii = (currentButtonsWii ^ previousButtonsWii[i]) & currentButtonsWii; + previousButtonsWii[i] = currentButtonsWii; + switch (wpad[i].exp.type) { case WPAD_EXP_CLASSIC: case WPAD_EXP_WIIUPRO: diff --git a/menu/LoadRomFrame.cpp b/menu/LoadRomFrame.cpp index 915688b..092728f 100644 --- a/menu/LoadRomFrame.cpp +++ b/menu/LoadRomFrame.cpp @@ -40,7 +40,7 @@ extern "C" { void Func_LoadFromSD(); void Func_LoadFromDVD(); void Func_LoadFromUSB(); -void Func_LoadFromSamba(); +void Func_LoadFromSMB(); void Func_ReturnFromLoadRomFrame(); #define NUM_FRAME_BUTTONS 4 @@ -51,7 +51,7 @@ static char FRAME_STRINGS[4][25] = { "Load from SD", "Load from DVD", "Load from USB", - "Load from Samba"}; + "Load from SMB"}; struct ButtonInfo { @@ -73,7 +73,7 @@ struct ButtonInfo { NULL, BTN_A_NRM, FRAME_STRINGS[0], 150.0, 100.0, 340.0, 56.0, 3, 1, -1, -1, Func_LoadFromSD, Func_ReturnFromLoadRomFrame }, // Load From SD { NULL, BTN_A_NRM, FRAME_STRINGS[1], 150.0, 180.0, 340.0, 56.0, 0, 2, -1, -1, Func_LoadFromDVD, Func_ReturnFromLoadRomFrame }, // Load From DVD { NULL, BTN_A_NRM, FRAME_STRINGS[2], 150.0, 260.0, 340.0, 56.0, 1, 3, -1, -1, Func_LoadFromUSB, Func_ReturnFromLoadRomFrame }, // Load From USB - { NULL, BTN_A_NRM, FRAME_STRINGS[3], 150.0, 340.0, 340.0, 56.0, 2, 0, -1, -1, Func_LoadFromSamba, Func_ReturnFromLoadRomFrame }, // Load From Samba + { NULL, BTN_A_NRM, FRAME_STRINGS[3], 150.0, 340.0, 340.0, 56.0, 2, 0, -1, -1, Func_LoadFromSMB, Func_ReturnFromLoadRomFrame }, // Load From SMB }; LoadRomFrame::LoadRomFrame() @@ -196,7 +196,7 @@ void Func_LoadFromUSB() fileBrowserFrame_OpenDirectory(romFile_topLevel); } -void Func_LoadFromSamba() +void Func_LoadFromSMB() { // Deinit any existing romFile state if(romFile_deinit) romFile_deinit( romFile_topLevel ); diff --git a/menu/MainFrame.cpp b/menu/MainFrame.cpp index 9e7032b..fcc80ad 100644 --- a/menu/MainFrame.cpp +++ b/menu/MainFrame.cpp @@ -229,8 +229,7 @@ void Func_PlayGame() { if((u16)PAD_ButtonsHeld(i)) buttonHeld++; #ifdef HW_RVL - WPADData* wiiPad = WPAD_Data(i); - if(wiiPad->err == WPAD_ERR_NONE && wiiPad->btns_h) buttonHeld++; + if(WPAD_ButtonsHeld(i)) buttonHeld++; #endif } } diff --git a/menu/SettingsFrame.cpp b/menu/SettingsFrame.cpp index 7db9fa5..2a6de10 100644 --- a/menu/SettingsFrame.cpp +++ b/menu/SettingsFrame.cpp @@ -449,11 +449,14 @@ void SettingsFrame::drawChildren(menu::Graphics &gfx) if(isVisible()) { #ifdef HW_RVL - WPADData* wiiPad = menu::Input::getInstance().getWpad(); + WPADData* wpad = menu::Input::getInstance().getWpad(); #endif for (int i=0; i<4; i++) { u16 currentButtonsGC = PAD_ButtonsHeld(i); +#ifdef HW_RVL + u32 currentButtonsWii = WPAD_ButtonsHeld(i); +#endif if (currentButtonsGC ^ previousButtonsGC[i]) { u16 currentButtonsDownGC = (currentButtonsGC ^ previousButtonsGC[i]) & currentButtonsGC; @@ -479,11 +482,11 @@ void SettingsFrame::drawChildren(menu::Graphics &gfx) break; } #ifdef HW_RVL - else if (wiiPad[i].btns_h ^ previousButtonsWii[i]) + else if (currentButtonsWii ^ previousButtonsWii[i]) { - u32 currentButtonsDownWii = (wiiPad[i].btns_h ^ previousButtonsWii[i]) & wiiPad[i].btns_h; - previousButtonsWii[i] = wiiPad[i].btns_h; - switch (wiiPad[i].exp.type) + u32 currentButtonsDownWii = (currentButtonsWii ^ previousButtonsWii[i]) & currentButtonsWii; + previousButtonsWii[i] = currentButtonsWii; + switch (wpad[i].exp.type) { case WPAD_EXP_CLASSIC: case WPAD_EXP_WIIUPRO: diff --git a/rsp_hle/alist.c b/rsp_hle/alist.c index 9f3e99a..229b159 100644 --- a/rsp_hle/alist.c +++ b/rsp_hle/alist.c @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - alist.c * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2014 Bobby Smiles * * Copyright (C) 2009 Richard Goedeken * * Copyright (C) 2002 Hacktarux * @@ -666,11 +666,11 @@ void alist_resample( while (count != 0) { const int16_t* lut = RESAMPLE_LUT + ((pitch_accu & 0xfc00) >> 8); - *sample(hle, opos++) = clamp_s16(( - (*sample(hle, ipos ) * lut[0]) + - (*sample(hle, ipos + 1) * lut[1]) + - (*sample(hle, ipos + 2) * lut[2]) + - (*sample(hle, ipos + 3) * lut[3])) >> 15); + *sample(hle, opos++) = clamp_s16( ( + (*sample(hle, ipos ) * lut[0]) + + (*sample(hle, ipos + 1) * lut[1]) + + (*sample(hle, ipos + 2) * lut[2]) + + (*sample(hle, ipos + 3) * lut[3]) ) >> 15); pitch_accu += pitch; ipos += (pitch_accu >> 16); diff --git a/rsp_hle/alist.h b/rsp_hle/alist.h index 7cfa24a..ba9424b 100644 --- a/rsp_hle/alist.h +++ b/rsp_hle/alist.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - alist.h * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2014 Bobby Smiles * * * * This program is free software; you can redistribute it and/or modify * diff --git a/rsp_hle/alist_audio.c b/rsp_hle/alist_audio.c index 3537f7b..6c92d13 100644 --- a/rsp_hle/alist_audio.c +++ b/rsp_hle/alist_audio.c @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - alist_audio.c * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2014 Bobby Smiles * * Copyright (C) 2009 Richard Goedeken * * Copyright (C) 2002 Hacktarux * diff --git a/rsp_hle/alist_naudio.c b/rsp_hle/alist_naudio.c index 6610324..0a05415 100644 --- a/rsp_hle/alist_naudio.c +++ b/rsp_hle/alist_naudio.c @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - alist_naudio.c * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2014 Bobby Smiles * * Copyright (C) 2009 Richard Goedeken * * Copyright (C) 2002 Hacktarux * diff --git a/rsp_hle/alist_nead.c b/rsp_hle/alist_nead.c index 0b0b038..46e9b9e 100644 --- a/rsp_hle/alist_nead.c +++ b/rsp_hle/alist_nead.c @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - alist_nead.c * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2014 Bobby Smiles * * Copyright (C) 2009 Richard Goedeken * * Copyright (C) 2002 Hacktarux * @@ -532,3 +532,25 @@ void alist_process_nead_ac(struct hle_t* hle) alist_process(hle, ABI, 0x18); rsp_break(hle, SP_STATUS_TASKDONE); } + +void alist_process_nead_mats(struct hle_t* hle) +{ + /* FIXME: implement proper ucode + * Forward the task if possible, + * otherwise better to have no sound than garbage sound + */ + if (HleForwardTask(hle->user_defined) != 0) { + rsp_break(hle, SP_STATUS_TASKDONE); + } +} + +void alist_process_nead_efz(struct hle_t* hle) +{ + /* FIXME: implement proper ucode + * Forward the task if possible, + * otherwise use FZero ucode which should be very similar + */ + if (HleForwardTask(hle->user_defined) != 0) { + alist_process_nead_fz(hle); + } +} diff --git a/rsp_hle/arithmetics.h b/rsp_hle/arithmetics.h index 996d57a..9e2793d 100644 --- a/rsp_hle/arithmetics.h +++ b/rsp_hle/arithmetics.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - arithmetics.h * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2014 Bobby Smiles * * * * This program is free software; you can redistribute it and/or modify * diff --git a/rsp_hle/audio.c b/rsp_hle/audio.c index c1c92ef..4487b31 100644 --- a/rsp_hle/audio.c +++ b/rsp_hle/audio.c @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - audio.c * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2014 Bobby Smiles * * * * This program is free software; you can redistribute it and/or modify * diff --git a/rsp_hle/audio.h b/rsp_hle/audio.h index 4f081cf..e8ede6e 100644 --- a/rsp_hle/audio.h +++ b/rsp_hle/audio.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - audio.h * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2014 Bobby Smiles * * * * This program is free software; you can redistribute it and/or modify * diff --git a/rsp_hle/cicx105.c b/rsp_hle/cicx105.c index 3e9c5c6..65f3ec2 100644 --- a/rsp_hle/cicx105.c +++ b/rsp_hle/cicx105.c @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - cicx105.c * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2012 Bobby Smiles * * Copyright (C) 2009 Richard Goedeken * * Copyright (C) 2002 Hacktarux * diff --git a/rsp_hle/common.h b/rsp_hle/common.h index dfc62b9..2f78034 100644 --- a/rsp_hle/common.h +++ b/rsp_hle/common.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - common.h * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2014 Bobby Smiles * * * * This program is free software; you can redistribute it and/or modify * diff --git a/rsp_hle/hle.c b/rsp_hle/hle.c index 5eb3b8f..571d6ec 100644 --- a/rsp_hle/hle.c +++ b/rsp_hle/hle.c @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - hle.c * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2012 Bobby Smiles * * Copyright (C) 2009 Richard Goedeken * * Copyright (C) 2002 Hacktarux * @@ -33,8 +33,6 @@ #include "memory.h" #include "ucodes.h" -#include "../main/wii64config.h" - #define min(a,b) (((a) < (b)) ? (a) : (b)) /* some rdp status flags */ @@ -45,24 +43,20 @@ /* helper functions prototypes */ static unsigned int sum_bytes(const unsigned char *bytes, unsigned int size); static bool is_task(struct hle_t* hle); -static void forward_gfx_task(struct hle_t* hle); -static bool try_fast_audio_dispatching(struct hle_t* hle); -static bool try_fast_task_dispatching(struct hle_t* hle); -static void normal_task_dispatching(struct hle_t* hle); -static void non_task_dispatching(struct hle_t* hle); -static void re2_task_dispatching(struct hle_t* hle); +static void send_dlist_to_gfx_plugin(struct hle_t* hle); +static ucode_func_t try_audio_task_detection(struct hle_t* hle); +static ucode_func_t try_normal_task_detection(struct hle_t* hle); +static ucode_func_t non_task_detection(struct hle_t* hle); +static ucode_func_t task_detection(struct hle_t* hle); #ifdef ENABLE_TASK_DUMP static void dump_binary(struct hle_t* hle, const char *const filename, const unsigned char *const bytes, unsigned int size); static void dump_task(struct hle_t* hle, const char *const filename); -static void dump_unknown_task(struct hle_t* hle, unsigned int sum); -static void dump_unknown_non_task(struct hle_t* hle, unsigned int sum); +static void dump_unknown_task(struct hle_t* hle, unsigned int uc_start); +static void dump_unknown_non_task(struct hle_t* hle, unsigned int uc_start); #endif -/* local variables */ -static const bool FORWARD_AUDIO = false, FORWARD_GFX = true; - /* Global functions */ void hle_init(struct hle_t* hle, unsigned char* dram, @@ -114,12 +108,36 @@ void hle_init(struct hle_t* hle, void hle_execute(struct hle_t* hle) { - if (is_task(hle)) { - if (!try_fast_task_dispatching(hle)) - normal_task_dispatching(hle); - } else { - non_task_dispatching(hle); + uint32_t uc_start = *dmem_u32(hle, TASK_UCODE); + uint32_t uc_dstart = *dmem_u32(hle, TASK_UCODE_DATA); + uint32_t uc_dsize = *dmem_u32(hle, TASK_UCODE_DATA_SIZE); + + bool match = false; + struct cached_ucodes_t * cached_ucodes = &hle->cached_ucodes; + struct ucode_info_t *info = &cached_ucodes->infos[cached_ucodes->count-1]; + for (int i = 0; i < cached_ucodes->count; i++) + { + if (info->uc_start == uc_start && info->uc_dstart == uc_dstart && info->uc_dsize == uc_dsize) + { + match = true; + break; + } + info--; } + + if (!match) + { + info = &cached_ucodes->infos[cached_ucodes->count]; + info->uc_start = uc_start; + info->uc_dstart = uc_dstart; + info->uc_dsize = uc_dsize; + info->uc_pfunc = task_detection(hle); + cached_ucodes->count++; + assert(cached_ucodes->count <= CACHED_UCODES_MAX_SIZE); + assert(info->uc_pfunc != NULL); + } + + info->uc_pfunc(hle); } /* local functions */ @@ -159,14 +177,67 @@ void rsp_break(struct hle_t* hle, unsigned int setbits) } } -static void forward_gfx_task(struct hle_t* hle) +static void send_alist_to_audio_plugin(struct hle_t* hle) { - HleProcessDlistList(hle->user_defined); - *hle->dpc_status &= ~DP_STATUS_FREEZE; + HleProcessAlistList(hle->user_defined); rsp_break(hle, SP_STATUS_TASKDONE); } -static bool try_fast_audio_dispatching(struct hle_t* hle) +static void send_dlist_to_gfx_plugin(struct hle_t* hle) +{ + /* Since GFX_INFO version 2, these bits are set before calling the ProcessDlistList function. + * And the GFX plugin is responsible to unset them if needed. + * For GFX_INFO version < 2, the GFX plugin didn't have access to sp_status so + * it doesn't matter if we set these bits before calling ProcessDlistList function. + */ + *hle->sp_status |= SP_STATUS_TASKDONE | SP_STATUS_BROKE | SP_STATUS_HALT; + + HleProcessDlistList(hle->user_defined); + *hle->dpc_status &= ~DP_STATUS_FREEZE; + + if ((*hle->sp_status & SP_STATUS_INTR_ON_BREAK) && (*hle->sp_status & (SP_STATUS_TASKDONE | SP_STATUS_BROKE | SP_STATUS_HALT))) { + *hle->mi_intr |= MI_INTR_SP; + HleCheckInterrupts(hle->user_defined); + } +} + +static void task_done(struct hle_t* hle) +{ + rsp_break(hle, SP_STATUS_TASKDONE); +} + +static void unknown_ucode(struct hle_t* hle) +{ + /* Forward task to RSP Fallback. + * If task is not forwarded, use the regular "unknown ucode" path */ + if (HleForwardTask(hle->user_defined) != 0) { + + uint32_t uc_start = *dmem_u32(hle, TASK_UCODE); + HleWarnMessage(hle->user_defined, "unknown RSP code: uc_start: %x PC:%x", uc_start, *hle->sp_pc); +#ifdef ENABLE_TASK_DUMP + dump_unknown_non_task(hle, uc_start); +#endif + } +} + +static void unknown_task(struct hle_t* hle) +{ + /* Forward task to RSP Fallback. + * If task is not forwarded, use the regular "unknown task" path */ + if (HleForwardTask(hle->user_defined) != 0) { + + /* Send task_done signal for unknown ucodes to allow further processings */ + rsp_break(hle, SP_STATUS_TASKDONE); + + uint32_t uc_start = *dmem_u32(hle, TASK_UCODE); + HleWarnMessage(hle->user_defined, "unknown OSTask: uc_start: %x PC:%x", uc_start, *hle->sp_pc); +#ifdef ENABLE_TASK_DUMP + dump_unknown_task(hle, uc_start); +#endif + } +} + +static ucode_func_t try_audio_task_detection(struct hle_t* hle) { /* identify audio ucode by using the content of ucode_data */ uint32_t ucode_data = *dmem_u32(hle, TASK_UCODE_DATA); @@ -178,11 +249,11 @@ static bool try_fast_audio_dispatching(struct hle_t* hle) switch(v) { case 0x1e24138c: /* audio ABI (most common) */ - alist_process_audio(hle); return true; + return &alist_process_audio; case 0x1dc8138c: /* GoldenEye */ - alist_process_audio_ge(hle); return true; + return &alist_process_audio_ge; case 0x1e3c1390: /* BlastCorp, DiddyKongRacing */ - alist_process_audio_bc(hle); return true; + return &alist_process_audio_bc; default: HleWarnMessage(hle->user_defined, "ABI1 identification regression: v=%08x", v); } @@ -191,30 +262,33 @@ static bool try_fast_audio_dispatching(struct hle_t* hle) switch(v) { case 0x11181350: /* MarioKart, WaveRace (E) */ - alist_process_nead_mk(hle); return true; + return &alist_process_nead_mk; case 0x111812e0: /* StarFox (J) */ - alist_process_nead_sfj(hle); return true; + return &alist_process_nead_sfj; case 0x110412ac: /* WaveRace (J RevB) */ - alist_process_nead_wrjb(hle); return true; + return &alist_process_nead_wrjb; case 0x110412cc: /* StarFox/LylatWars (except J) */ - alist_process_nead_sf(hle); return true; + return &alist_process_nead_sf; case 0x1cd01250: /* FZeroX */ - alist_process_nead_fz(hle); return true; + return &alist_process_nead_fz; case 0x1f08122c: /* YoshisStory */ - alist_process_nead_ys(hle); return true; + return &alist_process_nead_ys; case 0x1f38122c: /* 1080° Snowboarding */ - alist_process_nead_1080(hle); return true; + return &alist_process_nead_1080; case 0x1f681230: /* Zelda OoT / Zelda MM (J, J RevA) */ - alist_process_nead_oot(hle); return true; + return &alist_process_nead_oot; case 0x1f801250: /* Zelda MM (except J, J RevA, E Beta), PokemonStadium 2 */ - alist_process_nead_mm(hle); return true; + return &alist_process_nead_mm; case 0x109411f8: /* Zelda MM (E Beta) */ - alist_process_nead_mmb(hle); return true; + return &alist_process_nead_mmb; case 0x1eac11b8: /* AnimalCrossing */ - alist_process_nead_ac(hle); return true; + return &alist_process_nead_ac; case 0x00010010: /* MusyX v2 (IndianaJones, BattleForNaboo) */ - musyx_v2_task(hle); return true; - + return &musyx_v2_task; + case 0x1f701238: /* Mario Artist Talent Studio */ + return &alist_process_nead_mats; + case 0x1f4c1230: /* FZeroX Expansion */ + return &alist_process_nead_efz; default: HleWarnMessage(hle->user_defined, "ABI2 identification regression: v=%08x", v); } @@ -227,201 +301,172 @@ static bool try_fast_audio_dispatching(struct hle_t* hle) RogueSquadron, ResidentEvil2, PolarisSnoCross, TheWorldIsNotEnough, RugratsInParis, NBAShowTime, HydroThunder, Tarzan, GauntletLegend, Rush2049 */ - musyx_v1_task(hle); return true; + return &musyx_v1_task; case 0x0000127c: /* naudio (many games) */ - alist_process_naudio(hle); return true; + return &alist_process_naudio; case 0x00001280: /* BanjoKazooie */ - alist_process_naudio_bk(hle); return true; + return &alist_process_naudio_bk; case 0x1c58126c: /* DonkeyKong */ - alist_process_naudio_dk(hle); return true; + return &alist_process_naudio_dk; case 0x1ae8143c: /* BanjoTooie, JetForceGemini, MickeySpeedWayUSA, PerfectDark */ - alist_process_naudio_mp3(hle); return true; + return &alist_process_naudio_mp3; case 0x1ab0140c: /* ConkerBadFurDay */ - alist_process_naudio_cbfd(hle); return true; + return &alist_process_naudio_cbfd; default: HleWarnMessage(hle->user_defined, "ABI3 identification regression: v=%08x", v); } } - return false; + return NULL; } -static bool try_fast_task_dispatching(struct hle_t* hle) +static ucode_func_t try_normal_task_detection(struct hle_t* hle) { - /* identify task ucode by its type */ - switch (*dmem_u32(hle, TASK_TYPE)) { - case 1: - /* Resident evil 2 */ - if (*dmem_u32(hle, TASK_DATA_PTR) == 0) { - re2_task_dispatching(hle); - return true; - } - - if (FORWARD_GFX) { - forward_gfx_task(hle); - return true; - } - break; - - case 2: - if (!audioEnabled) - return true; - - if (FORWARD_AUDIO) { - HleProcessAlistList(hle->user_defined); - rsp_break(hle, SP_STATUS_TASKDONE); - return true; - } else if (try_fast_audio_dispatching(hle)) - return true; - break; - - case 7: - HleShowCFB(hle->user_defined); - rsp_break(hle, SP_STATUS_TASKDONE); - return true; - } - - return false; -} - -static void normal_task_dispatching(struct hle_t* hle) -{ - const unsigned int sum = + unsigned int sum = sum_bytes((void*)dram_u32(hle, *dmem_u32(hle, TASK_UCODE)), min(*dmem_u32(hle, TASK_UCODE_SIZE), 0xf80) >> 1); switch (sum) { /* StoreVe12: found in Zelda Ocarina of Time [misleading task->type == 4] */ case 0x278: /* Nothing to emulate */ - rsp_break(hle, SP_STATUS_TASKDONE); - return; + return &task_done; /* GFX: Twintris [misleading task->type == 0] */ case 0x212ee: - if (FORWARD_GFX) { - forward_gfx_task(hle); - return; + if (hle->hle_gfx) { + return &send_dlist_to_gfx_plugin; } - break; + return NULL; /* JPEG: found in Pokemon Stadium J */ case 0x2c85a: - jpeg_decode_PS0(hle); - return; + return &jpeg_decode_PS0; /* JPEG: found in Zelda Ocarina of Time, Pokemon Stadium 1, Pokemon Stadium 2 */ case 0x2caa6: - jpeg_decode_PS(hle); - return; + return &jpeg_decode_PS; /* JPEG: found in Ogre Battle, Bottom of the 9th */ case 0x130de: case 0x278b0: - jpeg_decode_OB(hle); - return; + return &jpeg_decode_OB; } - /* Send task_done signal for unknown ucodes to allow further processings */ - rsp_break(hle, SP_STATUS_TASKDONE); + /* Resident Evil 2 */ + sum = sum_bytes((void*)dram_u32(hle, *dmem_u32(hle, TASK_UCODE)), 256); + switch (sum) { - HleWarnMessage(hle->user_defined, "unknown OSTask: sum: %x PC:%x", sum, *hle->sp_pc); -#ifdef ENABLE_TASK_DUMP - dump_unknown_task(hle, sum); -#endif + case 0x450f: + return &resize_bilinear_task; + + case 0x3b44: + return &decode_video_frame_task; + + case 0x3d84: + return &fill_video_double_buffer_task; + } + + /* HVQM */ + sum = sum_bytes((void*)dram_u32(hle, *dmem_u32(hle, TASK_UCODE)), 1488); + switch (sum) { + case 0x19495: + return &hvqm2_decode_sp1_task; + + case 0x19728: + return &hvqm2_decode_sp2_task; + } + + return NULL; } -static void non_task_dispatching(struct hle_t* hle) +static ucode_func_t non_task_detection(struct hle_t* hle) { const unsigned int sum = sum_bytes(hle->imem, 44); if (sum == 0x9e2) { /* CIC x105 ucode (used during boot of CIC x105 games) */ - cicx105_ucode(hle); - return; + return &cicx105_ucode; } - - HleWarnMessage(hle->user_defined, "unknown RSP code: sum: %x PC:%x", sum, *hle->sp_pc); -#ifdef ENABLE_TASK_DUMP - dump_unknown_non_task(hle, sum); -#endif + return &unknown_ucode; } -/* Resident evil 2 */ -static void re2_task_dispatching(struct hle_t* hle) +static ucode_func_t task_detection(struct hle_t* hle) { - const unsigned int sum = - sum_bytes((void*)dram_u32(hle, *dmem_u32(hle, TASK_UCODE)), 256); + if (is_task(hle)) { + ucode_func_t uc_pfunc; + uint32_t type = *dmem_u32(hle, TASK_TYPE); - switch (sum) { - - case 0x450f: - resize_bilinear_task(hle); - return; - - case 0x3b44: - decode_video_frame_task(hle); - return; + if (type == 2) { + if (hle->hle_aud) { + return &send_alist_to_audio_plugin; + } + uc_pfunc = try_audio_task_detection(hle); + if (uc_pfunc) + return uc_pfunc; + } - case 0x3d84: - /* TODO: Nothing to emulate? */ - rsp_break(hle, SP_STATUS_TASKDONE); - return; + uc_pfunc = try_normal_task_detection(hle); + if (uc_pfunc) + return uc_pfunc; + + if (type == 1) { + if (hle->hle_gfx) { + return &send_dlist_to_gfx_plugin; + } + } + + return &unknown_task; + } + else { + return non_task_detection(hle); } - - /* Send task_done signal for unknown ucodes to allow further processings */ - rsp_break(hle, SP_STATUS_TASKDONE); - - HleWarnMessage(hle->user_defined, "unknown OSTask: sum: %x PC:%x", sum, *hle->sp_pc); -#ifdef ENABLE_TASK_DUMP - dump_unknown_task(hle, sum); -#endif } #ifdef ENABLE_TASK_DUMP -static void dump_unknown_task(struct hle_t* hle, unsigned int sum) +static void dump_unknown_task(struct hle_t* hle, unsigned int uc_start) { char filename[256]; uint32_t ucode = *dmem_u32(hle, TASK_UCODE); uint32_t ucode_data = *dmem_u32(hle, TASK_UCODE_DATA); uint32_t data_ptr = *dmem_u32(hle, TASK_DATA_PTR); - sprintf(&filename[0], "task_%x.log", sum); + sprintf(&filename[0], "task_%x.log", uc_start); dump_task(hle, filename); /* dump ucode_boot */ - sprintf(&filename[0], "ucode_boot_%x.bin", sum); + sprintf(&filename[0], "ucode_boot_%x.bin", uc_start); dump_binary(hle, filename, (void*)dram_u32(hle, *dmem_u32(hle, TASK_UCODE_BOOT)), *dmem_u32(hle, TASK_UCODE_BOOT_SIZE)); /* dump ucode */ if (ucode != 0) { - sprintf(&filename[0], "ucode_%x.bin", sum); + sprintf(&filename[0], "ucode_%x.bin", uc_start); dump_binary(hle, filename, (void*)dram_u32(hle, ucode), 0xf80); } /* dump ucode_data */ if (ucode_data != 0) { - sprintf(&filename[0], "ucode_data_%x.bin", sum); + sprintf(&filename[0], "ucode_data_%x.bin", uc_start); dump_binary(hle, filename, (void*)dram_u32(hle, ucode_data), *dmem_u32(hle, TASK_UCODE_DATA_SIZE)); } /* dump data */ if (data_ptr != 0) { - sprintf(&filename[0], "data_%x.bin", sum); + sprintf(&filename[0], "data_%x.bin", uc_start); dump_binary(hle, filename, (void*)dram_u32(hle, data_ptr), *dmem_u32(hle, TASK_DATA_SIZE)); } } -static void dump_unknown_non_task(struct hle_t* hle, unsigned int sum) +static void dump_unknown_non_task(struct hle_t* hle, unsigned int uc_start) { char filename[256]; /* dump IMEM & DMEM for further analysis */ - sprintf(&filename[0], "imem_%x.bin", sum); + sprintf(&filename[0], "imem_%x.bin", uc_start); dump_binary(hle, filename, hle->imem, 0x1000); - sprintf(&filename[0], "dmem_%x.bin", sum); + sprintf(&filename[0], "dmem_%x.bin", uc_start); dump_binary(hle, filename, hle->dmem, 0x1000); } diff --git a/rsp_hle/hle.h b/rsp_hle/hle.h index 4a18273..5a87e4e 100644 --- a/rsp_hle/hle.h +++ b/rsp_hle/hle.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - hle.h * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2014 Bobby Smiles * * * * This program is free software; you can redistribute it and/or modify * diff --git a/rsp_hle/hle_external.h b/rsp_hle/hle_external.h index b6d44b0..9cb660d 100644 --- a/rsp_hle/hle_external.h +++ b/rsp_hle/hle_external.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - hle_external.h * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2014 Bobby Smiles * * * * This program is free software; you can redistribute it and/or modify * @@ -22,17 +22,25 @@ #ifndef HLE_EXTERNAL_H #define HLE_EXTERNAL_H +#if defined(__GNUC__) +#define ATTR_FMT(fmtpos, attrpos) __attribute__ ((format (printf, fmtpos, attrpos))) +#else +#define ATTR_FMT(fmtpos, attrpos) +#endif + /* users of the hle core are expected to define these functions */ -void HleVerboseMessage(void* user_defined, const char *message, ...); -void HleErrorMessage(void* user_defined, const char *message, ...); -void HleWarnMessage(void* user_defined, const char *message, ...); +void HleVerboseMessage(void* user_defined, const char *message, ...) ATTR_FMT(2, 3); +void HleInfoMessage(void* user_defined, const char *message, ...) ATTR_FMT(2, 3); +void HleErrorMessage(void* user_defined, const char *message, ...) ATTR_FMT(2, 3); +void HleWarnMessage(void* user_defined, const char *message, ...) ATTR_FMT(2, 3); void HleCheckInterrupts(void* user_defined); void HleProcessDlistList(void* user_defined); void HleProcessAlistList(void* user_defined); void HleProcessRdpList(void* user_defined); void HleShowCFB(void* user_defined); +int HleForwardTask(void* user_defined); #endif diff --git a/rsp_hle/hle_internal.h b/rsp_hle/hle_internal.h index 0adfb74..9bdbfaa 100644 --- a/rsp_hle/hle_internal.h +++ b/rsp_hle/hle_internal.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - hle_internal.h * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2014 Bobby Smiles * * * * This program is free software; you can redistribute it and/or modify * @@ -57,6 +57,8 @@ struct hle_t /* for user convenience, this will be passed to "external" functions */ void* user_defined; + int hle_gfx; + int hle_aud; /* alist.c */ uint8_t alist_buffer[0x1000]; @@ -72,6 +74,8 @@ struct hle_t /* mp3.c */ uint8_t mp3_buffer[0x1000]; + + struct cached_ucodes_t cached_ucodes; }; /* some mips interface interrupt flags */ diff --git a/rsp_hle/hvqm.c b/rsp_hle/hvqm.c new file mode 100644 index 0000000..caf9caa --- /dev/null +++ b/rsp_hle/hvqm.c @@ -0,0 +1,354 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-rsp-hle - hvqm.c * + * Mupen64Plus homepage: https://mupen64plus.org/ * + * Copyright (C) 2020 Gilles Siberlin * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include +#include +#include +#include +#include + +#include "hle_external.h" +#include "hle_internal.h" +#include "memory.h" + + /* Nest size */ +#define HVQM2_NESTSIZE_L 70 /* Number of elements on long side */ +#define HVQM2_NESTSIZE_S 38 /* Number of elements on short side */ +#define HVQM2_NESTSIZE (HVQM2_NESTSIZE_L * HVQM2_NESTSIZE_S) + +struct HVQM2Block { + uint8_t nbase; + uint8_t dc; + uint8_t dc_l; + uint8_t dc_r; + uint8_t dc_u; + uint8_t dc_d; +}; + +struct HVQM2Basis { + uint8_t sx; + uint8_t sy; + int16_t scale; + uint16_t offset; + uint16_t lineskip; +}; + +struct HVQM2Arg { + uint32_t info; + uint32_t buf; + uint16_t buf_width; + uint8_t chroma_step_h; + uint8_t chroma_step_v; + uint16_t hmcus; + uint16_t vmcus; + uint8_t alpha; + uint32_t nest; +}; + +struct RGBA { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t a; +}; + +static struct HVQM2Arg arg; + +static const int16_t constant[5][16] = { +{0x0006,0x0008,0x0008,0x0006,0x0008,0x000A,0x000A,0x0008,0x0008,0x000A,0x000A,0x0008,0x0006,0x0008,0x0008,0x0006}, +{0x0002,0x0000,0xFFFF,0xFFFF,0x0002,0x0000,0xFFFF,0xFFFF,0x0002,0x0000,0xFFFF,0xFFFF,0x0002,0x0000,0xFFFF,0xFFFF}, +{0xFFFF,0xFFFF,0x0000,0x0002,0xFFFF,0xFFFF,0x0000,0x0002,0xFFFF,0xFFFF,0x0000,0x0002,0xFFFF,0xFFFF,0x0000,0x0002}, +{0x0002,0x0002,0x0002,0x0002,0x0000,0x0000,0x0000,0x0000,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF}, +{0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x0000,0x0000,0x0000,0x0000,0x0002,0x0002,0x0002,0x0002} +}; + +static int process_info(struct hle_t* hle, uint8_t* base, int16_t* out) +{ + struct HVQM2Block block; + uint8_t nbase = *base; + + dram_load_u8(hle, (uint8_t*)&block, arg.info, sizeof(struct HVQM2Block)); + arg.info += 8; + + *base = block.nbase & 0x7; + + if ((block.nbase & nbase) != 0) + return 0; + + if (block.nbase == 0) + { + //LABEL8 + for (int i = 0; i < 16; i++) + { + out[i] = constant[0][i] * block.dc; + out[i] += constant[1][i] * block.dc_l; + out[i] += constant[2][i] * block.dc_r; + out[i] += constant[3][i] * block.dc_u; + out[i] += constant[4][i] * block.dc_d; + out[i] += 4; + out[i] >>= 3; + } + } + else if ((block.nbase & 0xf) == 0) + { + //LABEL7 + for (int i = 0; i < 16; i++) + { + out[i] = *dram_u8(hle, arg.info); + arg.info++; + } + } + else if (*base == 0) + { + //LABEL6 + for (int i = 0; i < 16; i++) + { + out[i] = *(int8_t*)dram_u8(hle, arg.info) + block.dc; + arg.info++; + } + } + else + { + //LABEL5 + struct HVQM2Basis basis; + + for (int i = 0; i < 16; i++) + out[i] = block.dc; + + for (; *base != 0; (*base)--) + { + basis.sx = *dram_u8(hle, arg.info); + arg.info++; + basis.sy = *dram_u8(hle, arg.info); + arg.info++; + basis.scale = *dram_u16(hle, arg.info); + arg.info += 2; + basis.offset = *dram_u16(hle, arg.info); + arg.info += 2; + basis.lineskip = *dram_u16(hle, arg.info); + arg.info += 2; + + int16_t vec[16]; + uint32_t addr = arg.nest + basis.offset; + int shift = (basis.sx != 0) ? 1 : 0; + + //LABEL9 + //LABEL10 + for (int i = 0; i < 16; i += 4) + { + vec[i] = *dram_u8(hle, addr); + vec[i + 1] = *dram_u8(hle, addr + (1 << shift)); + vec[i + 2] = *dram_u8(hle, addr + (2 << shift)); + vec[i + 3] = *dram_u8(hle, addr + (3 << shift)); + addr += basis.lineskip; + } + + //LABEL11 + int16_t sum = 0x8; + for (int i = 0; i < 16; i++) + sum += vec[i]; + + sum >>= 4; + + int16_t max = 0; + for (int i = 0; i < 16; i++) + { + vec[i] -= sum; + max = (abs(vec[i]) > max) ? abs(vec[i]) : max; + } + + double dmax = 0.0; + if (max > 0) + dmax = (double)(basis.scale << 2) / (double)max; + + for (int i = 0; i < 16; i++) + out[i] += (vec[i] < 0) ? (int16_t)((double)vec[i] * dmax - 0.5) : (int16_t)((double)vec[i] * dmax + 0.5); + + block.nbase &= 8; + } + + assert(block.nbase == 0); + //if(block.nbase != 0) + // LABEL6 + } + + return 1; +} + +#define SATURATE8(x) ((unsigned int) x <= 255 ? x : (x < 0 ? 0: 255)) +static struct RGBA YCbCr_to_RGBA(int16_t Y, int16_t Cb, int16_t Cr, uint8_t alpha) +{ + struct RGBA color; + + //Format S10.6 + int r = (int)(((double)Y + 0.5) + (1.765625 * (double)(Cr - 128))); + int g = (int)(((double)Y + 0.5) - (0.34375 * (double)(Cr - 128)) - (0.71875 * (double)(Cb - 128))); + int b = (int)(((double)Y + 0.5) + (1.40625 * (double)(Cb - 128))); + + color.r = SATURATE8(r); + color.g = SATURATE8(g); + color.b = SATURATE8(b); + color.a = alpha; + + return color; +} + +void store_rgba5551(struct hle_t* hle, struct RGBA color, uint32_t * addr) +{ + uint16_t pixel = ((color.b >> 3) << 11) | ((color.g >> 3) << 6) | ((color.r >> 3) << 1) | (color.a & 1); + dram_store_u16(hle, &pixel, *addr, 1); + *addr += 2; +} + +void store_rgba8888(struct hle_t* hle, struct RGBA color, uint32_t * addr) +{ + uint32_t pixel = (color.b << 24) | (color.g << 16) | (color.r << 8) | color.a; + dram_store_u32(hle, &pixel, *addr, 1); + *addr += 4; +} + +typedef void(*store_pixel_t)(struct hle_t* hle, struct RGBA color, uint32_t * addr); + +static void hvqm2_decode(struct hle_t* hle, int is32) +{ + //uint32_t uc_data_ptr = *dmem_u32(hle, TASK_UCODE_DATA); + uint32_t data_ptr = *dmem_u32(hle, TASK_DATA_PTR); + + assert((*dmem_u32(hle, TASK_FLAGS) & 0x1) == 0); + + /* Fill HVQM2Arg struct */ + arg.info = *dram_u32(hle, data_ptr); + data_ptr += 4; + arg.buf = *dram_u32(hle, data_ptr); + data_ptr += 4; + arg.buf_width = *dram_u16(hle, data_ptr); + data_ptr += 2; + arg.chroma_step_h = *dram_u8(hle, data_ptr); + data_ptr++; + arg.chroma_step_v = *dram_u8(hle, data_ptr); + data_ptr++; + arg.hmcus = *dram_u16(hle, data_ptr); + data_ptr += 2; + arg.vmcus = *dram_u16(hle, data_ptr); + data_ptr += 2; + arg.alpha = *dram_u8(hle, data_ptr); + arg.nest = data_ptr + 1; + + assert(arg.chroma_step_h == 2); + assert((arg.chroma_step_v == 1) || (arg.chroma_step_v == 2)); + assert((*hle->sp_status & 0x80) == 0); //SP_STATUS_YIELD + + int length, skip; + store_pixel_t store_pixel; + + if (is32) + { + length = 0x20; + skip = arg.buf_width << 2; + arg.buf_width <<= 4; + store_pixel = &store_rgba8888; + } + else + { + length = 0x10; + skip = arg.buf_width << 1; + arg.buf_width <<= 3; + store_pixel = &store_rgba5551; + } + + if (arg.chroma_step_v == 2) + arg.buf_width += arg.buf_width; + + for (int i = arg.vmcus; i != 0; i--) + { + uint32_t out; + int j; + + for (j = arg.hmcus, out = arg.buf; j != 0; j--, out += length) + { + uint8_t base = 0x80; + int16_t Cb[16], Cr[16], Y1[32], Y2[32]; + int16_t* pCb = Cb; + int16_t* pCr = Cr; + int16_t* pY1 = Y1; + int16_t* pY2 = Y2; + + if (arg.chroma_step_v == 2) + { + if (process_info(hle, &base, pY1) == 0) + continue; + if (process_info(hle, &base, pY2) == 0) + continue; + + pY1 = &Y1[16]; + pY2 = &Y2[16]; + } + + if (process_info(hle, &base, pY1) == 0) + continue; + if (process_info(hle, &base, pY2) == 0) + continue; + if (process_info(hle, &base, Cr) == 0) + continue; + if (process_info(hle, &base, Cb) == 0) + continue; + + pY1 = Y1; + pY2 = Y2; + + uint32_t out_buf = out; + for (int k = 0; k < 4; k++) + { + for (int m = 0; m < arg.chroma_step_v; m++) + { + uint32_t addr = out_buf; + for (int l = 0; l < 4; l++) + { + struct RGBA color = YCbCr_to_RGBA(pY1[l], pCb[l >> 1], pCr[l >> 1], arg.alpha); + store_pixel(hle, color, &addr); + } + for (int l = 0; l < 4; l++) + { + struct RGBA color = YCbCr_to_RGBA(pY2[l], pCb[(l + 4) >> 1], pCr[(l + 4) >> 1], arg.alpha); + store_pixel(hle, color, &addr); + } + out_buf += skip; + pY1 += 4; + pY2 += 4; + } + pCr += 4; + pCb += 4; + } + } + arg.buf += arg.buf_width; + } + rsp_break(hle, SP_STATUS_TASKDONE); +} + +void hvqm2_decode_sp1_task(struct hle_t* hle) +{ + hvqm2_decode(hle, 0); +} + +void hvqm2_decode_sp2_task(struct hle_t* hle) +{ + hvqm2_decode(hle, 1); +} \ No newline at end of file diff --git a/rsp_hle/jpeg.c b/rsp_hle/jpeg.c index 5c4fbb1..9f86471 100644 --- a/rsp_hle/jpeg.c +++ b/rsp_hle/jpeg.c @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - jpeg.c * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2012 Bobby Smiles * * Copyright (C) 2009 Richard Goedeken * * Copyright (C) 2002 Hacktarux * @@ -475,7 +475,7 @@ static void ReorderSubBlock(int16_t *dst, const int16_t *src, const unsigned int unsigned int i; /* source and destination sublocks cannot overlap */ - assert(abs(dst - src) > SUBBLOCK_SIZE); + assert(labs(dst - src) > SUBBLOCK_SIZE); for (i = 0; i < SUBBLOCK_SIZE; ++i) dst[i] = src[table[i]]; diff --git a/rsp_hle/memory.c b/rsp_hle/memory.c index 3e3f58e..003174d 100644 --- a/rsp_hle/memory.c +++ b/rsp_hle/memory.c @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - memory.c * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2014 Bobby Smiles * * * * This program is free software; you can redistribute it and/or modify * diff --git a/rsp_hle/memory.h b/rsp_hle/memory.h index 5654c95..8e20568 100644 --- a/rsp_hle/memory.h +++ b/rsp_hle/memory.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - memory.h * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2014 Bobby Smiles * * * * This program is free software; you can redistribute it and/or modify * diff --git a/rsp_hle/mp3.c b/rsp_hle/mp3.c index 734ac0c..8ae2851 100644 --- a/rsp_hle/mp3.c +++ b/rsp_hle/mp3.c @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - mp3.c * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2014 Bobby Smiles * * Copyright (C) 2009 Richard Goedeken * * Copyright (C) 2002 Hacktarux * diff --git a/rsp_hle/musyx.c b/rsp_hle/musyx.c index 14e1592..d452fb0 100644 --- a/rsp_hle/musyx.c +++ b/rsp_hle/musyx.c @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - musyx.c * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2013 Bobby Smiles * * * * This program is free software; you can redistribute it and/or modify * diff --git a/rsp_hle/plugin.c b/rsp_hle/plugin.c index a73f0b2..cecdff7 100644 --- a/rsp_hle/plugin.c +++ b/rsp_hle/plugin.c @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - plugin.c * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2014 Bobby Smiles * * Copyright (C) 2009 Richard Goedeken * * Copyright (C) 2002 Hacktarux * @@ -28,6 +28,7 @@ #include "common.h" #include "hle.h" #include "hle_internal.h" +#include "hle_external.h" #include "RSPPlugin.h" #include "Rsp_#1.1.h" @@ -47,6 +48,11 @@ void HleVerboseMessage(void* UNUSED(user_defined), const char *message, ...) /* discard verbose message */ } +void HleInfoMessage(void* UNUSED(user_defined), const char *message, ...) +{ + /* discard informational message */ +} + void HleErrorMessage(void* UNUSED(user_defined), const char *message, ...) { /* discard error message */ @@ -97,6 +103,10 @@ void HleShowCFB(void* UNUSED(user_defined)) (*l_ShowCFB)(); } +int HleForwardTask(void* user_defined) +{ + return -1; +} /* DLL-exported functions */ EXPORT void CALL CloseDLL(void) @@ -140,9 +150,12 @@ EXPORT void CALL InitiateRSP(RSP_INFO Rsp_Info, unsigned int* UNUSED(CycleCount) l_ProcessAlistList = Rsp_Info.ProcessAlistList; l_ProcessRdpList = Rsp_Info.ProcessRdpList; l_ShowCFB = Rsp_Info.ShowCFB; + + g_hle.hle_gfx = 1; + g_hle.hle_aud = 0; } EXPORT void CALL RomClosed(void) { - /* do nothing */ + g_hle.cached_ucodes.count = 0; } diff --git a/rsp_hle/re2.c b/rsp_hle/re2.c index d64757c..85da283 100644 --- a/rsp_hle/re2.c +++ b/rsp_hle/re2.c @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - re2.c * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2016 Gilles Siberlin * * * * This program is free software; you can redistribute it and/or modify * @@ -178,3 +178,47 @@ void decode_video_frame_task(struct hle_t* hle) rsp_break(hle, SP_STATUS_TASKDONE); } + +void fill_video_double_buffer_task(struct hle_t* hle) +{ + int data_ptr = *dmem_u32(hle, TASK_UCODE_DATA); + + int pSrc = *dram_u32(hle, data_ptr); + int pDest = *dram_u32(hle, data_ptr + 0x4); + int width = *dram_u32(hle, data_ptr + 0x8) >> 1; + int height = *dram_u32(hle, data_ptr + 0x10) << 1; + int stride = *dram_u32(hle, data_ptr + 0x1c) >> 1; + + assert((*dram_u32(hle, data_ptr + 0x28) >> 16) == 0x8000); + +#if 0 /* unused, but keep it for documentation purpose */ + int arg3 = *dram_u32(hle, data_ptr + 0xc); + int arg5 = *dram_u32(hle, data_ptr + 0x14); + int arg6 = *dram_u32(hle, data_ptr + 0x18); +#endif + + int i, j; + int r, g, b; + uint32_t pixel, pixel1, pixel2; + + for(i = 0; i < height; i++) + { + for(j = 0; j < width; j=j+4) + { + pixel1 = *dram_u32(hle, pSrc+j); + pixel2 = *dram_u32(hle, pDest+j); + + r = (((pixel1 >> 24) & 0xff) + ((pixel2 >> 24) & 0xff)) >> 1; + g = (((pixel1 >> 16) & 0xff) + ((pixel2 >> 16) & 0xff)) >> 1; + b = (((pixel1 >> 8) & 0xff) + ((pixel2 >> 8) & 0xff)) >> 1; + + pixel = (r << 24) | (g << 16) | (b << 8) | 0; + + dram_store_u32(hle, &pixel, pDest+j, 1); + } + pSrc += stride; + pDest += stride; + } + + rsp_break(hle, SP_STATUS_TASKDONE); +} diff --git a/rsp_hle/ucodes.h b/rsp_hle/ucodes.h index c05414d..3bddee4 100644 --- a/rsp_hle/ucodes.h +++ b/rsp_hle/ucodes.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-rsp-hle - ucodes.h * - * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2014 Bobby Smiles * * * * This program is free software; you can redistribute it and/or modify * @@ -24,8 +24,23 @@ #include +#define CACHED_UCODES_MAX_SIZE 16 + struct hle_t; +typedef void(*ucode_func_t)(struct hle_t* hle); + +struct ucode_info_t { + uint32_t uc_start; + uint32_t uc_dstart; + uint16_t uc_dsize; + ucode_func_t uc_pfunc; +}; + +struct cached_ucodes_t { + struct ucode_info_t infos[CACHED_UCODES_MAX_SIZE]; + int count; +}; /* cic_x105 ucode */ void cicx105_ucode(struct hle_t* hle); @@ -126,7 +141,8 @@ void alist_process_nead_oot (struct hle_t* hle); void alist_process_nead_mm (struct hle_t* hle); void alist_process_nead_mmb (struct hle_t* hle); void alist_process_nead_ac (struct hle_t* hle); - +void alist_process_nead_mats(struct hle_t* hle); +void alist_process_nead_efz (struct hle_t* hle); /* mp3 ucode */ void mp3_task(struct hle_t* hle, unsigned int index, uint32_t address); @@ -145,7 +161,11 @@ void jpeg_decode_OB(struct hle_t* hle); /* Resident evil 2 ucode */ void resize_bilinear_task(struct hle_t* hle); void decode_video_frame_task(struct hle_t* hle); +void fill_video_double_buffer_task(struct hle_t* hle); +/* hvqm2 ucode */ +void hvqm2_decode_sp1_task(struct hle_t* hle); +void hvqm2_decode_sp2_task(struct hle_t* hle); #endif