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.
This commit is contained in:
Extrems 2020-05-09 01:20:15 -04:00
parent 1bb10eb21d
commit 8be842aa43
38 changed files with 819 additions and 354 deletions

View file

@ -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 \

View file

@ -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 \

View file

@ -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;
}

View file

@ -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)
{

View file

@ -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);

View file

@ -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

View file

@ -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();

View file

@ -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
};

View file

@ -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) <num_words_LSB> | (15:8) <num_words_MSB> | (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) <num_words_LSB> | (7:0) <num_words_MSB> (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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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:

View file

@ -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 );

View file

@ -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
}
}

View file

@ -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:

View file

@ -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);

View file

@ -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 *

View file

@ -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 *

View file

@ -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 *

View file

@ -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);
}
}

View file

@ -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 *

View file

@ -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 *

View file

@ -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 *

View file

@ -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 *

View file

@ -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 *

View file

@ -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);
}

View file

@ -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 *

View file

@ -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

View file

@ -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 */

354
rsp_hle/hvqm.c Normal file
View file

@ -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 <assert.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#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);
}

View file

@ -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]];

View file

@ -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 *

View file

@ -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 *

View file

@ -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 *

View file

@ -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 *

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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 <stdint.h>
#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