mirror of
https://github.com/extremscorner/not64.git
synced 2024-05-15 10:39:40 -04:00
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:
parent
1bb10eb21d
commit
8be842aa43
|
@ -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 \
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
||||
};
|
||||
|
||||
|
|
81
main/ata.c
81
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) <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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
127
main/rom_gc.c
127
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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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 *
|
||||
|
|
337
rsp_hle/hle.c
337
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
354
rsp_hle/hvqm.c
Normal 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);
|
||||
}
|
|
@ -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]];
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue