diff --git a/Config/Glide64.rdb b/Config/Glide64.rdb index f1aac62bc..ed6efb2eb 100644 --- a/Config/Glide64.rdb +++ b/Config/Glide64.rdb @@ -1946,6 +1946,12 @@ optimize_texrect=0 swapmode=2 useless_is_useless=1 +[27C985A8-ED7CE5C6-C:0] +Good Name=Mega Man 64 (Proto) +Internal Name=Megaman 64 +depthmode=1 +increase_texrect_edge=1 + [0EC158F5-FB3E6896-C:45] Good Name=Mega Man 64 (U) Internal Name=Mega Man 64 diff --git a/Config/Project64.rdb b/Config/Project64.rdb index acefa20cf..ac0395b4b 100644 --- a/Config/Project64.rdb +++ b/Config/Project64.rdb @@ -1811,6 +1811,7 @@ Status=Compatible Plugin Note=[Glide64] missing menu effects 32bit=No Culling=1 +Fixed Audio=0 [B30ED978-3003C9F9-C:45] Good Name=F-ZERO X (U) @@ -3380,6 +3381,11 @@ Plugin Note=[Glide64] errors:various RDRAM Size=8 Save Type=16kbit Eeprom +[27C985A8-ED7CE5C6-C:0] +Good Name=Mega Man 64 (Proto) +Internal Name=Megaman 64 +Status=Compatible + [0EC158F5-FB3E6896-C:45] Good Name=Mega Man 64 (U) Internal Name=Mega Man 64 @@ -3753,12 +3759,14 @@ Status=Compatible Good Name=NBA Live 2000 (E) (M4) Internal Name=NBA LIVE 2000 Status=Compatible +32bit=No [5F25B0EE-6227C1DB-C:45] Good Name=NBA Live 2000 (U) (M4) Internal Name=NBA LIVE 2000 Status=Compatible Culling=1 +32bit=No [CF84F45F-00E4F6EB-C:50] Good Name=NBA Live 99 (E) (M5) @@ -3813,11 +3821,13 @@ Status=Compatible Good Name=NFL Blitz 2000 (U) (V1.0) Internal Name=blitz2k Status=Compatible +32bit=No [5B755842-6CA39C7A-C:45] Good Name=NFL Blitz 2000 (U) (V1.1) Internal Name=blitz2k Status=Compatible +32bit=No [36FA35EB-E85E2E36-C:45] Good Name=NFL Blitz 2001 (U) diff --git a/Lang/Japanese.pj.Lang b/Lang/Japanese.pj.Lang index bd59acc57..204887059 100644 --- a/Lang/Japanese.pj.Lang +++ b/Lang/Japanese.pj.Lang @@ -246,8 +246,9 @@ #463# "前回使ったチートを記憶する(&R)" #464# "ロムの実行中はスクリーンセーバーを無効にする" #465# "フレームレートを表示" -#466# "表示形式によってフレームレートを変更する:" +#466# "フレームレートの表示形式" #467# "Project64がすでに起動しているかチェックする" +#468# "ゲーム毎にセーブディレクトリを作成する" //ROM Browser Tab #480# "最近開いたロムファイルの表示する数(0~10):" diff --git a/Source/Android/PluginRSP/alist.cpp b/Source/Android/PluginRSP/alist.cpp index 8e37e993b..6318cc54d 100644 --- a/Source/Android/PluginRSP/alist.cpp +++ b/Source/Android/PluginRSP/alist.cpp @@ -633,11 +633,11 @@ void alist_resample( CHle * hle, bool init, bool flag2, uint16_t dmemo, uint16_t { const int16_t* lut = RESAMPLE_LUT + ((pitch_accu & 0xfc00) >> 8); - *sample(hle, opos++) = clamp_s16( - ((*sample(hle, ipos) * lut[0]) >> 15) + - ((*sample(hle, ipos + 1) * lut[1]) >> 15) + - ((*sample(hle, ipos + 2) * lut[2]) >> 15) + - ((*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); @@ -911,7 +911,7 @@ void alist_polef(CHle * hle, bool init, uint16_t dmemo, uint16_t dmemi, uint16_t count -= 16; } while (count != 0); - dram_store_u16(hle, (uint16_t*)(dst - 4), address, 4); + dram_store_u32(hle, (uint32_t*)(dst - 4), address, 2); } void alist_iirf(CHle * hle, bool init, uint16_t dmemo, uint16_t dmemi, uint16_t count, int16_t* table, uint32_t address) diff --git a/Source/Project64-core/Multilanguage.h b/Source/Project64-core/Multilanguage.h index 0bc0d81b8..5ee4eac8f 100644 --- a/Source/Project64-core/Multilanguage.h +++ b/Source/Project64-core/Multilanguage.h @@ -81,6 +81,7 @@ enum LanguageStringID MENU_RESUME = 132, MENU_RESET_SOFT = 133, //added in build 1.7.50 MENU_RESET_HARD = 134, //added in build 1.7.50 + MENU_SWAPDISK = 135, //added in build 2.2.???? //Options Menu MENU_OPTIONS = 140, diff --git a/Source/Project64-core/Multilanguage/LanguageClass.cpp b/Source/Project64-core/Multilanguage/LanguageClass.cpp index 4b906cfad..2a4bd46f9 100644 --- a/Source/Project64-core/Multilanguage/LanguageClass.cpp +++ b/Source/Project64-core/Multilanguage/LanguageClass.cpp @@ -88,6 +88,7 @@ void CLanguage::LoadDefaultStrings(void) DEF_STR(MENU_RESUME, "R&esume"); DEF_STR(MENU_RESET_SOFT, "&Soft Reset"); DEF_STR(MENU_RESET_HARD, "&Hard Reset"); + DEF_STR(MENU_SWAPDISK, "Swap &Disk"); //Options Menu DEF_STR(MENU_OPTIONS, "&Options"); diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp index 5759e0f65..af100bf17 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp @@ -481,7 +481,7 @@ R4300iOp::Func * R4300iOp::BuildInterpreter() Jump_CoP1_S[5] = COP1_S_ABS; Jump_CoP1_S[6] = COP1_S_MOV; Jump_CoP1_S[7] = COP1_S_NEG; - Jump_CoP1_S[8] = UnknownOpcode; + Jump_CoP1_S[8] = COP1_S_ROUND_L; Jump_CoP1_S[9] = COP1_S_TRUNC_L; Jump_CoP1_S[10] = COP1_S_CEIL_L; //added by Witten Jump_CoP1_S[11] = COP1_S_FLOOR_L; //added by Witten @@ -546,7 +546,7 @@ R4300iOp::Func * R4300iOp::BuildInterpreter() Jump_CoP1_D[5] = COP1_D_ABS; Jump_CoP1_D[6] = COP1_D_MOV; Jump_CoP1_D[7] = COP1_D_NEG; - Jump_CoP1_D[8] = UnknownOpcode; + Jump_CoP1_D[8] = COP1_D_ROUND_L; Jump_CoP1_D[9] = COP1_D_TRUNC_L; //added by Witten Jump_CoP1_D[10] = COP1_D_CEIL_L; //added by Witten Jump_CoP1_D[11] = COP1_D_FLOOR_L; //added by Witten @@ -2461,6 +2461,12 @@ void R4300iOp::COP1_S_NEG() *(float *)_FPR_S[m_Opcode.fd] = (*(float *)_FPR_S[m_Opcode.fs] * -1.0f); } +void R4300iOp::COP1_S_ROUND_L() +{ + TEST_COP1_USABLE_EXCEPTION(); + Float_RoundToInteger64(&*(int64_t *)_FPR_D[m_Opcode.fd], &*(float *)_FPR_S[m_Opcode.fs], FE_TONEAREST); +} + void R4300iOp::COP1_S_TRUNC_L() { TEST_COP1_USABLE_EXCEPTION(); @@ -2652,6 +2658,12 @@ void R4300iOp::COP1_D_NEG() *(double *)_FPR_D[m_Opcode.fd] = (*(double *)_FPR_D[m_Opcode.fs] * -1.0); } +void R4300iOp::COP1_D_ROUND_L() +{ + TEST_COP1_USABLE_EXCEPTION(); + Double_RoundToInteger64(&*(uint64_t *)_FPR_S[m_Opcode.fd], &*(double *)_FPR_D[m_Opcode.fs], FE_TONEAREST); +} + void R4300iOp::COP1_D_TRUNC_L() { //added by Witten TEST_COP1_USABLE_EXCEPTION(); diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps.h b/Source/Project64-core/N64System/Interpreter/InterpreterOps.h index 6aeb7000d..cf370db61 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps.h +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps.h @@ -160,6 +160,7 @@ public: static void COP1_S_ABS(); static void COP1_S_MOV(); static void COP1_S_NEG(); + static void COP1_S_ROUND_L(); static void COP1_S_TRUNC_L(); static void COP1_S_CEIL_L(); //added by Witten static void COP1_S_FLOOR_L(); //added by Witten @@ -181,6 +182,7 @@ public: static void COP1_D_ABS(); static void COP1_D_MOV(); static void COP1_D_NEG(); + static void COP1_D_ROUND_L(); static void COP1_D_TRUNC_L(); //added by Witten static void COP1_D_CEIL_L(); //added by Witten static void COP1_D_FLOOR_L(); //added by Witten diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp index 09447ae6d..6d8324b36 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp @@ -376,7 +376,7 @@ R4300iOp32::Func * R4300iOp32::BuildInterpreter() Jump_CoP1_S[5] = R4300iOp::COP1_S_ABS; Jump_CoP1_S[6] = R4300iOp::COP1_S_MOV; Jump_CoP1_S[7] = R4300iOp::COP1_S_NEG; - Jump_CoP1_S[8] = R4300iOp::UnknownOpcode; + Jump_CoP1_S[8] = R4300iOp::COP1_S_ROUND_L; Jump_CoP1_S[9] = R4300iOp::COP1_S_TRUNC_L; Jump_CoP1_S[10] = R4300iOp::COP1_S_CEIL_L; //added by Witten Jump_CoP1_S[11] = R4300iOp::COP1_S_FLOOR_L; //added by Witten @@ -441,7 +441,7 @@ R4300iOp32::Func * R4300iOp32::BuildInterpreter() Jump_CoP1_D[5] = R4300iOp::COP1_D_ABS; Jump_CoP1_D[6] = R4300iOp::COP1_D_MOV; Jump_CoP1_D[7] = R4300iOp::COP1_D_NEG; - Jump_CoP1_D[8] = R4300iOp::UnknownOpcode; + Jump_CoP1_D[8] = R4300iOp::COP1_D_ROUND_L; Jump_CoP1_D[9] = R4300iOp::COP1_D_TRUNC_L; //added by Witten Jump_CoP1_D[10] = R4300iOp::COP1_D_CEIL_L; //added by Witten Jump_CoP1_D[11] = R4300iOp::COP1_D_FLOOR_L; //added by Witten diff --git a/Source/Project64-core/N64System/Mips/Disk.cpp b/Source/Project64-core/N64System/Mips/Disk.cpp index 783a6f992..707de645f 100644 --- a/Source/Project64-core/N64System/Mips/Disk.cpp +++ b/Source/Project64-core/N64System/Mips/Disk.cpp @@ -22,6 +22,8 @@ #include #endif +uint8_t dd_swapdelay; + bool dd_write; bool dd_reset_hold; uint32_t dd_track_offset, dd_zone; @@ -29,11 +31,9 @@ uint32_t dd_start_block, dd_current; void DiskCommand() { - if (g_Disk != NULL) - g_Reg->ASIC_STATUS |= DD_STATUS_DISK_PRES; - //ASIC_CMD_STATUS - Commands uint32_t cmd = g_Reg->ASIC_CMD; + WriteTrace(TraceN64System, TraceDebug, "DD CMD %08X", cmd); #ifdef _WIN32 SYSTEMTIME sysTime; @@ -81,7 +81,13 @@ void DiskCommand() g_Reg->ASIC_STATUS &= ~DD_STATUS_DISK_CHNG; break; case 0x00090000: //Unset Reset Bit - g_Reg->ASIC_STATUS &= ~DD_STATUS_RST_STATE; break; + g_Reg->ASIC_STATUS &= ~DD_STATUS_RST_STATE; + g_Reg->ASIC_STATUS &= ~DD_STATUS_DISK_CHNG; + //F-Zero X + Expansion Kit fix so it doesn't enable "swapping" at boot + dd_swapdelay = 0; + if (g_Disk != NULL) + g_Reg->ASIC_STATUS |= DD_STATUS_DISK_PRES; + break; case 0x00120000: //RTC Get Year & Month g_Reg->ASIC_DATA = (year << 24) | (month << 16); break; @@ -100,7 +106,11 @@ void DiskCommand() void DiskReset(void) { //ASIC_HARD_RESET 0xAAAA0000 + WriteTrace(TraceN64System, TraceDebug, "DD RESET"); g_Reg->ASIC_STATUS |= DD_STATUS_RST_STATE; + dd_swapdelay = 0; + if (g_Disk != NULL) + g_Reg->ASIC_STATUS |= DD_STATUS_DISK_PRES; } void DiskBMControl(void) @@ -159,6 +169,17 @@ void DiskGapSectorCheck() DiskBMUpdate(); } } + + if (!(g_Reg->ASIC_STATUS & DD_STATUS_DISK_PRES) && g_Disk != NULL && g_Settings->LoadBool(GameRunning_LoadingInProgress) == false) + { + dd_swapdelay++; + if (dd_swapdelay >= 50) + { + g_Reg->ASIC_STATUS |= (DD_STATUS_DISK_PRES | DD_STATUS_DISK_CHNG); + dd_swapdelay = 0; + WriteTrace(TraceN64System, TraceDebug, "DD SWAP DONE"); + } + } } void DiskBMUpdate() @@ -245,7 +266,7 @@ void DiskBMRead() sector += dd_track_offset; sector += dd_start_block * SECTORS_PER_BLOCK * ddZoneSecSize[dd_zone]; sector += (dd_current) * (((g_Reg->ASIC_HOST_SECBYTE & 0x00FF0000) >> 16) + 1); - WriteTrace(TraceN64System, TraceDebug, "READ Block %d Sector %02X - %08X", ((g_Reg->ASIC_CUR_TK & 0x0FFF0000) >> 15) | dd_start_block, dd_current, sector); + //WriteTrace(TraceN64System, TraceDebug, "READ Block %d Sector %02X - %08X", ((g_Reg->ASIC_CUR_TK & 0x0FFF0000) >> 15) | dd_start_block, dd_current, sector); g_Disk->SetDiskAddressBuffer(sector); return; } @@ -256,7 +277,7 @@ void DiskBMWrite() sector += dd_track_offset; sector += dd_start_block * SECTORS_PER_BLOCK * ddZoneSecSize[dd_zone]; sector += (dd_current) * (((g_Reg->ASIC_HOST_SECBYTE & 0x00FF0000) >> 16) + 1); - WriteTrace(TraceN64System, TraceDebug, "WRITE Block %d Sector %02X - %08X", ((g_Reg->ASIC_CUR_TK & 0x0FFF0000) >> 15) | dd_start_block, dd_current, sector); + //WriteTrace(TraceN64System, TraceDebug, "WRITE Block %d Sector %02X - %08X", ((g_Reg->ASIC_CUR_TK & 0x0FFF0000) >> 15) | dd_start_block, dd_current, sector); g_Disk->SetDiskAddressBuffer(sector); return; } diff --git a/Source/Project64-core/N64System/Mips/Dma.cpp b/Source/Project64-core/N64System/Mips/Dma.cpp index 86d7fde61..26d62defa 100644 --- a/Source/Project64-core/N64System/Mips/Dma.cpp +++ b/Source/Project64-core/N64System/Mips/Dma.cpp @@ -198,12 +198,8 @@ void CDMA::PI_DMA_READ() void CDMA::PI_DMA_WRITE() { - uint32_t PI_WR_LEN_REG = ((g_Reg->PI_WR_LEN_REG) & 0x00FFFFFFul) + 1; - - if ((PI_WR_LEN_REG & 1) != 0) - { - PI_WR_LEN_REG += 1; /* fixes AI Shougi 3, Doraemon 3, etc. */ - } + uint32_t PI_WR_LEN_REG = ((g_Reg->PI_WR_LEN_REG) & 0x00FFFFFEul) + 2; + /* rounding PI_WR_LEN_REG up to the nearest even number fixes AI Shougi 3, Doraemon 3, etc. */ g_Reg->PI_STATUS_REG |= PI_STATUS_DMA_BUSY; if (g_Reg->PI_DRAM_ADDR_REG + PI_WR_LEN_REG > g_MMU->RdramSize()) @@ -366,9 +362,63 @@ void CDMA::PI_DMA_WRITE() g_Reg->PI_CART_ADDR_REG -= 0x10000000; if (g_Reg->PI_CART_ADDR_REG + PI_WR_LEN_REG < g_Rom->GetRomSize()) { - for (i = 0; i < PI_WR_LEN_REG; i++) + size_t alignment; + RDRAM += g_Reg->PI_DRAM_ADDR_REG; + ROM += g_Reg->PI_CART_ADDR_REG; + alignment = PI_WR_LEN_REG | (size_t)RDRAM | (size_t)ROM; + if ((alignment & 0x3) == 0) { - *(RDRAM + ((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3)) = *(ROM + ((g_Reg->PI_CART_ADDR_REG + i) ^ 3)); + for (i = 0; i < PI_WR_LEN_REG; i += 4) + { + *(uint32_t *)(RDRAM + i) = *(uint32_t *)(ROM + i); + } + } + else if ((alignment & 1) == 0) + { + if ((PI_WR_LEN_REG & 2) == 0) + { + if (((size_t)RDRAM & 2) == 0) + { + for (i = 0; i < PI_WR_LEN_REG; i += 4) + { + *(uint16_t *)(((size_t)RDRAM + i) + 2) = *(uint16_t *)(((size_t)ROM + i) - 2); + *(uint16_t *)(((size_t)RDRAM + i) + 0) = *(uint16_t *)(((size_t)ROM + i) + 4); + } + } + else + { + if (((size_t)ROM & 2) == 0) + { + for (i = 0; i < PI_WR_LEN_REG; i += 4) + { + *(uint16_t *)(((size_t)RDRAM + i) - 2) = *(uint16_t *)(((size_t)ROM + i) + 2); + *(uint16_t *)(((size_t)RDRAM + i) + 4) = *(uint16_t *)(((size_t)ROM + i) + 0); + } + } + else + { + for (i = 0; i < PI_WR_LEN_REG; i += 4) + { + *(uint16_t *)(((size_t)RDRAM + i) - 2) = *(uint16_t *)(((size_t)ROM + i) - 2); + *(uint16_t *)(((size_t)RDRAM + i) + 4) = *(uint16_t *)(((size_t)ROM + i) + 4); + } + } + } + } + else + { + for (i = 0; i < PI_WR_LEN_REG; i += 2) + { + *(uint16_t *)(((size_t)RDRAM + i) ^ 2) = *(uint16_t *)(((size_t)ROM + i) ^ 2); + } + } + } + else + { + for (i = 0; i < PI_WR_LEN_REG; i++) + { + *(uint8_t *)(((size_t)RDRAM + i) ^ 3) = *(uint8_t *)(((size_t)ROM + i) ^ 3); + } } } else if (g_Reg->PI_CART_ADDR_REG >= g_Rom->GetRomSize()) diff --git a/Source/Project64-core/N64System/Mips/Mempak.H b/Source/Project64-core/N64System/Mips/Mempak.H index 1f0fda70f..e55c0156c 100644 --- a/Source/Project64-core/N64System/Mips/Mempak.H +++ b/Source/Project64-core/N64System/Mips/Mempak.H @@ -14,8 +14,9 @@ class Mempak { public: static uint8_t CalculateCrc(uint8_t * DataToCrc); - static void Load(int32_t Control); - static void Format(int32_t Control); static void ReadFrom(int32_t Control, uint32_t address, uint8_t * data); static void WriteTo(int32_t Control, uint32_t address, uint8_t * data); +private: + static void LoadMempak(int32_t Control); + static void Format(int32_t Control); }; \ No newline at end of file diff --git a/Source/Project64-core/N64System/Mips/Mempak.cpp b/Source/Project64-core/N64System/Mips/Mempak.cpp index 8d9a8ea87..121829292 100644 --- a/Source/Project64-core/N64System/Mips/Mempak.cpp +++ b/Source/Project64-core/N64System/Mips/Mempak.cpp @@ -15,33 +15,37 @@ #include uint8_t Mempaks[4][128 * 256]; /* [CONTROLLERS][PAGES][BYTES_PER_PAGE] */ -CPath MempakNames[4]; +CFile MempakHandle[4]; -void Mempak::Load(int32_t Control) +void Mempak::LoadMempak(int32_t Control) { stdstr MempakName; - MempakName.Format("%s_Cont_%d", g_Settings->LoadStringVal(Game_GameName).c_str(), Control + 1); - MempakNames[Control] = CPath(g_Settings->LoadStringVal(Directory_NativeSave).c_str(), stdstr_f("%s.mpk",MempakName.c_str()).c_str()); + CPath MempakPath(g_Settings->LoadStringVal(Directory_NativeSave).c_str(), stdstr_f("%s.mpk",MempakName.c_str()).c_str()); + if (g_Settings->LoadBool(Setting_UniqueSaveDir)) { - MempakNames[Control].AppendDirectory(g_Settings->LoadStringVal(Game_UniqueSaveDir).c_str()); + MempakPath.AppendDirectory(g_Settings->LoadStringVal(Game_UniqueSaveDir).c_str()); } - if (!MempakNames[Control].DirectoryExists()) + if (!MempakPath.DirectoryExists()) { - MempakNames[Control].DirectoryCreate(); + MempakPath.DirectoryCreate(); } - if (MempakNames[Control].Exists()) + bool formatMempak = !MempakPath.Exists(); + + MempakHandle[Control].Open(MempakPath, CFileBase::modeReadWrite | CFileBase::modeNoTruncate | CFileBase::modeCreate); + MempakHandle[Control].SeekToBegin(); + + if (formatMempak) { - FILE *mempak = fopen(MempakNames[Control], "rb"); - fread(Mempaks[Control], 1, 0x8000, mempak); - fclose(mempak); + Mempak::Format(Control); + MempakHandle[Control].Write(Mempaks[Control], 0x8000); } else { - Mempak::Format(Control); + MempakHandle[Control].Read(Mempaks[Control], 0x8000); } } @@ -113,6 +117,11 @@ void Mempak::ReadFrom(int32_t Control, uint32_t address, uint8_t * data) { if (address < 0x8000) { + if (!MempakHandle[Control].IsOpen()) + { + LoadMempak(Control); + } + memcpy(data, &Mempaks[Control][address], 0x20); } else @@ -126,11 +135,16 @@ void Mempak::WriteTo(int32_t Control, uint32_t address, uint8_t * data) { if (address < 0x8000) { + if (!MempakHandle[Control].IsOpen()) + { + LoadMempak(Control); + } + memcpy(&Mempaks[Control][address], data, 0x20); - FILE* mempak = fopen(MempakNames[Control], "wb"); - fwrite(Mempaks[Control], 1, 0x8000, mempak); - fclose(mempak); + MempakHandle[Control].Seek(address, CFile::begin); + MempakHandle[Control].Write(data, 0x20); + MempakHandle[Control].Flush(); } else { diff --git a/Source/Project64-core/N64System/Mips/PifRam.cpp b/Source/Project64-core/N64System/Mips/PifRam.cpp index 932acd658..5f8d83c98 100644 --- a/Source/Project64-core/N64System/Mips/PifRam.cpp +++ b/Source/Project64-core/N64System/Mips/PifRam.cpp @@ -118,6 +118,7 @@ void CPifRam::PifRamRead() CurPos = 0x40; } break; + case 0xFD: CurPos = 0x40; break; case 0xFE: CurPos = 0x40; break; case 0xFF: break; case 0xB4: case 0x56: case 0xB8: break; /* ??? */ @@ -227,6 +228,7 @@ void CPifRam::PifRamWrite() CurPos = 0x40; } break; + case 0xFD: CurPos = 0x40; break; case 0xFE: CurPos = 0x40; break; case 0xFF: break; case 0xB4: case 0x56: case 0xB8: break; /* ??? */ diff --git a/Source/Project64-core/N64System/Mips/RegisterClass.cpp b/Source/Project64-core/N64System/Mips/RegisterClass.cpp index f0283f6d3..aac7e23a9 100644 --- a/Source/Project64-core/N64System/Mips/RegisterClass.cpp +++ b/Source/Project64-core/N64System/Mips/RegisterClass.cpp @@ -307,14 +307,15 @@ void CRegisters::SetAsCurrentSystem() void CRegisters::CheckInterrupts() { + uint32_t mi_intr_reg = MI_INTR_REG, status_register; if (!m_System->bFixedAudio() && CpuType() != CPU_SyncCores) { - MI_INTR_REG &= ~MI_INTR_AI; - MI_INTR_REG |= (m_AudioIntrReg & MI_INTR_AI); + mi_intr_reg &= ~MI_INTR_AI; + mi_intr_reg |= (m_AudioIntrReg & MI_INTR_AI); } - MI_INTR_REG |= (m_RspIntrReg & MI_INTR_SP); - MI_INTR_REG |= (m_GfxIntrReg & MI_INTR_DP); - if ((MI_INTR_MASK_REG & MI_INTR_REG) != 0) + mi_intr_reg |= (m_RspIntrReg & MI_INTR_SP); + mi_intr_reg |= (m_GfxIntrReg & MI_INTR_DP); + if ((MI_INTR_MASK_REG & mi_intr_reg) != 0) { FAKE_CAUSE_REGISTER |= CAUSE_IP2; } @@ -322,21 +323,23 @@ void CRegisters::CheckInterrupts() { FAKE_CAUSE_REGISTER &= ~CAUSE_IP2; } + MI_INTR_REG = mi_intr_reg; + status_register = STATUS_REGISTER; - if ((STATUS_REGISTER & STATUS_IE) == 0) + if ((status_register & STATUS_IE) == 0) { return; } - if ((STATUS_REGISTER & STATUS_EXL) != 0) + if ((status_register & STATUS_EXL) != 0) { return; } - if ((STATUS_REGISTER & STATUS_ERL) != 0) + if ((status_register & STATUS_ERL) != 0) { return; } - if ((STATUS_REGISTER & FAKE_CAUSE_REGISTER & 0xFF00) != 0) + if ((status_register & FAKE_CAUSE_REGISTER & 0xFF00) != 0) { if (m_FirstInterupt) { diff --git a/Source/Project64-core/N64System/Mips/SystemTiming.cpp b/Source/Project64-core/N64System/Mips/SystemTiming.cpp index 7a749bcc4..22db902b9 100644 --- a/Source/Project64-core/N64System/Mips/SystemTiming.cpp +++ b/Source/Project64-core/N64System/Mips/SystemTiming.cpp @@ -161,12 +161,12 @@ void CSystemTimer::UpdateTimers() int TimeTaken = m_LastUpdate - m_NextTimer; if (TimeTaken != 0) { - uint32_t random, wired; + int32_t random, wired; m_LastUpdate = m_NextTimer; g_Reg->COUNT_REGISTER += TimeTaken; random = g_Reg->RANDOM_REGISTER - (TimeTaken / g_System->CountPerOp()); wired = g_Reg->WIRED_REGISTER; - if ((int)random < (int)wired) + if (random < wired) { if (wired == 0) { @@ -175,10 +175,7 @@ void CSystemTimer::UpdateTimers() else { uint32_t increment = 32 - wired; - do - { - random += increment; - } while ((int)random < (int)wired); + random += ((wired - random + increment - 1) / increment) * increment; } } g_Reg->RANDOM_REGISTER = random; diff --git a/Source/Project64-core/N64System/Mips/Transferpak.cpp b/Source/Project64-core/N64System/Mips/Transferpak.cpp index dfa77a0d4..f089a77a1 100644 --- a/Source/Project64-core/N64System/Mips/Transferpak.cpp +++ b/Source/Project64-core/N64System/Mips/Transferpak.cpp @@ -32,13 +32,22 @@ void Transferpak::Init() void Transferpak::Release() { - GBCart::release_gb_cart(&tpak.gb_cart); + if (tpak.gb_cart.rom != NULL) + { + GBCart::release_gb_cart(&tpak.gb_cart); + } } void Transferpak::ReadFrom(uint16_t address, uint8_t * data) { if ((address >= 0x8000) && (address <= 0x8FFF)) { + //Ensure we actually have a ROM loaded in first. + if (tpak.gb_cart.rom == NULL) + { + Init(); + } + //Get whether the GB cart is enabled or disabled uint8_t value = (tpak.enabled) ? 0x84 : 0x00; @@ -71,8 +80,15 @@ void Transferpak::ReadFrom(uint16_t address, uint8_t * data) void Transferpak::WriteTo(uint16_t address, uint8_t * data) { + if ((address >= 0x8000) && (address <= 0x8FFF)) { + //Ensure we actually have a ROM loaded in first. + if (tpak.gb_cart.rom == NULL) + { + Init(); + } + //Set whether the gb cart is enabled or disabled. switch (*data) { diff --git a/Source/Project64-core/N64System/N64Class.cpp b/Source/Project64-core/N64System/N64Class.cpp index 5969b123b..7ce2212bb 100644 --- a/Source/Project64-core/N64System/N64Class.cpp +++ b/Source/Project64-core/N64System/N64Class.cpp @@ -385,6 +385,13 @@ bool CN64System::EmulationStarting(CThread * thread) WriteTrace(TraceN64System, TraceDebug, "Game starting"); g_BaseSystem->StartEmulation2(false); WriteTrace(TraceN64System, TraceDebug, "Game Done"); + //PLACE TO ADD 64DD SAVING CODE + if (g_Disk != NULL) + { + g_Disk->SaveDiskImage(); + //g_Notify->DisplayError(g_Disk->GetError()); + WriteTrace(TraceN64System, TraceDebug, "64DD Save Done"); + } } catch (...) { @@ -411,11 +418,11 @@ void CN64System::StartEmulation2(bool NewThread) StartLog(); } - WriteTrace(TraceN64System, TraceDebug, "Setting up system"); + WriteTrace(TraceN64System, TraceDebug, "Setting up system"); CInterpreterCPU::BuildCPU(); uint32_t CpuType = g_Settings->LoadDword(Game_CpuType); - WriteTrace(TraceN64System, TraceDebug, "CpuType = %d",CpuType); + WriteTrace(TraceN64System, TraceDebug, "CpuType = %d",CpuType); if (CpuType == CPU_SyncCores && !g_Settings->LoadBool(Debugger_Enabled)) { g_Settings->SaveDword(Game_CpuType, CPU_Recompiler); @@ -440,7 +447,7 @@ void CN64System::StartEmulation2(bool NewThread) m_Recomp = new CRecompiler(m_Reg, m_Profile, m_EndEmulation); } - WriteTrace(TraceN64System, TraceDebug, "Setting system as active"); + WriteTrace(TraceN64System, TraceDebug, "Setting system as active"); bool bSetActive = true; if (m_SyncCPU) { @@ -454,13 +461,13 @@ void CN64System::StartEmulation2(bool NewThread) if (!bSetActive) { - WriteTrace(TraceN64System, TraceWarning, "Failed to set system as active"); + WriteTrace(TraceN64System, TraceWarning, "Failed to set system as active"); g_Settings->SaveBool(GameRunning_LoadingInProgress, false); g_Notify->DisplayError(MSG_PLUGIN_NOT_INIT); } else { - WriteTrace(TraceN64System, TraceDebug, "Starting emulation thread"); + WriteTrace(TraceN64System, TraceDebug, "Starting emulation thread"); StartEmulationThead(); } } @@ -468,10 +475,10 @@ void CN64System::StartEmulation2(bool NewThread) { //mark the emulation as starting and fix up menus g_Notify->DisplayMessage(5, MSG_EMULATION_STARTED); - WriteTrace(TraceN64System, TraceDebug, "Start Executing CPU"); + WriteTrace(TraceN64System, TraceDebug, "Start Executing CPU"); ExecuteCPU(); } - WriteTrace(TraceN64System, TraceDebug, "Done"); + WriteTrace(TraceN64System, TraceDebug, "Done"); } void CN64System::StartEmulation(bool NewThread) @@ -687,25 +694,6 @@ bool CN64System::SetActiveSystem(bool bActive) { WriteTrace(TraceN64System, TraceError, "g_Plugins->Initiate Failed"); } - else - { - CONTROL * Controllers = g_Plugins->Control()->PluginControllers(); - for (int i = 0; i < 3; i++) - { - if (Controllers[i].Present) - { - switch (Controllers[i].Plugin) - { - case PLUGIN_TANSFER_PAK: - Transferpak::Init(); - break; - case PLUGIN_MEMPAK: - Mempak::Load(i); - break; - } - } - } - } } if (bReset) diff --git a/Source/Project64-core/N64System/N64DiskClass.cpp b/Source/Project64-core/N64System/N64DiskClass.cpp index 813a559ec..4eb7d3c94 100644 --- a/Source/Project64-core/N64System/N64DiskClass.cpp +++ b/Source/Project64-core/N64System/N64DiskClass.cpp @@ -13,6 +13,7 @@ #include "SystemGlobals.h" #include #include +#include #include CN64Disk::CN64Disk() : @@ -31,9 +32,21 @@ bool CN64Disk::LoadDiskImage(const char * FileLoc) { UnallocateDiskImage(); - if (!AllocateAndLoadDiskImage(FileLoc)) + //Assume the file extension is *.ndd (it is the only case where it is loaded) + stdstr ShadowFile = FileLoc; + ShadowFile[ShadowFile.length() - 1] = 'r'; + + g_Settings->SaveBool(GameRunning_LoadingInProgress, true); + + WriteTrace(TraceN64System, TraceDebug, "Attempt to load shadow file."); + if (!AllocateAndLoadDiskImage(ShadowFile.c_str())) { - return false; + WriteTrace(TraceN64System, TraceDebug, "Loading Shadow file failed"); + UnallocateDiskImage(); + if (!AllocateAndLoadDiskImage(FileLoc)) + { + return false; + } } if (g_Disk == this) @@ -41,9 +54,64 @@ bool CN64Disk::LoadDiskImage(const char * FileLoc) g_Settings->SaveBool(GameRunning_LoadingInProgress, false); } + m_FileName = FileLoc; return true; } +bool CN64Disk::SaveDiskImage() +{ + //NO NEED TO SAVE IF DISK TYPE IS 6 + uint8_t disktype = m_DiskImage[5] & 0xF; + if (disktype == 0x6) + { + m_DiskFile.Close(); + WriteTrace(TraceN64System, TraceDebug, "Loaded Disk Type is 0x7. No RAM area. Shadow file is not needed."); + return true; + } + + //Assume the file extension is *.ndd (it is the only case where it is loaded) + stdstr ShadowFile = m_FileName; + ShadowFile[ShadowFile.length() - 1] = 'r'; + + WriteTrace(TraceN64System, TraceDebug, "Trying to open %s (Shadow File)", ShadowFile.c_str()); + m_DiskFile.Close(); + if (!m_DiskFile.Open(ShadowFile.c_str(), CFileBase::modeWrite | CFileBase::modeCreate)) + { + WriteTrace(TraceN64System, TraceError, "Failed to open %s (Shadow File)", ShadowFile.c_str()); + return false; + } + + m_DiskFile.SeekToBegin(); + ForceByteSwapDisk(); + + if (m_DiskFormat == DiskFormatMAME) + { + //If original file was MAME format, just copy + WriteTrace(TraceN64System, TraceDebug, "64DD disk is MAME format"); + if (!m_DiskFile.Write(m_DiskImage, MameFormatSize)) + { + m_DiskFile.Close(); + WriteTrace(TraceN64System, TraceError, "Failed to write file"); + return false; + } + } + else if (m_DiskFormat == DiskFormatSDK) + { + //If original file was SDK format, we need to convert it back + WriteTrace(TraceN64System, TraceDebug, "64DD disk is SDK format"); + ConvertDiskFormatBack(); + } + + m_DiskFile.Close(); + return true; +} + +void CN64Disk::SwapDiskImage(const char * FileLoc) +{ + g_Reg->ASIC_STATUS &= ~DD_STATUS_DISK_PRES; + LoadDiskImage(FileLoc); +} + bool CN64Disk::IsValidDiskImage(uint8_t Test[4]) { if (*((uint32_t *)&Test[0]) == 0x16D348E8) { return true; } @@ -101,6 +169,7 @@ bool CN64Disk::AllocateAndLoadDiskImage(const char * FileLoc) if (DiskFileSize == MameFormatSize) { //If Disk is MAME Format (size is constant, it should be the same for every file), then continue + m_DiskFormat = DiskFormatMAME; WriteTrace(TraceN64System, TraceDebug, "Disk File is MAME Format"); if (!AllocateDiskImage(DiskFileSize)) @@ -144,6 +213,8 @@ bool CN64Disk::AllocateAndLoadDiskImage(const char * FileLoc) { //If Disk is SDK format (made with SDK based dumpers like LuigiBlood's, or Nintendo's, size is also constant) //We need to convert it. + m_DiskFormat = DiskFormatSDK; + g_Notify->DisplayMessage(5, MSG_LOADING); //Allocate supported size @@ -193,6 +264,21 @@ void CN64Disk::ByteSwapDisk() } } +void CN64Disk::ForceByteSwapDisk() +{ + uint32_t count; + + for (count = 0; count < m_DiskFileSize; count += 4) + { + m_DiskImage[count] ^= m_DiskImage[count + 3]; + m_DiskImage[count + 3] ^= m_DiskImage[count]; + m_DiskImage[count] ^= m_DiskImage[count + 3]; + m_DiskImage[count + 1] ^= m_DiskImage[count + 2]; + m_DiskImage[count + 2] ^= m_DiskImage[count + 1]; + m_DiskImage[count + 1] ^= m_DiskImage[count + 2]; + } +} + void CN64Disk::SetError(LanguageStringID ErrorMsg) { m_ErrorMsg = ErrorMsg; @@ -290,7 +376,7 @@ void CN64Disk::ConvertDiskFormat() atrack = 0; for (track = 0; track < ZoneTracks[zone]; track++) { - if (track == SystemData[0x20 + zone * 0xC + atrack]) + if (atrack < 0xC && track == SystemData[0x20 + zone * 0xC + atrack]) { memset((void *)(&BlockData0), 0, BLOCKSIZE(zone)); memset((void *)(&BlockData1), 0, BLOCKSIZE(zone)); @@ -327,7 +413,7 @@ void CN64Disk::ConvertDiskFormat() atrack = 0xB; for (track = 1; track < ZoneTracks[zone] + 1; track++) { - if ((ZoneTracks[zone] - track) == SystemData[0x20 + (zone)* 0xC + atrack]) + if (atrack > -1 && (ZoneTracks[zone] - track) == SystemData[0x20 + (zone)* 0xC + atrack]) { memset((void *)(&BlockData0), 0, BLOCKSIZE(zone)); memset((void *)(&BlockData1), 0, BLOCKSIZE(zone)); @@ -354,4 +440,178 @@ void CN64Disk::ConvertDiskFormat() OutOffset += BLOCKSIZE(zone); } } +} + +void CN64Disk::ConvertDiskFormatBack() +{ + //Original code by Happy_ + const uint32_t ZoneSecSize[16] = { 232, 216, 208, 192, 176, 160, 144, 128, + 216, 208, 192, 176, 160, 144, 128, 112 }; + const uint32_t ZoneTracks[16] = { 158, 158, 149, 149, 149, 149, 149, 114, + 158, 158, 149, 149, 149, 149, 149, 114 }; + const uint32_t DiskTypeZones[7][16] = { + { 0, 1, 2, 9, 8, 3, 4, 5, 6, 7, 15, 14, 13, 12, 11, 10 }, + { 0, 1, 2, 3, 10, 9, 8, 4, 5, 6, 7, 15, 14, 13, 12, 11 }, + { 0, 1, 2, 3, 4, 11, 10, 9, 8, 5, 6, 7, 15, 14, 13, 12 }, + { 0, 1, 2, 3, 4, 5, 12, 11, 10, 9, 8, 6, 7, 15, 14, 13 }, + { 0, 1, 2, 3, 4, 5, 6, 13, 12, 11, 10, 9, 8, 7, 15, 14 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8, 15 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 15, 14, 13, 12, 11, 10, 9, 8 } + }; + const uint32_t RevDiskTypeZones[7][16] = { + { 0, 1, 2, 5, 6, 7, 8, 9, 4, 3, 15, 14, 13, 12, 11, 10 }, + { 0, 1, 2, 3, 7, 8, 9, 10, 6, 5, 4, 15, 14, 13, 12, 11 }, + { 0, 1, 2, 3, 4, 9, 10, 11, 8, 7, 6, 5, 15, 14, 13, 12 }, + { 0, 1, 2, 3, 4, 5, 11, 12, 10, 9, 8, 7, 6, 15, 14, 13 }, + { 0, 1, 2, 3, 4, 5, 6, 13, 12, 11, 10, 9, 8, 7, 15, 14 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8, 15 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 15, 14, 13, 12, 11, 10, 9, 8 } + }; + const uint32_t StartBlock[7][16] = { + { 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1 }, + { 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0 }, + { 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1 }, + { 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0 }, + { 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1 }, + { 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0 }, + { 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1 } + }; + + uint32_t disktype = 0; + uint32_t zone, track = 0; + int32_t atrack = 0; + int32_t block = 0; + uint8_t SystemData[0xE8]; + uint8_t BlockData0[0x100 * SECTORS_PER_BLOCK]; + uint8_t BlockData1[0x100 * SECTORS_PER_BLOCK]; + uint32_t InOffset, OutOffset = 0; + uint32_t InStart[16]; + uint32_t OutStart[16]; + + //SDK DISK RAM + WriteTrace(TraceN64System, TraceDebug, "Allocating memory for disk SDK format"); + std::auto_ptr ImageBase(new uint8_t[SDKFormatSize + 0x1000]); + if (ImageBase.get() == NULL) + { + SetError(MSG_MEM_ALLOC_ERROR); + WriteTrace(TraceN64System, TraceError, "Failed to allocate memory for disk SDK format (size: 0x%X)", SDKFormatSize); + return; + } + uint8_t * Image = (uint8_t *)(((uint64_t)ImageBase.get() + 0xFFF) & ~0xFFF); // start at begining of memory page + WriteTrace(TraceN64System, TraceDebug, "Allocated disk SDK format memory (%p)", Image); + + //save information about the disk loaded + uint8_t * s_DiskImageBase = ImageBase.release(); + uint8_t * s_DiskImage = Image; + //END + + InStart[0] = 0; + OutStart[0] = 0; + + //Read System Area + memcpy(&SystemData, m_DiskImage, 0xE8); + + disktype = SystemData[5] & 0xF; + + //Prepare Input Offsets + for (zone = 1; zone < 16; zone++) + { + InStart[zone] = InStart[zone - 1] + + VZONESIZE(DiskTypeZones[disktype][zone - 1]); + } + + //Prepare Output Offsets + for (zone = 1; zone < 16; zone++) + { + OutStart[zone] = OutStart[zone - 1] + ZONESIZE(zone - 1); + } + + //Copy Head 0 + for (zone = 0; zone < 8; zone++) + { + block = StartBlock[disktype][zone]; + atrack = 0; + for (track = 0; track < ZoneTracks[zone]; track++) + { + InOffset = OutStart[zone] + (track)* TRACKSIZE(zone); + OutOffset = InStart[RevDiskTypeZones[disktype][zone]] + (track - atrack) * TRACKSIZE(zone); + + if (atrack < 0xC && track == SystemData[0x20 + zone * 0xC + atrack]) + { + atrack += 1; + } + else + { + if ((block % 2) == 1) + { + memcpy(&BlockData1, m_DiskImage + InOffset, BLOCKSIZE(zone)); + InOffset += BLOCKSIZE(zone); + memcpy(&BlockData0, m_DiskImage + InOffset, BLOCKSIZE(zone)); + InOffset += BLOCKSIZE(zone); + } + else + { + memcpy(&BlockData0, m_DiskImage + InOffset, BLOCKSIZE(zone)); + InOffset += BLOCKSIZE(zone); + memcpy(&BlockData1, m_DiskImage + InOffset, BLOCKSIZE(zone)); + InOffset += BLOCKSIZE(zone); + } + block = 1 - block; + memcpy(s_DiskImage + OutOffset, &BlockData0, BLOCKSIZE(zone)); + OutOffset += BLOCKSIZE(zone); + memcpy(s_DiskImage + OutOffset, &BlockData1, BLOCKSIZE(zone)); + OutOffset += BLOCKSIZE(zone); + } + } + } + + //Copy Head 1 + for (zone = 8; zone < 16; zone++) + { + block = StartBlock[disktype][zone]; + atrack = 0xB; + for (track = 1; track < ZoneTracks[zone] + 1; track++) + { + InOffset = OutStart[zone] + (ZoneTracks[zone] - track) * TRACKSIZE(zone); + OutOffset = InStart[RevDiskTypeZones[disktype][zone]] + (track - (0xB - atrack) - 1) * TRACKSIZE(zone); + + if (atrack > -1 && (ZoneTracks[zone] - track) == SystemData[0x20 + (zone)* 0xC + atrack]) + { + atrack -= 1; + } + else + { + if ((block % 2) == 1) + { + memcpy(&BlockData1, m_DiskImage + InOffset, BLOCKSIZE(zone)); + InOffset += BLOCKSIZE(zone); + memcpy(&BlockData0, m_DiskImage + InOffset, BLOCKSIZE(zone)); + InOffset += BLOCKSIZE(zone); + } + else + { + memcpy(&BlockData0, m_DiskImage + InOffset, BLOCKSIZE(zone)); + InOffset += BLOCKSIZE(zone); + memcpy(&BlockData1, m_DiskImage + InOffset, BLOCKSIZE(zone)); + InOffset += BLOCKSIZE(zone); + } + block = 1 - block; + memcpy(s_DiskImage + OutOffset, &BlockData0, BLOCKSIZE(zone)); + OutOffset += BLOCKSIZE(zone); + memcpy(s_DiskImage + OutOffset, &BlockData1, BLOCKSIZE(zone)); + OutOffset += BLOCKSIZE(zone); + } + } + } + + if (!m_DiskFile.Write(s_DiskImage, SDKFormatSize)) + { + m_DiskFile.Close(); + WriteTrace(TraceN64System, TraceError, "Failed to write file"); + } + + WriteTrace(TraceN64System, TraceDebug, "Unallocating disk SDK format memory"); + delete[] s_DiskImageBase; + s_DiskImageBase = NULL; + s_DiskImage = NULL; } \ No newline at end of file diff --git a/Source/Project64-core/N64System/N64DiskClass.h b/Source/Project64-core/N64System/N64DiskClass.h index 2b3938966..594db44db 100644 --- a/Source/Project64-core/N64System/N64DiskClass.h +++ b/Source/Project64-core/N64System/N64DiskClass.h @@ -18,6 +18,8 @@ public: ~CN64Disk(); bool LoadDiskImage(const char * FileLoc); + bool SaveDiskImage(); + void SwapDiskImage(const char * FileLoc); static bool IsValidDiskImage(uint8_t Test[4]); uint8_t * GetDiskAddress() { return m_DiskImage; } uint8_t * GetDiskAddressBuffer() { return m_DiskImage + m_DiskBufAddress; } @@ -30,11 +32,14 @@ private: bool AllocateDiskImage(uint32_t DiskFileSize); bool AllocateAndLoadDiskImage(const char * FileLoc); void ByteSwapDisk(); + void ForceByteSwapDisk(); void SetError(LanguageStringID ErrorMsg); void ConvertDiskFormat(); + void ConvertDiskFormatBack(); //constant values - enum { ReadFromRomSection = 0x400000, MameFormatSize = 0x0435B0C0, SDKFormatSize = 0x03DEC800 }; + enum { ReadFromRomSection = 0x400000, MameFormatSize = 0x0435B0C0, SDKFormatSize = 0x03DEC800, + DiskFormatMAME = 0x0, DiskFormatSDK = 0x1 }; //class variables CFile m_DiskFile; @@ -44,6 +49,7 @@ private: uint32_t m_DiskBufAddress; LanguageStringID m_ErrorMsg; stdstr m_FileName, m_DiskIdent; + uint8_t m_DiskFormat; //0 = MAME, 1 = SDK //disk convert #define SECTORS_PER_BLOCK 85 diff --git a/Source/Project64-core/N64System/Recompiler/CodeSection.cpp b/Source/Project64-core/N64System/Recompiler/CodeSection.cpp index 9cfc153db..f98aef1c2 100644 --- a/Source/Project64-core/N64System/Recompiler/CodeSection.cpp +++ b/Source/Project64-core/N64System/Recompiler/CodeSection.cpp @@ -1292,6 +1292,7 @@ bool CCodeSection::GenerateX86Code(uint32_t Test) case R4300i_COP1_FUNCT_NEG: COP1_S_NEG(); break; case R4300i_COP1_FUNCT_SQRT: COP1_S_SQRT(); break; case R4300i_COP1_FUNCT_MOV: COP1_S_MOV(); break; + case R4300i_COP1_FUNCT_ROUND_L: COP1_S_ROUND_L(); break; case R4300i_COP1_FUNCT_TRUNC_L: COP1_S_TRUNC_L(); break; case R4300i_COP1_FUNCT_CEIL_L: COP1_S_CEIL_L(); break; //added by Witten case R4300i_COP1_FUNCT_FLOOR_L: COP1_S_FLOOR_L(); break; //added by Witten @@ -1326,6 +1327,7 @@ bool CCodeSection::GenerateX86Code(uint32_t Test) case R4300i_COP1_FUNCT_NEG: COP1_D_NEG(); break; case R4300i_COP1_FUNCT_SQRT: COP1_D_SQRT(); break; case R4300i_COP1_FUNCT_MOV: COP1_D_MOV(); break; + case R4300i_COP1_FUNCT_ROUND_L: COP1_D_ROUND_L(); break; case R4300i_COP1_FUNCT_TRUNC_L: COP1_D_TRUNC_L(); break; //added by Witten case R4300i_COP1_FUNCT_CEIL_L: COP1_D_CEIL_L(); break; //added by Witten case R4300i_COP1_FUNCT_FLOOR_L: COP1_D_FLOOR_L(); break; //added by Witten diff --git a/Source/Project64-core/N64System/Recompiler/RecompilerOps.cpp b/Source/Project64-core/N64System/Recompiler/RecompilerOps.cpp index c7dd1f425..d697e157d 100644 --- a/Source/Project64-core/N64System/Recompiler/RecompilerOps.cpp +++ b/Source/Project64-core/N64System/Recompiler/RecompilerOps.cpp @@ -5946,6 +5946,18 @@ void CRecompilerOps::COP1_S_MOV() Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Float); } +void CRecompilerOps::COP1_S_ROUND_L() +{ + CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(m_Opcode.Hex, m_CompilePC)); + + m_Section->CompileCop1Test(); + if (m_Opcode.fd != m_Opcode.fs || !RegInStack(m_Opcode.fd, CRegInfo::FPU_Float)) + { + Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Float); + } + ChangeFPURegFormat(m_Opcode.fd, CRegInfo::FPU_Float, CRegInfo::FPU_Qword, CRegInfo::RoundNearest); +} + void CRecompilerOps::COP1_S_TRUNC_L() { CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(m_Opcode.Hex, m_CompilePC)); @@ -6296,6 +6308,22 @@ void CRecompilerOps::COP1_D_MOV() Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Double); } +void CRecompilerOps::COP1_D_ROUND_L() +{ + CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(m_Opcode.Hex, m_CompilePC)); + + m_Section->CompileCop1Test(); + if (RegInStack(m_Opcode.fs, CRegInfo::FPU_Double) || RegInStack(m_Opcode.fs, CRegInfo::FPU_Qword)) + { + UnMap_FPR(m_Opcode.fs, true); + } + if (m_Opcode.fd != m_Opcode.fs || !RegInStack(m_Opcode.fd, CRegInfo::FPU_Double)) + { + Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Double); + } + ChangeFPURegFormat(m_Opcode.fd, CRegInfo::FPU_Double, CRegInfo::FPU_Qword, CRegInfo::RoundNearest); +} + void CRecompilerOps::COP1_D_TRUNC_L() //added by Witten { CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(m_Opcode.Hex, m_CompilePC)); diff --git a/Source/Project64-core/N64System/Recompiler/RecompilerOps.h b/Source/Project64-core/N64System/Recompiler/RecompilerOps.h index 0bcc46866..281829bba 100644 --- a/Source/Project64-core/N64System/Recompiler/RecompilerOps.h +++ b/Source/Project64-core/N64System/Recompiler/RecompilerOps.h @@ -160,6 +160,7 @@ protected: static void COP1_S_NEG (); static void COP1_S_SQRT (); static void COP1_S_MOV (); + static void COP1_S_ROUND_L (); static void COP1_S_TRUNC_L (); static void COP1_S_CEIL_L (); //added by Witten static void COP1_S_FLOOR_L (); //added by Witten @@ -181,6 +182,7 @@ protected: static void COP1_D_NEG (); static void COP1_D_SQRT (); static void COP1_D_MOV (); + static void COP1_D_ROUND_L (); static void COP1_D_TRUNC_L (); //added by Witten static void COP1_D_CEIL_L (); //added by Witten static void COP1_D_FLOOR_L (); //added by Witten diff --git a/Source/Project64/Support.h b/Source/Project64/Support.h index 2380ecee0..eb7f72cd1 100644 --- a/Source/Project64/Support.h +++ b/Source/Project64/Support.h @@ -1,6 +1,8 @@ +#if defined(_WIN32) #include +#endif -#include +#include #include #include #include diff --git a/Source/Project64/UserInterface/MainMenuClass.cpp b/Source/Project64/UserInterface/MainMenuClass.cpp index c8fe28eb9..b936f83b0 100644 --- a/Source/Project64/UserInterface/MainMenuClass.cpp +++ b/Source/Project64/UserInterface/MainMenuClass.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "RomInformationClass.h" +#include #include #include @@ -229,6 +230,31 @@ bool CMainMenu::ProcessMessage(HWND hWnd, DWORD /*FromAccelerator*/, DWORD MenuI g_Settings->SaveBool(GameRunning_LimitFPS, !g_Settings->LoadBool(GameRunning_LimitFPS)); WriteTrace(TraceUserInterface, TraceDebug, "ID_SYSTEM_LIMITFPS 1"); break; + case ID_SYSTEM_SWAPDISK: + WriteTrace(TraceUserInterface, TraceDebug, "ID_SYSTEM_SWAPDISK"); + // Open Disk + OPENFILENAME openfilename; + char FileName[_MAX_PATH], Directory[_MAX_PATH]; + + memset(&FileName, 0, sizeof(FileName)); + memset(&openfilename, 0, sizeof(openfilename)); + + strcpy(Directory, g_Settings->LoadStringVal(RomList_GameDir).c_str()); + + openfilename.lStructSize = sizeof(openfilename); + openfilename.hwndOwner = (HWND)hWnd; + openfilename.lpstrFilter = "N64DD Disk Image (*.ndd)\0*.ndd\0All files (*.*)\0*.*\0"; + openfilename.lpstrFile = FileName; + openfilename.lpstrInitialDir = Directory; + openfilename.nMaxFile = MAX_PATH; + openfilename.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; + + if (GetOpenFileName(&openfilename)) + { + g_Disk->SaveDiskImage(); + g_Disk->SwapDiskImage(FileName); + } + break; case ID_SYSTEM_SAVE: WriteTrace(TraceUserInterface, TraceDebug, "ID_SYSTEM_SAVE"); g_BaseSystem->ExternalEvent(SysEvent_SaveMachineState); @@ -868,6 +894,10 @@ void CMainMenu::FillOutMenu(HMENU hMenu) SystemMenu.push_back(Item); SystemMenu.push_back(MENU_ITEM(SPLITER)); } + Item.Reset(ID_SYSTEM_SWAPDISK, MENU_SWAPDISK, m_ShortCuts.ShortCutString(ID_SYSTEM_SWAPDISK, AccessLevel)); + if (g_Disk == NULL) { Item.SetItemEnabled(false); } + SystemMenu.push_back(Item); + SystemMenu.push_back(MENU_ITEM(SPLITER)); SystemMenu.push_back(MENU_ITEM(ID_SYSTEM_SAVE, MENU_SAVE, m_ShortCuts.ShortCutString(ID_SYSTEM_SAVE, AccessLevel))); if (!inBasicMode) { diff --git a/Source/Project64/UserInterface/MainMenuClass.h b/Source/Project64/UserInterface/MainMenuClass.h index d00474463..2d6760c72 100644 --- a/Source/Project64/UserInterface/MainMenuClass.h +++ b/Source/Project64/UserInterface/MainMenuClass.h @@ -18,7 +18,7 @@ enum MainMenuID //System Menu ID_SYSTEM_RESET_SOFT, ID_SYSTEM_RESET_HARD, ID_SYSTEM_PAUSE, ID_SYSTEM_BITMAP, - ID_SYSTEM_LIMITFPS, ID_SYSTEM_RESTORE, ID_SYSTEM_LOAD, ID_SYSTEM_SAVE, + ID_SYSTEM_LIMITFPS, ID_SYSTEM_SWAPDISK, ID_SYSTEM_RESTORE, ID_SYSTEM_LOAD, ID_SYSTEM_SAVE, ID_SYSTEM_SAVEAS, ID_SYSTEM_CHEAT, ID_SYSTEM_GSBUTTON, //Current Save Slot diff --git a/Source/Project64/UserInterface/MenuShortCuts.cpp b/Source/Project64/UserInterface/MenuShortCuts.cpp index 25e50c116..6317ec3d9 100644 --- a/Source/Project64/UserInterface/MenuShortCuts.cpp +++ b/Source/Project64/UserInterface/MenuShortCuts.cpp @@ -316,6 +316,7 @@ void CShortCuts::Load(bool InitialValues) AddShortCut(ID_SYSTEM_PAUSE, STR_SHORTCUT_SYSTEMMENU, MENU_PAUSE, CMenuShortCutKey::GAME_RUNNING); AddShortCut(ID_SYSTEM_BITMAP, STR_SHORTCUT_SYSTEMMENU, MENU_BITMAP, CMenuShortCutKey::GAME_RUNNING); AddShortCut(ID_SYSTEM_LIMITFPS, STR_SHORTCUT_SYSTEMMENU, MENU_LIMIT_FPS, CMenuShortCutKey::GAME_RUNNING); + AddShortCut(ID_SYSTEM_SWAPDISK, STR_SHORTCUT_SYSTEMMENU, MENU_SWAPDISK, CMenuShortCutKey::GAME_RUNNING_WINDOW); AddShortCut(ID_SYSTEM_SAVE, STR_SHORTCUT_SYSTEMMENU, MENU_SAVE, CMenuShortCutKey::GAME_RUNNING); AddShortCut(ID_SYSTEM_SAVEAS, STR_SHORTCUT_SYSTEMMENU, MENU_SAVE_AS, CMenuShortCutKey::GAME_RUNNING_WINDOW); AddShortCut(ID_SYSTEM_RESTORE, STR_SHORTCUT_SYSTEMMENU, MENU_RESTORE, CMenuShortCutKey::GAME_RUNNING); @@ -383,6 +384,7 @@ void CShortCuts::Load(bool InitialValues) m_ShortCuts.find(ID_SYSTEM_PAUSE)->second.AddShortCut(VK_PAUSE, false, false, false, CMenuShortCutKey::GAME_RUNNING); m_ShortCuts.find(ID_SYSTEM_BITMAP)->second.AddShortCut(VK_F3, false, false, false, CMenuShortCutKey::GAME_RUNNING); m_ShortCuts.find(ID_SYSTEM_LIMITFPS)->second.AddShortCut(VK_F4, false, false, false, CMenuShortCutKey::GAME_RUNNING); + m_ShortCuts.find(ID_SYSTEM_SWAPDISK)->second.AddShortCut('D', true, false, false, CMenuShortCutKey::GAME_RUNNING_WINDOW); m_ShortCuts.find(ID_SYSTEM_SAVE)->second.AddShortCut(VK_F5, false, false, false, CMenuShortCutKey::GAME_RUNNING); m_ShortCuts.find(ID_SYSTEM_RESTORE)->second.AddShortCut(VK_F7, false, false, false, CMenuShortCutKey::GAME_RUNNING); m_ShortCuts.find(ID_SYSTEM_LOAD)->second.AddShortCut('L', true, false, false, CMenuShortCutKey::GAME_RUNNING_WINDOW); diff --git a/Source/Project64/main.cpp b/Source/Project64/main.cpp index d403532a9..4b2afb963 100644 --- a/Source/Project64/main.cpp +++ b/Source/Project64/main.cpp @@ -24,7 +24,42 @@ int WINAPI WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR / if (g_Settings->LoadStringVal(Cmd_RomFile).length() > 0) { MainWindow.Show(true); //Show the main window - CN64System::RunFileImage(g_Settings->LoadStringVal(Cmd_RomFile).c_str()); + //N64 ROM or 64DD Disk + stdstr ext = CPath(g_Settings->LoadStringVal(Cmd_RomFile)).GetExtension(); + if (!(_stricmp(ext.c_str(), "ndd") == 0)) + { + //File Extension is not *.ndd so it should be a N64 ROM + CN64System::RunFileImage(g_Settings->LoadStringVal(Cmd_RomFile).c_str()); + } + else + { + //Ext is *.ndd, so it should be a disk file. + if (CN64System::RunDiskImage(g_Settings->LoadStringVal(Cmd_RomFile).c_str())) + { + stdstr IPLROM = g_Settings->LoadStringVal(File_DiskIPLPath); + if ((IPLROM.length() <= 0) || (!CN64System::RunFileImage(IPLROM.c_str()))) + { + // Open DDROM + OPENFILENAME openfilename; + char FileName[_MAX_PATH], Directory[_MAX_PATH]; + memset(&FileName, 0, sizeof(FileName)); + memset(&openfilename, 0, sizeof(openfilename)); + + openfilename.lStructSize = sizeof(openfilename); + //openfilename.hwndOwner = (HWND)hWnd; + openfilename.lpstrFilter = "64DD IPL ROM Image (*.zip, *.7z, *.?64, *.rom, *.usa, *.jap, *.pal, *.bin)\0*.?64;*.zip;*.7z;*.bin;*.rom;*.usa;*.jap;*.pal\0All files (*.*)\0*.*\0"; + openfilename.lpstrFile = FileName; + openfilename.lpstrInitialDir = Directory; + openfilename.nMaxFile = MAX_PATH; + openfilename.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; + + if (GetOpenFileName(&openfilename)) + { + CN64System::RunFileImage(FileName); + } + } + } + } } else {