From 5e2028fb8b2b9e4e7d8ac99d78a4fa08d7d86f3d Mon Sep 17 00:00:00 2001 From: Logan McNaughton <848146+loganmc10@users.noreply.github.com> Date: Sun, 17 Jul 2022 19:11:05 -0600 Subject: [PATCH] update core --- mupen64plus-core/.github/workflows/build.yml | 162 ++++++++----- mupen64plus-core/data/mupen64plus.ini | 221 +----------------- .../projects/msvc/mupen64plus-core.vcxproj | 2 + .../msvc/mupen64plus-core.vcxproj.filters | 6 + mupen64plus-core/projects/unix/Makefile | 5 +- mupen64plus-core/src/api/debugger.c | 2 +- mupen64plus-core/src/api/frontend.c | 1 - mupen64plus-core/src/api/m64p_types.h | 1 - .../src/asm_defines/asm_defines.c | 1 - mupen64plus-core/src/device/cart/cart.c | 26 +-- mupen64plus-core/src/device/cart/cart.h | 8 +- mupen64plus-core/src/device/cart/cart_rom.c | 9 +- mupen64plus-core/src/device/cart/cart_rom.h | 4 +- mupen64plus-core/src/device/cart/flashram.c | 8 +- mupen64plus-core/src/device/cart/flashram.h | 4 +- mupen64plus-core/src/device/cart/sram.c | 8 +- mupen64plus-core/src/device/cart/sram.h | 4 +- .../src/device/dd/dd_controller.c | 26 +-- .../src/device/dd/dd_controller.h | 4 +- mupen64plus-core/src/device/device.c | 4 +- mupen64plus-core/src/device/device.h | 2 - mupen64plus-core/src/device/memory/dcache.c | 96 ++++++++ mupen64plus-core/src/device/memory/dcache.h | 44 ++++ mupen64plus-core/src/device/memory/icache.c | 100 ++++++++ mupen64plus-core/src/device/memory/icache.h | 44 ++++ mupen64plus-core/src/device/memory/memory.c | 3 + mupen64plus-core/src/device/memory/memory.h | 4 + mupen64plus-core/src/device/pif/pif.c | 10 - mupen64plus-core/src/device/pif/pif.h | 2 - .../src/device/r4300/cached_interp.c | 23 +- mupen64plus-core/src/device/r4300/cp0.c | 43 +--- mupen64plus-core/src/device/r4300/cp0.h | 7 +- mupen64plus-core/src/device/r4300/interrupt.c | 16 +- .../src/device/r4300/mips_instructions.def | 109 +++++++-- .../device/r4300/new_dynarec/new_dynarec.c | 3 - .../src/device/r4300/pure_interp.c | 9 +- .../src/device/r4300/r4300_core.c | 142 ++++++----- .../src/device/r4300/r4300_core.h | 7 +- mupen64plus-core/src/device/r4300/recomp.c | 5 +- mupen64plus-core/src/device/r4300/tlb.c | 34 ++- mupen64plus-core/src/device/r4300/tlb.h | 4 +- .../src/device/rcp/ai/ai_controller.c | 6 +- .../src/device/rcp/mi/mi_controller.c | 1 - .../src/device/rcp/pi/pi_controller.c | 62 ++++- .../src/device/rcp/pi/pi_controller.h | 4 +- .../src/device/rcp/rsp/rsp_core.c | 20 +- .../src/device/rcp/si/si_controller.c | 13 -- .../src/device/rcp/si/si_controller.h | 2 - .../src/device/rcp/vi/vi_controller.c | 8 +- mupen64plus-core/src/main/main.c | 16 +- mupen64plus-core/src/main/rom.c | 24 +- mupen64plus-core/src/main/rom.h | 2 - 52 files changed, 770 insertions(+), 601 deletions(-) create mode 100644 mupen64plus-core/src/device/memory/dcache.c create mode 100644 mupen64plus-core/src/device/memory/dcache.h create mode 100644 mupen64plus-core/src/device/memory/icache.c create mode 100644 mupen64plus-core/src/device/memory/icache.h diff --git a/mupen64plus-core/.github/workflows/build.yml b/mupen64plus-core/.github/workflows/build.yml index 6cddb8f..f115043 100644 --- a/mupen64plus-core/.github/workflows/build.yml +++ b/mupen64plus-core/.github/workflows/build.yml @@ -20,31 +20,47 @@ jobs: matrix: include: - cc: GCC + platform: x64 + bits: 64 + - cc: GCC + platform: x86 + bits: 32 - cc: Clang - name: Linux / ${{ matrix.cc }} / x64 | x86 - runs-on: ubuntu-20.04 + platform: x64 + bits: 64 + - cc: Clang + platform: x86 + bits: 32 + name: Linux / ${{ matrix.cc }} / ${{ matrix.platform }} + runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get build dependencies and arrange the environment run: | - sudo dpkg --add-architecture i386 + if [[ "${{ matrix.platform }}" == "x86" ]]; then sudo dpkg --add-architecture i386; fi sudo apt-get update sudo apt-get -y install libfreetype6-dev libgl1-mesa-dev libglu1-mesa-dev libpng-dev libsdl1.2-dev libsdl2-dev nasm zlib1g-dev - sudo apt-get --reinstall -y install gcc-multilib g++-multilib libc6 libc6-dev-i386 libfreetype6:i386 libgl1-mesa-glx:i386 libglu1-mesa:i386 libpng16-16:i386 libsdl1.2debian:i386 libsdl2-2.0-0:i386 zlib1g:i386 - LINK="sudo ln -s -T" - cd /usr/lib/i386-linux-gnu - if ! [[ -f libfreetype.so ]]; then ${LINK} libfreetype.so.6.17.1 libfreetype.so; fi - if ! [[ -f libGL.so ]]; then ${LINK} libGL.so.1.7.0 libGL.so; fi - if ! [[ -f libGLU.so ]]; then ${LINK} libGLU.so.1.3.1 libGLU.so; fi - if ! [[ -f libpng16.so ]]; then ${LINK} libpng16.so.16.37.0 libpng16.so; fi - if ! [[ -f libSDL.so ]]; then ${LINK} libSDL-1.2.so.0.11.4 libSDL.so; fi - if ! [[ -f libSDL2.so ]]; then ${LINK} libSDL2-2.0.so.0.10.0 libSDL2.so; fi - if ! [[ -f libz.so ]]; then ${LINK} libz.so.1.2.11 libz.so; fi - cd /usr/include/SDL2 - if ! [[ -f _real_SDL_config.h ]]; then ${LINK} ../x86_64-linux-gnu/SDL2/_real_SDL_config.h _real_SDL_config.h; fi + if [[ "${{ matrix.platform }}" == "x86" ]]; then + sudo apt-get --reinstall -y install gcc-multilib g++-multilib libc6 libc6-dev-i386 libfreetype6:i386 libgl1-mesa-glx:i386 libglu1-mesa:i386 libpng16-16:i386 libsdl1.2debian:i386 libsdl2-2.0-0:i386 zlib1g:i386 + LINK="sudo ln -s -T" + cd /usr/lib/i386-linux-gnu + if ! [[ -f libfreetype.so ]]; then ${LINK} libfreetype.so.6.18.1 libfreetype.so; fi + if ! [[ -f libGL.so ]]; then ${LINK} libGL.so.1.7.0 libGL.so; fi + if ! [[ -f libGLU.so ]]; then ${LINK} libGLU.so.1.3.1 libGLU.so; fi + if ! [[ -f libpng16.so ]]; then ${LINK} libpng16.so.16.37.0 libpng16.so; fi + if ! [[ -f libSDL.so ]]; then ${LINK} libSDL-1.2.so.0.11.4 libSDL.so; fi + if ! [[ -f libSDL2.so ]]; then ${LINK} libSDL2-2.0.so.0.18.2 libSDL2.so; fi + if ! [[ -f libz.so ]]; then ${LINK} libz.so.1.2.11 libz.so; fi + cd /usr/include/SDL2 + if ! [[ -f _real_SDL_config.h ]]; then ${LINK} ../x86_64-linux-gnu/SDL2/_real_SDL_config.h _real_SDL_config.h; fi + fi sudo ldconfig - name: Build and related stuff run: | + if [[ ${{ matrix.bits }} -eq 32 ]]; then export OPTFLAGS="-O2 -flto -mtune=pentium4"; else export OPTFLAGS="-O2 -flto -mtune=core2"; fi + G_REV=$(git rev-parse --short HEAD) + echo "G_REV=${G_REV}" >> "${GITHUB_ENV}" + ORIG="$(pwd)" if [[ "${{ matrix.cc }}" == "GCC" ]]; then CC="gcc" CXX="g++" @@ -52,40 +68,45 @@ jobs: CC="clang" CXX="clang++" fi + if [[ ${{ matrix.bits }} -eq 32 ]]; then export PIC="1"; fi ${CC} --version - for TSK in 1 2 3 4 5 6 7 8 + SDL="sdl" + MSG="1.2" + mkdir tmp + for DYN in 0 1 0 1 do - unset PIC - if [[ ${TSK} -le 4 ]]; then - SDL="sdl" - MSG="SDL1.2" + if [[ ${DYN} -eq 0 ]]; then + export POSTFIX="-old" else - SDL="sdl2" - MSG="SDL2" - fi - if [[ "${DYN}" == "0" ]]; then - DYN="1" + unset POSTFIX MSG="${MSG} / NEW_DYNAREC" - else - DYN="0" - if [[ "${BITS}" == "64" ]]; then BITS="32"; else BITS="64"; fi - fi - if [[ ${BITS} -eq 32 ]]; then - if [[ "${CC}" == "clang" ]]; then export PIC="1"; fi - MSG="x86 / ${MSG}" - else - MSG="x64 / ${MSG}" fi echo "" - echo ":: ${{ matrix.cc }} ${MSG} ::" + echo ":: ${{ matrix.cc }} ${{ matrix.platform }} / SDL${MSG} ::" echo "" - make -C projects/unix clean + make NEW_DYNAREC="${DYN}" -C projects/unix clean echo "" - make CC="${CC}" CXX="${CXX}" BITS="${BITS}" SDL_CONFIG="${SDL}-config" NEW_DYNAREC="${DYN}" -C projects/unix all + make CC="${CC}" CXX="${CXX}" BITS="${{ matrix.bits }}" SDL_CONFIG="${SDL}-config" NEW_DYNAREC="${DYN}" -C projects/unix all -j4 echo "" - ls -gG projects/unix/*.so* - ldd projects/unix/libmupen64plus.so.2.0.0 + make BITS="${{ matrix.bits }}" NEW_DYNAREC="${DYN}" -C projects/unix install DESTDIR="${ORIG}/tmp" + echo "" + cd tmp/usr/local/lib + ls -gG libmupen64plus${POSTFIX}.so* + ldd libmupen64plus${POSTFIX}.so.2.0.0 + if [[ ${DYN} -eq 1 ]]; then + SDL="sdl2" + MSG="2" + fi + cd "${ORIG}" done + mkdir pkg + if [[ "${CC}" == "gcc" ]]; then tar cvzf pkg/mupen64plus-core-${{ matrix.platform }}-g${G_REV}.tar.gz -C tmp/ "usr"; fi + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: mupen64plus-core-${{ matrix.platform }}-g${{ env.G_REV }} + path: pkg/* + if-no-files-found: ignore MSYS2: strategy: @@ -106,13 +127,14 @@ jobs: run: shell: msys2 {0} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: msys2/setup-msys2@v2 with: msystem: MINGW${{ matrix.bits }} update: true install: >- git + libtool make mingw-w64-${{ matrix.cross }}-gcc mingw-w64-${{ matrix.cross }}-toolchain @@ -123,26 +145,28 @@ jobs: mingw-w64-${{ matrix.cross }}-zlib - name: Build and related stuff run: | - export OPTFLAGS="-O2 -flto" + if [[ ${{ matrix.bits }} -eq 32 ]]; then export OPTFLAGS="-O2 -flto -mtune=pentium4"; else export OPTFLAGS="-O2 -flto -mtune=core2"; fi echo "G_REV=$(git rev-parse --short HEAD)" >> "${GITHUB_ENV}" + ORIG="$(pwd)" CC="gcc" CXX="g++" ${CC} --version - mkdir backup - LIB="-old" + mkdir tmp + export POSTFIX="-old" for DYN in 0 1 do echo "" echo ":: ${{ matrix.cc }} ${{ matrix.platform }} / SDL2${MSG} ::" echo "" - make -C projects/unix clean + make NEW_DYNAREC="${DYN}" -C projects/unix clean echo "" - make CC="${CC}" CXX="${CXX}" BITS="${{ matrix.bits }}" NEW_DYNAREC="${DYN}" -C projects/unix all + make CC="${CC}" CXX="${CXX}" BITS="${{ matrix.bits }}" NEW_DYNAREC="${DYN}" -C projects/unix all -j4 echo "" - cp projects/unix/*.dll backup/mupen64plus${LIB}.dll - ls -gG backup/mupen64plus${LIB}.dll - ldd backup/mupen64plus${LIB}.dll - unset LIB + make BITS="${{ matrix.bits }}" NEW_DYNAREC="${DYN}" -C projects/unix install PLUGINDIR="" SHAREDIR="" BINDIR="" MANDIR="" LIBDIR="" APPSDIR="" ICONSDIR="icons" INCDIR="api" LDCONFIG="true" DESTDIR="${ORIG}/tmp" + echo "" + ls -gG tmp/mupen64plus${POSTFIX}.dll + ldd tmp/mupen64plus${POSTFIX}.dll + unset POSTFIX MSG=" / NEW_DYNAREC" done - name: Copy binaries, dependencies, etc... @@ -162,14 +186,14 @@ jobs: cp -r "${DAT}" ../pkg/ done fi - cd ../backup + cd ../tmp for BIN in *.dll do echo ":: Copying ${BIN}" cp "${BIN}" ../pkg/ done - name: Upload artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: mupen64plus-core-msys2-${{ matrix.platform }}-g${{ env.G_REV }} path: pkg/* @@ -189,8 +213,8 @@ jobs: run: shell: cmd steps: - - uses: actions/checkout@v2 - - uses: microsoft/setup-msbuild@v1.0.3 + - uses: actions/checkout@v3 + - uses: microsoft/setup-msbuild@v1 # with: # vs-version: 16.11 - name: Build and related stuff @@ -226,19 +250,19 @@ jobs: copy "..\..\mupen64plus-win32-deps\SDL2_net-2.0.1\lib\${{ matrix.platform }}\*.dll" . copy "..\..\mupen64plus-win32-deps\zlib-1.2.11\lib\${{ matrix.platform }}\*.dll" . - name: Upload artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: mupen64plus-core-msvc-${{ matrix.platform }}-g${{ env.G_REV }} path: pkg/* Nightly-build: runs-on: ubuntu-latest - needs: [MSYS2, MSVC] + needs: [Linux, MSYS2, MSVC] if: github.ref == 'refs/heads/master' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Download artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: path: binaries - name: Get some tools @@ -251,20 +275,30 @@ jobs: cd binaries for BIN in * do - echo ":: Creating ${BIN}.zip" cd "${BIN}" - zip -r "../../pkg/${BIN}.zip" * + if [[ "${BIN:17:4}" == "msys" ]]; then + echo ":: Creating ${BIN}.zip" + zip -r "../../pkg/${BIN}.zip" * + elif [[ "${BIN:17:4}" == "msvc" ]]; then + echo ":: Creating ${BIN}.zip" + zip -r "../../pkg/${BIN}.zip" * + else + echo ":: Recovering ${BIN}.tar.gz" + mv *.tar.gz ../../pkg/ + fi cd .. done cd ../pkg echo "" - for BIN in *.zip + for BIN in * do ls -gG ${BIN} - tigerdeep -l ${BIN} >> ${BIN:0:16}.tiger.txt - sha256sum ${BIN} >> ${BIN:0:16}.sha256.txt - sha512sum ${BIN} >> ${BIN:0:16}.sha512.txt + tigerdeep -l ${BIN} >> ../${BIN:0:16}.tiger.txt + sha256sum ${BIN} >> ../${BIN:0:16}.sha256.txt + sha512sum ${BIN} >> ../${BIN:0:16}.sha512.txt done + mv ../*.tiger.txt . + mv ../*.sha*.txt . echo "" echo "TIGER:" cat *.tiger.txt diff --git a/mupen64plus-core/data/mupen64plus.ini b/mupen64plus-core/data/mupen64plus.ini index 94270e0..81020ea 100644 --- a/mupen64plus-core/data/mupen64plus.ini +++ b/mupen64plus-core/data/mupen64plus.ini @@ -11,7 +11,6 @@ CRC=B2242748 FFBD61DA Status=1 Rumble=Yes Players=4 -CountPerOp=1 [34AB1DEA3111A233A8B5C5679DE22E83] GoodName=007 - The World is Not Enough (E) (M3) [!] @@ -227,7 +226,6 @@ SaveType=Eeprom 4KB Mempak=Yes Rumble=Yes Status=5 -CountPerOp=1 [88763C3FD50E036BBB9CF504F77C0741] GoodName=64 Oozumou (J) [b1] @@ -273,7 +271,6 @@ Players=4 Status=2 SaveType=Eeprom 4KB Mempak=Yes -CountPerOp=1 [11B20CFE8E3ECCC680AA8157A7906D6D] GoodName=64 de Hakken!! Tamagotchi Minna de Tamagotchi World (J) [b1] @@ -622,7 +619,6 @@ SaveType=Eeprom 4KB Mempak=Yes Status=4 Rumble=Yes -CountPerOp=1 [DCFB92A4B106FE61E54579B1D3B7336E] GoodName=Airboarder 64 (E) [f1] (NTSC) @@ -642,7 +638,6 @@ Status=4 Rumble=Yes SaveType=Eeprom 4KB Mempak=Yes -CountPerOp=1 [F558165311C9CDCA73FB089E298F2056] GoodName=Airboarder 64 (J) [b1] @@ -950,7 +945,6 @@ Status=3 [53E2872612760133AB7B2CC2E22B847C] GoodName=Army Men - Sarge's Heroes (E) (M3) [!] CRC=B210DF19 98B58D1A -CountPerOp=1 Players=4 SaveType=None Mempak=Yes @@ -959,7 +953,6 @@ Rumble=Yes [B8085C2EDB1C6D23E52ED8C06D92B4F8] GoodName=Army Men - Sarge's Heroes (U) [!] CRC=862C0657 8DFD896D -CountPerOp=1 SaveType=None Mempak=Yes Players=4 @@ -994,7 +987,6 @@ RefMD5=B8085C2EDB1C6D23E52ED8C06D92B4F8 [6EEA5C4A6256092ED8F9BA8861C689C6] GoodName=Army Men - Sarge's Heroes 2 (U) [!] CRC=B20F73B6 2975FC34 -CountPerOp=1 Players=4 SaveType=None Mempak=Yes @@ -1365,7 +1357,6 @@ GoodName=Bass Hunter 64 (E) [!] CRC=B088FBB4 441E4B1D Players=1 SaveType=Eeprom 4KB -CountPerOp=1 Rumble=Yes [2C618F6C69C3B4803F08762A03835139] @@ -1373,7 +1364,6 @@ GoodName=Bass Rush - ECOGEAR PowerWorm Championship (J) [!] CRC=D76333AC 0CB6219D Players=1 Rumble=Yes -CountPerOp=1 [B1AB1D5B3B92B0ACA380D0291DA0689E] GoodName=Bass Rush - ECOGEAR PowerWorm Championship (J) [b1] @@ -1391,7 +1381,6 @@ CRC=BCFACCAA B814D8EF Players=4 SaveType=None Mempak=Yes -CountPerOp=1 Rumble=Yes [D8903586B5E479E6C4937879650D0D2D] @@ -1443,7 +1432,6 @@ RefMD5=A5EE8A6C34863E3D0EB8C06AE8668B30 [3406A505C22BAC2F40D9BFC6FF08CF86] GoodName=BattleTanx (U) [!] CRC=6AA4DDE7 E3E2F4E7 -CountPerOp=3 SaveType=None Mempak=Yes Players=4 @@ -1472,7 +1460,6 @@ RefMD5=3406A505C22BAC2F40D9BFC6FF08CF86 [D6E667FE10AFE8F7116888EFDE98AE0E] GoodName=BattleTanx - Global Assault (E) (M3) [!] CRC=0CAD17E6 71A5B797 -CountPerOp=1 Players=4 SaveType=None Mempak=Yes @@ -1481,7 +1468,6 @@ Rumble=Yes [654557C316F901A2CA6F7F4B43343147] GoodName=BattleTanx - Global Assault (U) [!] CRC=75A4E247 6008963D -CountPerOp=3 Players=4 SaveType=None Mempak=Yes @@ -1511,7 +1497,6 @@ CRC=A1B64A61 D014940B Players=4 SaveType=None Mempak=Yes -CountPerOp=3 Rumble=Yes [9D5A1B779F8B43E63E8CE8427675A7EF] @@ -1530,7 +1515,6 @@ CRC=9C7318D2 24AE0DC1 Players=4 SaveType=None Mempak=Yes -CountPerOp=3 Rumble=Yes [E126B84FA242916289D04D68C0E20BFE] @@ -1544,7 +1528,6 @@ CRC=EDF419A8 BF1904CC SaveType=None Mempak=Yes Players=4 -CountPerOp=3 Rumble=Yes [D11BC38F26EA2835FBF017FE9BD404FE] @@ -1679,7 +1662,6 @@ GoodName=Biohazard 2 (J) [!] CRC=7EAE2488 9D40A35A SaveType=SRAM Players=1 -CountPerOp=1 Rumble=Yes [13D7834291A311077B84B9A2816AF6FC] @@ -1779,7 +1761,6 @@ GoodName=Body Harvest (E) (M3) [!] CRC=0B58B8CD B7B291D2 SaveType=Eeprom 4KB Players=1 -CountPerOp=1 Rumble=Yes [0EF2448C243F86C4C9F194F49CFD8352] @@ -1792,7 +1773,6 @@ GoodName=Body Harvest (U) [!] CRC=5326696F FE9A99C3 Players=1 SaveType=Eeprom 4KB -CountPerOp=1 Rumble=Yes [77554810629D4EF4D93519745FA6066B] @@ -1820,7 +1800,6 @@ GoodName=Bokujou Monogatari 2 (J) (V1.0) [!] CRC=B3D451C6 E1CB58E2 Players=1 Mempak=Yes -CountPerOp=1 [C902BB7203C6C77DDA16ABCDF8995E32] GoodName=Bokujou Monogatari 2 (J) (V1.0) [b1] @@ -2030,7 +2009,6 @@ CRC=D72FD14D 1FED32C4 SaveType=None Mempak=Yes Players=2 -CountPerOp=1 [6E207C47FAAD2A4F64AE721A3A8F6161] GoodName=Bottom of the 9th (U) [b1] @@ -2110,7 +2088,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [5BF0F2351AEE577A8345D6E13D197E06] GoodName=Bug's Life, A (E) [f1] (NTSC) @@ -2124,7 +2101,6 @@ SaveType=None Mempak=Yes Rumble=Yes Players=1 -CountPerOp=1 [504C92A5978B7EAE7A3FD30645E06D39] GoodName=Bug's Life, A (F) [f1] (NTSC) @@ -2138,7 +2114,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [919E5D60A7F9A79D89AC179123D47EEE] GoodName=Bug's Life, A (G) [f1] (NTSC) @@ -2152,7 +2127,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [7FD6BFFB80F920E01EF869829D485EA3] GoodName=Bug's Life, A (U) [!] @@ -2161,7 +2135,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [14ACC20454B0C2789C9F7EF7A556231A] GoodName=Bug's Life, A (U) [b1] @@ -2397,7 +2370,6 @@ CRC=CA2A7444 71DAB71C SaveType=None Mempak=Yes Players=2 -CountPerOp=1 Rumble=Yes [965AD2FA317F0644E49A89A3219719CB] @@ -2406,7 +2378,6 @@ CRC=AC16400E CF5D071A SaveType=None Mempak=Yes Players=2 -CountPerOp=1 Rumble=Yes [C95353C14C4AE3DC95D1D91D6566EF92] @@ -2431,7 +2402,6 @@ Players=2 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [A5DB496C328C36682EB770CEFE6C2064] GoodName=Carmageddon 64 (E) (M4) (Eng-Spa-Fre-Ger) [f1] (NTSC) @@ -2445,7 +2415,6 @@ Players=2 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [D5271DB3CBE6B24099DCC6878C137FF7] GoodName=Carmageddon 64 (E) (M4) (Eng-Spa-Fre-Ita) [b1] @@ -2469,7 +2438,6 @@ Players=2 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [57146B6CD8EE7D96B01A811F98A1AC61] GoodName=Castlevania (E) (M3) [!] @@ -2765,7 +2733,6 @@ GoodName=Charlie Blast's Territory (E) [!] CRC=FB3C48D0 8D28F69F SaveType=None Players=4 -CountPerOp=1 Rumble=Yes [A7C15E0C1E7D898C1B20276DF7A62660] @@ -2778,7 +2745,6 @@ GoodName=Charlie Blast's Territory (U) [!] CRC=1E0E96E8 4E28826B SaveType=None Players=4 -CountPerOp=1 Rumble=Yes [7FFD84FC7D112EAB4EEF15CB10189A38] @@ -2936,7 +2902,6 @@ Players=2 SaveType=Eeprom 16KB Mempak=Yes Rumble=Yes -CountPerOp=1 [4808E8129B22AC8B3185B37243113005] GoodName=City-Tour GP - Zennihon GT Senshuken (J) [b1] @@ -3409,7 +3374,6 @@ CRC=17C54A61 4A83F2E7 Players=1 SaveType=Eeprom 16KB Rumble=Yes -CountPerOp=1 [BA99C445ADC6994C97FE6463F3E0EC10] GoodName=Densha de Go! 64 (J) [f1] (PAL) @@ -3442,7 +3406,6 @@ CRC=630AA37D 896BD7DB Players=4 SaveType=None Mempak=Yes -CountPerOp=1 Rumble=Yes [7FCCB47498EEC06E96AE9372247D1E90] @@ -3451,7 +3414,6 @@ CRC=DEE584A2 0F161187 Players=4 SaveType=None Mempak=Yes -CountPerOp=1 Rumble=Yes [02EEF6ED11174664A548626337879E8C] @@ -3688,7 +3650,6 @@ CRC=C16C421B A21580F7 Players=1 SaveType=None Mempak=Yes -CountPerOp=3 [BD1DE2FC1CF31096423563A40ECBF933] GoodName=Disney's Tarzan (E) [!] @@ -3697,7 +3658,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [AF740B224E5DD0BD09F7254811559ADF] GoodName=Disney's Tarzan (E) [h1C] @@ -3711,7 +3671,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [DF3CDD959E8C63B45F557FC197CE0E63] GoodName=Disney's Tarzan (G) [!] @@ -3720,7 +3679,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [A29E203DDB6293B7D105BF4A2EEEDD1E] GoodName=Disney's Tarzan (G) [h1C] @@ -3734,7 +3692,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [C56AD8ABD0FB5EFEF1FA0229F9A2EFF0] GoodName=Disney's Tarzan (U) [f1] (PAL) @@ -3997,7 +3954,6 @@ CRC=3DF17480 193DED5A Players=1 SaveType=None Mempak=Yes -CountPerOp=3 [07C4944DDAAD234F1F6B0B200BEA60B2] GoodName=Donald Duck - Quack Attack (E) (M5) [b1] @@ -4024,7 +3980,6 @@ CRC=11936D8C 6F2C4B43 SaveType=Eeprom 16KB Players=4 Rumble=Yes -CountPerOp=1 [428067DC7DB42DFC977A775F0A6E55B1] GoodName=Donkey Kong 64 (E) [b1] @@ -4046,14 +4001,12 @@ GoodName=Donkey Kong 64 (J) [!] CRC=053C89A7 A5064302 SaveType=Eeprom 16KB Players=4 -CountPerOp=1 Rumble=Yes [98A5836E3A5DA7BD0B5819E7498ACEA2] GoodName=Donkey Kong 64 (U) (Kiosk Demo) [!] CRC=0DD4ABAB B5A2A91E SaveType=Eeprom 16KB -CountPerOp=1 Rumble=Yes [843DB032839BF1AA74759F2E39A2ABDC] @@ -4076,7 +4029,6 @@ GoodName=Donkey Kong 64 (U) [!] CRC=EC58EABF AD7C7169 SaveType=Eeprom 16KB Players=4 -CountPerOp=1 Rumble=Yes [6B4772AA1743FEAC1919618B3FC6B3E1] @@ -4367,7 +4319,6 @@ GoodName=Duck Dodgers Starring Daffy Duck (U) (M3) [!] CRC=FBB9F1FA 6BF88689 Players=1 SaveType=Eeprom 4KB -CountPerOp=1 Rumble=Yes [B5A5A71483679DCCACBDA770647A9DBF] @@ -4381,7 +4332,6 @@ CRC=DC36626A 3F3770CB Players=4 SaveType=None Mempak=Yes -CountPerOp=1 Rumble=Yes [51A1EEE441240229BEB2E6CD8FAB285C] @@ -4395,7 +4345,6 @@ CRC=32CA974B B2C29C50 Players=4 SaveType=None Mempak=Yes -CountPerOp=1 Rumble=Yes [026789D47DB5FE202A76F89797B33AC7] @@ -4404,7 +4353,6 @@ CRC=04DAF07F 0D18E688 Players=4 SaveType=None Mempak=Yes -CountPerOp=1 Rumble=Yes [69ED326664E48BAA9CE743E6E9C450DA] @@ -4634,7 +4582,6 @@ GoodName=Elmo's Letter Adventure (U) [!] CRC=F2A653CB 60633B3B SaveType=None Players=1 -CountPerOp=1 [F733453ED26AFA0ACA8D3EB3B5B6D8EA] GoodName=Elmo's Number Journey (U) [!] @@ -4678,7 +4625,6 @@ CRC=D49DFF90 8DB53A8C [F4B41863440137C6A3BA22942F3E0DA2] GoodName=Excitebike 64 (Ch) (iQue) [!] Players=4 -CountPerOp=1 [876F87C91A4B6339DAA8FC1F41EB7ACD] GoodName=Excitebike 64 (Ch) (iQue) (Manual) [!] @@ -4688,7 +4634,6 @@ GoodName=Excitebike 64 (E) [!] CRC=202A8EE4 83F88B89 SaveType=Eeprom 16KB Players=4 -CountPerOp=1 Mempak=Yes Rumble=Yes @@ -4712,7 +4657,6 @@ GoodName=Excitebike 64 (U) (V1.0) [!] CRC=07861842 A12EBC9F SaveType=Eeprom 16KB Players=4 -CountPerOp=1 Mempak=Yes Rumble=Yes @@ -4736,7 +4680,6 @@ GoodName=Excitebike 64 (U) (V1.1) [!] CRC=F9D411E3 7CB29BC0 SaveType=Eeprom 16KB Players=4 -CountPerOp=1 Mempak=Yes Rumble=Yes @@ -5331,7 +5274,6 @@ CRC=66CF0FFE AD697F9C Players=2 SaveType=None Mempak=Yes -CountPerOp=1 Rumble=Yes [E7008D17FD71D9C2BDA1362C885388B2] @@ -5340,7 +5282,6 @@ CRC=32EFC7CB C3EA3F20 Players=2 SaveType=None Mempak=Yes -CountPerOp=1 Rumble=Yes [13962910EFD82C2A2333CF38EE1FCD96] @@ -5380,7 +5321,6 @@ CRC=22E9623F B60E52AD SaveType=None Mempak=Yes Players=2 -CountPerOp=1 Rumble=Yes [272B359D8F8AC48ACBF053C262F422E4] @@ -5389,7 +5329,6 @@ CRC=A92D52E5 1D26B655 SaveType=None Mempak=Yes Players=2 -CountPerOp=1 Rumble=Yes [46E9A352AD6AFB83B0557EC659957B2E] @@ -5526,7 +5465,6 @@ CRC=F774EAEE F0D8B13E Players=1 SaveType=SRAM Mempak=Yes -CountPerOp=1 [316C59DAE45C20250A0419A937E7D65B] GoodName=G.A.S.P!! Fighter's NEXTream (E) [!] @@ -5570,7 +5508,6 @@ GoodName=GT 64 - Championship Edition (E) (M3) [!] CRC=EE4A0E33 8FD588C9 SaveType=Eeprom 16KB Players=2 -CountPerOp=1 Mempak=Yes Rumble=Yes @@ -5594,7 +5531,6 @@ GoodName=GT 64 - Championship Edition (U) [!] CRC=C49ADCA2 F1501B62 Players=2 SaveType=Eeprom 16KB -CountPerOp=1 Mempak=Yes Rumble=Yes @@ -5665,7 +5601,6 @@ CRC=457B9CD9 09C55352 Players=2 SaveType=SRAM Rumble=Yes -CountPerOp=1 [7EB07675E2E9CB547A3B238AA71F57CC] GoodName=Ganbare Goemon - Derodero Douchuu Obake Tenkomori (J) [t1] @@ -5691,7 +5626,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [7F4E8F2ECF04BE27E660AC2EFDAC0C68] GoodName=Ganbare Goemon - Neo Momoyama Bakufu no Odori (J) [b1] @@ -5727,7 +5661,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [0806E6DB8B2BF0501BE9F2D78D280DCF] GoodName=Gauntlet Legends (E) [b1] @@ -5741,7 +5674,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [9CB963E8B71F18568F78EC1AF120362E] GoodName=Gauntlet Legends (U) [!] @@ -5750,7 +5682,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [50F8E73CA0160EB1A339AC2137A7B559] GoodName=Gauntlet Legends (U) [f1] (PAL) @@ -5891,7 +5822,6 @@ Players=2 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [231BAC1AFB3DE138072C2D697783059B] GoodName=Golden Nugget 64 (U) [!] @@ -6057,7 +5987,6 @@ GoodName=HSV Adventure Racing (A) [!] CRC=72611D7D 9919BDD2 Players=4 SaveType=None -CountPerOp=3 Rumble=Yes Mempak=Yes @@ -6076,17 +6005,14 @@ GoodName=Hamster Monogatari 64 (J) [!] CRC=95A80114 E0B72A7F Players=1 Mempak=Yes -CountPerOp=1 [617197EF2B6B51E58488C9F6B75F112E] GoodName=Hard Coded Demo by Silo and Fractal (PD) [a1] CRC=775AFA9C 0EB52EF6 -CountPerOp=1 [FB8974C6130A6B8585EA98D6661553BC] GoodName=Hard Coded Demo by Silo and Fractal (PD) CRC=775AFA9C 0EB52EF6 -CountPerOp=1 [193913BB063F3D945019E8F765F48F1C] GoodName=Hard Pom '99 Demo by TS_Garp (POM '99) (PD) @@ -6119,7 +6045,6 @@ GoodName=Harvest Moon 64 (U) [!] CRC=98DF9DFC 6606C189 Players=1 SaveType=SRAM -CountPerOp=1 [3CDD87026EFEC9A03648D225F97858A5] GoodName=Harvest Moon 64 (U) [T+Pol001] @@ -6187,7 +6112,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [6BBD8C42F6EF8F5B9541D6F4DB657DD7] GoodName=Hercules - The Legendary Journeys (U) [!] @@ -6196,7 +6120,7 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 +SiDmaDuration=140000 [57D8E020643146B325A11612FEFACF74] GoodName=Hercules - The Legendary Journeys (U) [o1] @@ -6224,7 +6148,6 @@ CRC=95B2B30B 2B6415C1 Players=4 SaveType=None Mempak=Yes -CountPerOp=1 [E86A8BF46985B7CE8459AFBE5FC3DCC3] GoodName=Hexen (E) [h1C] @@ -6237,7 +6160,6 @@ CRC=5C1B5FBD 7E961634 Players=4 SaveType=None Mempak=Yes -CountPerOp=1 [08CBB141DEC604E4DAD2787F237D57A2] GoodName=Hexen (G) [!] @@ -6245,7 +6167,6 @@ CRC=9AB3B50A BC666105 Players=4 SaveType=None Mempak=Yes -CountPerOp=1 [35E9ECE11306EF7D8F5F09F65761D365] GoodName=Hexen (G) [h1C] @@ -6258,7 +6179,6 @@ CRC=66751A57 54A29D6E Players=4 SaveType=None Mempak=Yes -CountPerOp=1 [EB98F1B8C6898AF7417F6882946DA9B3] GoodName=Hexen (U) [!] @@ -6266,7 +6186,6 @@ CRC=9CAB6AEA 87C61C00 Players=4 SaveType=None Mempak=Yes -CountPerOp=1 [B06625703DB3A03BAE3D02FD0F904541] GoodName=Hexen (U) [b1] @@ -6294,7 +6213,7 @@ CRC=D3F10E5D 052EA579 Players=1 SaveType=Eeprom 4KB Rumble=Yes -AiDmaModifier=88 +AiDmaModifier=83 [DCC316EFFC4928F5B0AE8D273D8024BF] GoodName=HiRes CFB Demo (PD) @@ -6307,7 +6226,6 @@ Players=2 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [8976913EFBE98EFED3B0B32CBCAA8B49] GoodName=Hiryuu no Ken Twin (J) [h1C] @@ -6522,7 +6440,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [1F57194EA272CF5DB500D228E9C94D75] GoodName=Hydro Thunder (E) [f1] (NTSC) @@ -6536,7 +6453,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [54F43E6B68782E98CAABEA5E7976B2BE] GoodName=Hydro Thunder (U) [!] @@ -6545,7 +6461,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [22AAD544C062FB8A2DC6B2DEB32DE188] GoodName=Hydro Thunder (U) [b1] @@ -6658,7 +6573,6 @@ CRC=8C138BE0 95700E46 SaveType=Eeprom 4KB Players=1 Rumble=Yes -CountPerOp=1 [1AF93922A67085AB2C777B1F08AF365B] GoodName=In-Fisherman Bass Hunter 64 (U) [f1] (PAL) @@ -6748,7 +6662,6 @@ CRC=E2D37CF0 F57E4EAE Players=4 SaveType=None Mempak=Yes -CountPerOp=1 [7FCC22F4BF1FC82F886C455981D2A420] GoodName=International Superstar Soccer 64 (E) [b1] @@ -6776,7 +6689,6 @@ CRC=5F2763C4 62412AE5 Players=4 SaveType=None Mempak=Yes -CountPerOp=1 [C0969E1C141BE6E144E651CAB1AEA3D8] GoodName=International Superstar Soccer 64 (U) [b1] @@ -7118,14 +7030,12 @@ GoodName=Jikkyou Powerful Pro Yakyuu - Basic Ban 2001 (J) (V1.0) [!] CRC=6EDD4766 A93E9BA8 Players=4 Mempak=Yes -CountPerOp=3 [F13D0803885B73B4A6B35EDDD40B9253] GoodName=Jikkyou Powerful Pro Yakyuu - Basic Ban 2001 (J) (V1.1) [!] CRC=B00E3829 29F232D1 Players=4 Mempak=Yes -CountPerOp=3 [23409668A6E6C4ECE7B5FB0B7D0E8F2C] GoodName=Jikkyou Powerful Pro Yakyuu 2000 (J) (V1.0) [!] @@ -7262,7 +7172,6 @@ GoodName=Jikkyou World Soccer 3 (J) [!] CRC=E0A79F8C 32CC97FA Players=4 Mempak=Yes -CountPerOp=1 [68230D510015FF6817EF898C0B8B636C] GoodName=Jinsei Game 64 (J) [!] @@ -7668,7 +7577,6 @@ Players=2 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=3 [26B5EAA13DC5B5E35307FE8C0CF5B6BA] GoodName=LEGO Racers (U) (M10) [!] @@ -7677,7 +7585,6 @@ Players=2 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=3 [97C4CAE584F427EC44266E9B98FBF7B6] GoodName=LEGO Racers (U) (M10) [b1] @@ -8388,7 +8295,6 @@ GoodName=Lt. Duck Dodgers (Prototype) CRC=FBB9F1FA 6BF88689 Players=1 Rumble=Yes -CountPerOp=1 [7A99628EDF0A6602D0C408F31B701435] GoodName=Lylat Wars (A) (M3) [!] @@ -8723,7 +8629,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [441FA65FAA5C12339F89A0BB7DB43C8F] GoodName=Madden NFL 2001 (U) [!] @@ -8732,7 +8637,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [AD0F2EC565D7575FB37512BC8DF8A092] GoodName=Madden NFL 2002 (U) [!] @@ -8741,7 +8645,6 @@ SaveType=None Mempak=Yes Rumble=Yes Players=4 -CountPerOp=1 [E7BF80861A0AB2A788959463D953B5D5] GoodName=Madden NFL 99 (E) [!] @@ -8750,7 +8653,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [9CB5F5CD6AB141454D645C92FD9BF67C] GoodName=Madden NFL 99 (E) [h1C] @@ -8764,7 +8666,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [C049FCD4CB185A553D8122CFE6C30139] GoodName=Madden NFL 99 (U) [o1] @@ -8778,7 +8679,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [5F3D42D5F96191F3CE50D70E0E42127A] GoodName=Madden NFL 99 (Beta) (1998-08-05) [!] @@ -9316,7 +9216,6 @@ CRC=9C663069 80F24A80 Players=4 SaveType=Eeprom 4KB Rumble=Yes -CountPerOp=1 [2608A4D7A695D0B1A1BBC47695EACE0E] GoodName=Mario Party (E) (M3) [b1] @@ -9334,7 +9233,6 @@ CRC=ADA815BE 6028622F Players=4 SaveType=Eeprom 4KB Rumble=Yes -CountPerOp=1 [8BC2712139FBF0C56C8EA835802C52DC] GoodName=Mario Party (U) [!] @@ -9342,7 +9240,6 @@ CRC=2829657E A0621877 Players=4 SaveType=Eeprom 4KB Rumble=Yes -CountPerOp=1 [D072DDBCC5961AE85E6FA9BF50241370] GoodName=Mario Party (U) [f1] (PAL) @@ -9355,7 +9252,6 @@ CRC=82380387 DFC744D9 Players=4 SaveType=Eeprom 4KB Rumble=Yes -CountPerOp=1 [F23E4CD437465F3E725262253CF3EA59] GoodName=Mario Party 2 (J) [!] @@ -9363,7 +9259,6 @@ CRC=ED567D0F 38B08915 Players=4 SaveType=Eeprom 4KB Rumble=Yes -CountPerOp=1 [04840612A35ECE222AFDB2DFBF926409] GoodName=Mario Party 2 (U) [!] @@ -9371,7 +9266,6 @@ CRC=9EA95858 AF72B618 Players=4 SaveType=Eeprom 4KB Rumble=Yes -CountPerOp=1 [F253C5A0FB69AB56A1548D435AF84D0F] GoodName=Mario Party 2 (U) [f1] (PAL) @@ -9389,7 +9283,6 @@ CRC=C5674160 0F5F453C SaveType=Eeprom 16KB Players=4 Rumble=Yes -CountPerOp=1 [ED99F330CE7A2638AB13351012EEB86B] GoodName=Mario Party 3 (J) [!] @@ -9397,7 +9290,6 @@ CRC=0B0AB4CD 7B158937 SaveType=Eeprom 16KB Players=4 Rumble=Yes -CountPerOp=1 [76A8BBC81BC2060EC99C9645867237CC] GoodName=Mario Party 3 (U) [!] @@ -9405,7 +9297,6 @@ CRC=7C3829D9 6E8247CE SaveType=Eeprom 16KB Players=4 Rumble=Yes -CountPerOp=1 [BDD79F498F37D01B8958F56EC6FFA097] GoodName=Mario Party 3 (U) [f1] @@ -9429,7 +9320,6 @@ Status=2 Players=1 SaveType=Flash RAM Rumble=Yes -CountPerOp=1 [FFF9B3E22ABB9B60215DAFB13AD5A4DE] GoodName=Mario Tennis (E) [!] @@ -9756,7 +9646,6 @@ GoodName=Mischief Makers (E) [!] CRC=418BDA98 248A0F58 Players=1 SaveType=Eeprom 4KB -CountPerOp=1 [5690D74157C6623E2928A6F0353EF4AF] GoodName=Mischief Makers (E) [b1] @@ -9768,7 +9657,6 @@ GoodName=Mischief Makers (U) (V1.0) [!] CRC=0B93051B 603D81F9 Players=1 SaveType=Eeprom 4KB -CountPerOp=1 [CCF012DF82022D4797CE4CC5405E084F] GoodName=Mischief Makers (U) (V1.0) [b1] @@ -9785,7 +9673,6 @@ GoodName=Mischief Makers (U) (V1.1) [!] CRC=BFA526B4 0691E430 Players=1 SaveType=Eeprom 4KB -CountPerOp=1 [599B5D40B51F53C2C9A909E0139702FC] GoodName=Mission Impossible (E) [!] @@ -9915,7 +9802,6 @@ GoodName=Monopoly (U) [!] CRC=5AC383E1 D712E387 Players=4 SaveType=Eeprom 4KB -CountPerOp=1 [26C3654D20B8718A75B5FE8DA5B3284A] GoodName=Monopoly (U) [f1] (PAL) @@ -9928,7 +9814,6 @@ CRC=D3D806FC B43AA2A8 Players=4 SaveType=None Rumble=Yes -CountPerOp=3 [12534DAB32DBFC6CA4F66D05729102E6] GoodName=Monster Truck Madness 64 (E) (M5) [f1] (NTSC) @@ -9941,7 +9826,6 @@ CRC=B19AD999 7E585118 Players=4 SaveType=None Rumble=Yes -CountPerOp=3 [3C9F329D5E0C7FE57355B8DC68F79331] GoodName=Monster Truck Madness 64 (U) [t1] @@ -10297,7 +10181,6 @@ Players=2 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [75AD771425CBE2B1E8C7B4D94E67B1CA] GoodName=Mystical Ninja 2 Starring Goemon (E) (M3) [hI] @@ -10316,7 +10199,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [DBD2BC43FCDADACD234AEFC8130A5413] GoodName=Mystical Ninja Starring Goemon (E) [b1] @@ -10340,7 +10222,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [42E282A3F208C4BDE50A4A4301181B16] GoodName=Mystical Ninja Starring Goemon (U) [h1C] @@ -10584,7 +10465,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [F8F87AEB2C537C9CB2E9913050BFC928] GoodName=NBA In the Zone 2 (J) [!] @@ -10744,7 +10624,6 @@ CRC=3FFE80F4 A7C15F7E Players=4 SaveType=None Mempak=Yes -CountPerOp=1 [76DB89759121710C416ECFB1736B5E39] GoodName=NBA Showtime - NBA on NBC (U) [f1] (Country Check) @@ -11272,7 +11151,6 @@ RefMD5=4116CF435DB315A2481AF8D1E9352FEB GoodName=Nintama Rantarou 64 Game Gallery (J) [!] CRC=CD3C3CDF 317793FA Players=4 -CountPerOp=1 [66DB457B130D31A286A23D6E4DD9726E] GoodName=Nintendo All-Star! Dairantou Smash Brothers (J) [!] @@ -11281,7 +11159,6 @@ Status=3 Players=4 SaveType=SRAM Rumble=Yes -CountPerOp=1 [B2DF29627E0219A9C14605F46803C94C] GoodName=Nintendo All-Star! Dairantou Smash Brothers (J) [b1] @@ -11353,7 +11230,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [59C28E02BAF4065051C63EA51736892A] GoodName=Nuclear Strike 64 (E) (M2) [h1C] @@ -11367,7 +11243,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [FFC584040D0D052FBAB4CB6C19245449] GoodName=Nuclear Strike 64 (U) [!] @@ -11376,7 +11251,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [76C8EFDD11F6D2E553055B801A022653] GoodName=Nuclear Strike 64 (U) [b1] @@ -11400,7 +11274,6 @@ Players=1 Mempak=Yes Rumble=Yes Transferpak=Yes -CountPerOp=1 [7412417C50A42427637575A3CD2E652E] GoodName=Nushi Tsuri 64 (J) (V1.0) [b1] @@ -11434,7 +11307,6 @@ Players=1 Mempak=Yes Rumble=Yes Transferpak=Yes -CountPerOp=1 [828E0C399C0AA7E3B047859F4FAD3550] GoodName=Nushi Tsuri 64 - Shiokaze ni Notte (J) [b1] @@ -11452,7 +11324,6 @@ CRC=5B9B1618 1B43C649 Players=1 Rumble=Yes Transferpak=Yes -CountPerOp=1 [E2FB4F16A039A0E302D28ACA94D5D928] GoodName=O.D.T. (E) (M5) [!] @@ -11725,7 +11596,6 @@ Status=2 Players=1 SaveType=Flash RAM Rumble=Yes -CountPerOp=1 [A722F8161FF489943191330BF8416496] GoodName=Paper Mario (U) [!] @@ -11734,7 +11604,6 @@ Status=2 Players=1 SaveType=Flash RAM Rumble=Yes -CountPerOp=1 [8595BA0A0D2EA73944228BDED4A969AD] GoodName=Paper Mario (U) [T+Chi] @@ -11894,7 +11763,7 @@ CRC=3F245305 FC0B74AA Players=1 SaveType=Eeprom 4KB Rumble=Yes -AiDmaModifier=88 +AiDmaModifier=83 [D0AE6C07AC0481EBA5FF9CE798A69574] GoodName=Pikachu Genki Dechu (J) [b1] @@ -11906,7 +11775,6 @@ GoodName=Pilotwings 64 (E) (M3) [!] CRC=1AA05AD5 46F52D80 Players=1 SaveType=Eeprom 4KB -CountPerOp=3 [F21E2A3A05ACF49586F32DCE5C449FE4] GoodName=Pilotwings 64 (E) (M3) [b1] @@ -11928,7 +11796,6 @@ GoodName=Pilotwings 64 (J) [!] CRC=09CC4801 E42EE491 Players=1 SaveType=Eeprom 4KB -CountPerOp=3 [2740F1B89CE7D78A5D31CF60C97A0C11] GoodName=Pilotwings 64 (J) [b1] @@ -11940,7 +11807,6 @@ GoodName=Pilotwings 64 (U) [!] CRC=C851961C 78FCAAFA Players=1 SaveType=Eeprom 4KB -CountPerOp=3 [E28F8F19E56CC6C7A0F3A3286AEB60C1] GoodName=Pilotwings 64 (U) [h1C] @@ -12049,7 +11915,6 @@ GoodName=Pocket Monsters Snap (J) [!] CRC=EC0F690D 32A7438C Players=1 SaveType=Flash RAM -CountPerOp=1 [33FDAB9712D9FEA793A3AE44293999C3] GoodName=Pocket Monsters Snap (J) (VC) [!] @@ -12195,7 +12060,6 @@ GoodName=Pokemon Snap (A) [!] CRC=7BB18D40 83138559 Players=1 SaveType=Flash RAM -CountPerOp=1 [A88FCF3FF00F21D3CEC44D2E0FAAAAD8] GoodName=Pokemon Snap (A) [f1] (GameShark) @@ -12207,14 +12071,12 @@ GoodName=Pokemon Snap (E) [!] CRC=4FF5976F ACF559D8 Players=1 SaveType=Flash RAM -CountPerOp=1 [E9028F9CCC307806695DD81742D05D5D] GoodName=Pokemon Snap (F) [!] CRC=BA6C293A 9FAFA338 Players=1 SaveType=Flash RAM -CountPerOp=1 [5FA70A63E352EA804607999674381749] GoodName=Pokemon Snap (F) [b1] @@ -12226,28 +12088,24 @@ GoodName=Pokemon Snap (G) [!] CRC=5753720D 2A8A884D Players=1 SaveType=Flash RAM -CountPerOp=1 [D0453459095F69BE36D675D8F743069B] GoodName=Pokemon Snap (I) [!] CRC=C0C85046 61051B05 Players=1 SaveType=Flash RAM -CountPerOp=1 [A45D7115BE5A06FD1567F9F913C3BDF8] GoodName=Pokemon Snap (S) [!] CRC=817D286A EF417416 Players=1 SaveType=Flash RAM -CountPerOp=1 [FC3C9329B7CDD67CF7650ABF63B9A580] GoodName=Pokemon Snap (U) [!] CRC=CA12B547 71FA4EE4 Players=1 SaveType=Flash RAM -CountPerOp=1 [CCA6F7593302D46ADA66C991C976DA2D] GoodName=Pokemon Snap (U) [T+Spa] @@ -12279,7 +12137,6 @@ GoodName=Pokemon Snap Station (U) [!] CRC=39119872 07722E9F Players=1 SaveType=Flash RAM -CountPerOp=1 [B88F0EC125C54685FA516D233B564842] GoodName=Pokemon Snap Station (U) [f1] @@ -12553,7 +12410,6 @@ GoodName=Pro Mahjong Kiwame 64 (J) (V1.0) [!] CRC=9BA10C4E 0408ABD3 Players=1 Mempak=Yes -CountPerOp=1 [D1624977A3C25192671772623FA76438] GoodName=Pro Mahjong Kiwame 64 (J) (V1.0) [b1] @@ -12570,14 +12426,12 @@ GoodName=Pro Mahjong Kiwame 64 (J) (V1.1) [!] CRC=0AE2B37C FBC174F0 Players=1 Mempak=Yes -CountPerOp=1 [F1A2E4DD22ADF4F90DA4BDDCA37D5F18] GoodName=Pro Mahjong Tsuwamono 64 - Jansou Battle ni Chousen (J) [!] CRC=1BDCB30F A132D876 Players=1 Mempak=Yes -CountPerOp=1 [4FA4DC582C23EEE81FEB39B7EEBD15D6] GoodName=Psychodelic Demo by Ste (POM '98) (PD) [b1] @@ -12703,7 +12557,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [55A789C553827114306E29D71E26E5DC] GoodName=Quake II (E) [h1C] @@ -12717,7 +12570,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [920FAACCE1F8A80022433ACFD5CD2BC3] GoodName=Quake II (U) [f1] (PAL) @@ -12981,8 +12833,6 @@ CRC=20FD0BF1 F5CF1D87 Players=4 SaveType=None Mempak=Yes -; Allows the game to boot -Cheat0=F117DAEC 8014,F117DAEE A1D0 [E0BB65C30C1185FD9997020A1994B07E] GoodName=Rat Attack (E) (M6) [f1] (NTSC) @@ -13000,8 +12850,6 @@ CRC=0304C48E AC4001B8 Players=4 SaveType=None Mempak=Yes -; Allows the game to boot -Cheat0=F117E34C 8014,F117E34E A8F0 [5DBBFD5ACE8222FA8FE51BE113453C13] GoodName=Rayman 2 - The Great Escape (E) (M5) [!] @@ -13039,7 +12887,6 @@ Players=2 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [FAA64ABB0D222FCC0C6E2515D3805D9F] GoodName=Re-Volt (E) (M4) [!] @@ -13110,7 +12957,6 @@ Players=2 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [CB97350D5CAB48EAB8B954D91C0E5DAC] GoodName=Ready 2 Rumble Boxing - Round 2 (U) [t1] @@ -13123,7 +12969,6 @@ CRC=9B500E8E E90550B3 Players=1 SaveType=SRAM Rumble=Yes -CountPerOp=1 [DD21150CBC21C05420304599EC57411C] GoodName=Resident Evil 2 (U) (V1.0) [!] @@ -13131,7 +12976,6 @@ CRC=2F493DD0 2E64DFD9 Players=1 SaveType=SRAM Rumble=Yes -CountPerOp=1 [1ADD2C0217662B307CDFD876B35FBF7A] GoodName=Resident Evil 2 (U) (V1.1) [!] @@ -13139,7 +12983,6 @@ CRC=AA18B1A5 07DB6AEB Players=1 SaveType=SRAM Rumble=Yes -CountPerOp=1 [AD922DAE446A301E1AAFE1DFBAD75A2E] GoodName=Road Rash 64 (E) [!] @@ -13148,7 +12991,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=3 [5EB2B1892B68767EB1D310FF7507D34E] GoodName=Road Rash 64 (E) [h1C] @@ -13162,7 +13004,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=3 [7966F17F36C43D3807C0949AAD45168A] GoodName=Road Rash 64 (U) [f1] (PAL) @@ -13189,7 +13030,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [AE705F25C57ACABBD0E8BAE5EC6E237F] GoodName=Roadsters Trophy (U) (M3) [f1] (PAL) @@ -13382,7 +13222,6 @@ Players=2 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [8A59477C29B4353FEAB85303C58B98F0] GoodName=Rush 2 - Extreme Racing USA (E) (M6) [h1I] @@ -13401,7 +13240,6 @@ Players=2 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [7ED3F10BC32CF76F172D8C31D15A2799] GoodName=S.C.A.R.S. (E) (M3) [!] @@ -13634,7 +13472,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [AF5BE0ADFF51A8E9C6D771282C295810] GoodName=San Francisco Rush 2049 (U) [!] @@ -13643,7 +13480,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [1977D63B511A900628DB2A3A104160AC] GoodName=San Francisco Rush 2049 (U) [t1] @@ -13678,7 +13514,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [A485A6E9E30B7D55D23D8DD043770C64] GoodName=Shadow Man (E) (M3) [!] @@ -13687,7 +13522,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [235511BBDB21AF5A767BDB7502A80F06] GoodName=Shadow Man (F) [!] @@ -13696,7 +13530,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [AF40EF12CE923FF1C26E76CC9D9B9ED9] GoodName=Shadow Man (G) [!] @@ -13705,7 +13538,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [CFBDC1C5E419FF162DF02A0065D9BC1D] GoodName=Shadow Man (G) [b1] @@ -13729,7 +13561,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [474647AEDFA95AEF73229A2784897EDD] GoodName=Shadow Man (U) [b1] @@ -13820,7 +13651,6 @@ GoodName=Itoi Shigesato no Bass Tsuri No. 1 Kettei Ban! (J) [!] CRC=D137A2CA 62B65053 Players=1 Rumble=Yes -CountPerOp=1 [16EC788C8A4E7EEE268FDF9072A4F0D4] GoodName=Itoi Shigesato no Bass Tsuri No. 1 Kettei Ban! (J) [b1] @@ -13914,7 +13744,6 @@ Status=3 SaveType=SRAM Players=4 Rumble=Yes -CountPerOp=1 [983F8A1D9A8D6AA1A6500AF413CE31FF] GoodName=SmashRemix0.9.5b @@ -14246,7 +14075,6 @@ CRC=A3A044B5 6DB1BF5E Players=4 Status=3 SaveType=None -CountPerOp=1 [3A6A249843DDEAFFFD334AB3C5931F8D] GoodName=Spacer by Memir (POM '99) (PD) [t1] @@ -14676,7 +14504,6 @@ CRC=EAE6ACE2 020B4384 Players=1 SaveType=Eeprom 4KB Rumble=Yes -CountPerOp=1 [3CB88B934572E7520F35E5458798775B] GoodName=Star Wars Episode I - Battle for Naboo (U) [!] @@ -14684,7 +14511,6 @@ CRC=3D02989B D4A381E2 Players=1 SaveType=Eeprom 4KB Rumble=Yes -CountPerOp=1 [B4724120C269A1DC86991D34B1561F3D] GoodName=Star Wars Episode I - Battle for Naboo (U) [b1] @@ -15128,7 +14954,6 @@ Status=3 SaveType=SRAM Players=4 Rumble=Yes -CountPerOp=1 [7F18A06BB16A507E23F9DD636B7046A6] GoodName=Super Smash Bros. (A) [f1] @@ -15149,7 +14974,6 @@ Status=3 SaveType=SRAM Players=4 Rumble=Yes -CountPerOp=1 [4D37726FDFEC039CB36E2AAE65B9727D] GoodName=Super Smash Bros. (E) (M3) [b1] @@ -15168,7 +14992,6 @@ Status=3 SaveType=SRAM Players=4 Rumble=Yes -CountPerOp=1 [508BE860974B75470851A2D25C0FCB36] GoodName=Super Smash Bros. (U) [b1] @@ -15546,14 +15369,12 @@ GoodName=Tigger's Honey Hunt (E) (M7) [!] CRC=E0C4F72F 769E1506 Players=1 SaveType=Flash RAM -CountPerOp=1 [F8636514B5B0EDEBF376C3111D24417A] GoodName=Tigger's Honey Hunt (U) [!] CRC=4EBFDD33 664C9D84 Players=1 SaveType=Flash RAM -CountPerOp=1 [7B41F28A920112F17401D633B368BA0C] GoodName=Tigger's Honey Hunt (U) [t1] @@ -15744,7 +15565,6 @@ Players=2 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [0072538EF925645DB310F8E23A480B89] GoodName=Top Gear Hyper Bike (E) [!] @@ -15753,7 +15573,6 @@ Players=2 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [561B438F6E8240BEF1DAEB36AAE72675] GoodName=Top Gear Hyper Bike (E) [b1] @@ -15767,7 +15586,6 @@ Players=2 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [7258F4AB367B025C95A4F476C461E717] GoodName=Top Gear Hyper Bike (U) [!] @@ -15776,7 +15594,6 @@ Players=2 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [6C65A252F227AEF18DF2DD3CE04CC821] GoodName=Top Gear Overdrive (E) [!] @@ -15784,7 +15601,6 @@ CRC=D09BA538 1C1A5489 Players=4 SaveType=Eeprom 4KB Rumble=Yes -CountPerOp=1 [11D6FFF288DE1BD61CCBD7CCA0C4A97B] GoodName=Top Gear Overdrive (E) [h1C] @@ -15797,7 +15613,6 @@ CRC=0578F24F 9175BF17 Players=4 SaveType=Eeprom 4KB Rumble=Yes -CountPerOp=1 [8C0F46FEF9A6034FCF0B7D6952FFEC53] GoodName=Top Gear Overdrive (J) [b1] @@ -15810,7 +15625,6 @@ CRC=D741CD80 ACA9B912 Players=4 SaveType=Eeprom 4KB Rumble=Yes -CountPerOp=1 [773FD446DA7F4E392907505053BF2A42] GoodName=Top Gear Overdrive (U) [o1] @@ -15937,7 +15751,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [FA0F12C15B3655F9F56888C3249B1CED] GoodName=Toy Story 2 - Buzz L'eclair A La Rescousse! (F) [!] @@ -15946,7 +15759,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [3F40F37B0464DD065067523FB21016DD] GoodName=Toy Story 2 - Captain Buzz Lightyear auf Rettungsmission! (G) (V1.0) [!] @@ -15955,7 +15767,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [A4A2B825797E2059B5DF60D733461F34] GoodName=Toy Story 2 - Captain Buzz Lightyear auf Rettungsmission! (G) (V1.1) [!] @@ -15964,7 +15775,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [B44E9C2D9D2F2DE3AF4793B824CCF936] GoodName=Toy Story 2 - Buzz Lightyear to the Rescue! (U) [!] @@ -15973,7 +15783,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [9E4F62BD672E3601F1BBF9CDAB791F9F] GoodName=Toy Story 2 - Buzz Lightyear to the Rescue! (U) (V1.0) [f1] (PAL) @@ -15992,7 +15801,6 @@ Players=1 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [3D22D5BD7997293612ECDD3046BEBA13] GoodName=Transformers - Beast Wars Metals 64 (J) [!] @@ -16016,7 +15824,6 @@ Players=2 SaveType=None Rumble=Yes Mempak=Yes -CountPerOp=1 [25E03763FC8A388A33871C58DFEB7C0E] GoodName=Tristar and Lightforce Quake Intro by Ayatollah & Mike (PD) @@ -16374,7 +16181,6 @@ GoodName=Uchhannanchan no Hono no Challenger - Denryu IraIra Bou (J) [!] CRC=28D5562D E4D5AE50 Players=2 Rumble=Yes -CountPerOp=1 [07B7A5CFDE9BC43F02A622387C5B5C58] GoodName=Uchhannanchan no Hono no Challenger - Denryu IraIra Bou (J) [h1C] @@ -16700,7 +16506,6 @@ CRC=98F9F2D0 03D9F09C Players=2 SaveType=None Mempak=Yes -CountPerOp=1 [C4FD61C707977F1BF48DC15E31BD2FB1] GoodName=Virtual Pool 64 (E) [o1] @@ -16713,7 +16518,6 @@ CRC=4E4A7643 A37439D7 Players=2 SaveType=None Mempak=Yes -CountPerOp=1 [C6855DF00BD5BE8A41DCE809093EE40B] GoodName=Virtual Pool 64 (U) [o1] @@ -16806,7 +16610,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=3 [EC097EB33BAD93A8AC6E15F7839762AB] GoodName=WCW Nitro (U) [b3] @@ -16868,7 +16671,6 @@ CRC=68E8A875 0CE7A486 Players=4 SaveType=SRAM Rumble=Yes -CountPerOp=1 [07F0AD841350BD7CA1E6A99FB7E887E6] GoodName=WCW-nWo Revenge (E) [h1C] @@ -16881,7 +16683,6 @@ CRC=DEE596AB AF3B7AE7 Players=4 SaveType=SRAM Rumble=Yes -CountPerOp=1 [B230D307428F4B69B3A80109AC905A44] GoodName=WCW-nWo Revenge (U) [b1] @@ -17085,14 +16886,12 @@ GoodName=War Gods (E) [!] CRC=D715CC70 271CF5D6 Players=2 SaveType=None -CountPerOp=1 [9FF2BA3C8408DE9F0EDB6D764A97C197] GoodName=War Gods (U) [!] CRC=F7FE28F6 C3F2ACC3 Players=2 SaveType=None -CountPerOp=1 [D08D61E3C244A081C166C6A8D539A181] GoodName=War Gods (U) [o1] @@ -17185,7 +16984,6 @@ Mempak=Yes GoodName=Wave Race 64 - Shindou Edition (J) (V1.2) [!] CRC=535DF3E2 609789F1 Players=2 -CountPerOp=3 SaveType=Eeprom 4KB Mempak=Yes Rumble=Yes @@ -17326,7 +17124,6 @@ CRC=CEA8B54F 7F21D503 Players=4 SaveType=None Mempak=Yes -CountPerOp=3 [15F425829D54DD290451D2F3EBAF953F] GoodName=Wetrix (E) (M6) [f1] (NTSC) @@ -17343,7 +17140,6 @@ GoodName=Wetrix (J) [!] CRC=DCB6EAFA C6BBCFA3 Players=4 SaveType=Eeprom 4KB -CountPerOp=3 [08826E96F3FB022A1C6351774198BA9D] GoodName=Wetrix (J) [o1] @@ -17356,7 +17152,6 @@ CRC=CEA8B54F 7F21D503 Players=4 SaveType=None Mempak=Yes -CountPerOp=3 [2ABE36754E866B9B6C4BDCFFC1D11ABF] GoodName=Wheel of Fortune (U) [!] @@ -17475,7 +17270,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [7260DA1CECD0D8844C5E29AA63476DEF] GoodName=Wipeout 64 (E) (Beta) [!] @@ -17484,7 +17278,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [73C6D87DBE50F73F3B44E0F237A546D7] GoodName=Wipeout 64 (U) [!] @@ -17493,7 +17286,6 @@ SaveType=None Mempak=Yes Rumble=Yes Players=4 -CountPerOp=1 [361F65D37F41536CDE98F83CAD456217] GoodName=Wipeout 64 (U) [o1] @@ -17516,7 +17308,6 @@ CRC=E43C9765 05B1C1BE Players=1 SaveType=None Mempak=Yes -CountPerOp=1 [D6E56B92EC7DBFB8B14DD5D8CFF6492E] GoodName=Wonder Project J2 - Koruro no Mori no Jozet (J) [b1] @@ -17559,7 +17350,6 @@ Players=2 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [9A2B0F3226FB8D129BEB7509C169476A] GoodName=World Driver Championship (E) (M5) [h1C] @@ -17573,7 +17363,6 @@ Players=2 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [4B86C373533D015860467C5DC1F1C662] GoodName=World Driver Championship (U) [b1] @@ -17615,7 +17404,6 @@ SaveType=Eeprom 4KB [EC2BCB1B7FC7D068BE1F39E79E49A842] GoodName=Xena Warrior Princess - The Talisman of Fate (E) [!] CRC=0A1667C7 293346A6 -CountPerOp=4 Players=4 SaveType=None Mempak=Yes @@ -17624,7 +17412,6 @@ Rumble=Yes [1AC234649D28F09E82C0D11ABB17F03B] GoodName=Xena Warrior Princess - The Talisman of Fate (U) [!] CRC=0553AE9D EAD8E0C1 -CountPerOp=3 Players=4 SaveType=None Mempak=Yes @@ -17665,7 +17452,6 @@ GoodName=Yakouchuu II - Satsujin Kouru (J) [!] CRC=9F8B96C3 A01194DC Players=1 Rumble=Yes -CountPerOp=1 [F7AA4F819F41CB4236792A8145684627] GoodName=Yoshi's Story (Ch) (iQue) [!] @@ -17809,7 +17595,6 @@ GoodName=Yuke Yuke!! Trouble Makers (J) [!] CRC=9FE6162D E97E4037 Players=1 SaveType=Eeprom 4KB -CountPerOp=1 [6F9E56C8A2B6BA5F6DBE5214E352590D] GoodName=Yuke Yuke!! Trouble Makers (J) [a1] diff --git a/mupen64plus-core/projects/msvc/mupen64plus-core.vcxproj b/mupen64plus-core/projects/msvc/mupen64plus-core.vcxproj index ef1d1dd..5561c86 100644 --- a/mupen64plus-core/projects/msvc/mupen64plus-core.vcxproj +++ b/mupen64plus-core/projects/msvc/mupen64plus-core.vcxproj @@ -160,6 +160,8 @@ + + true true diff --git a/mupen64plus-core/projects/msvc/mupen64plus-core.vcxproj.filters b/mupen64plus-core/projects/msvc/mupen64plus-core.vcxproj.filters index caf7af7..7e37505 100644 --- a/mupen64plus-core/projects/msvc/mupen64plus-core.vcxproj.filters +++ b/mupen64plus-core/projects/msvc/mupen64plus-core.vcxproj.filters @@ -177,6 +177,12 @@ device\memory + + device\memory + + + device\memory + osal diff --git a/mupen64plus-core/projects/unix/Makefile b/mupen64plus-core/projects/unix/Makefile index bd0c572..fd998a5 100755 --- a/mupen64plus-core/projects/unix/Makefile +++ b/mupen64plus-core/projects/unix/Makefile @@ -182,7 +182,6 @@ ifeq ($(ARCH_DETECTED), 64BITS_32) endif ifneq ($(OS), OSX) ifeq ($(OS), MINGW) - CFLAGS += -march=i686 LDFLAGS += -Wl,-m,i386pe else CFLAGS += -m32 @@ -551,6 +550,8 @@ SOURCE = \ $(SRCDIR)/device/gb/mbc3_rtc.c \ $(SRCDIR)/device/gb/m64282fp.c \ $(SRCDIR)/device/memory/memory.c \ + $(SRCDIR)/device/memory/dcache.c \ + $(SRCDIR)/device/memory/icache.c \ $(SRCDIR)/device/pif/bootrom_hle.c \ $(SRCDIR)/device/pif/cic.c \ $(SRCDIR)/device/pif/n64_cic_nus_6105.c \ @@ -805,7 +806,7 @@ uninstall: $(RM) "$(DESTDIR)$(SHAREDIR)/mupencheat.txt" clean: - $(RM) -r $(TARGET) $(SONAME) $(OBJDIR) $(SRCDIR)/asm_defines/asm_defines_* + $(RM) -r $(TARGET) $(SONAME) _obj $(OBJDIR) $(SRCDIR)/asm_defines/asm_defines_* # build dependency files CFLAGS += -MD -MP diff --git a/mupen64plus-core/src/api/debugger.c b/mupen64plus-core/src/api/debugger.c index 2973194..26be135 100644 --- a/mupen64plus-core/src/api/debugger.c +++ b/mupen64plus-core/src/api/debugger.c @@ -447,7 +447,7 @@ EXPORT uint32_t CALL DebugVirtualToPhysical(uint32_t address) struct r4300_core* r4300 = &dev->r4300; if ((address & UINT32_C(0xc0000000)) != UINT32_C(0x80000000)) { - address = virtual_to_physical_address(r4300, address, 0); + address = virtual_to_physical_address(r4300, address, 0, &(uint8_t){0}); if (address == 0) { return 0; } diff --git a/mupen64plus-core/src/api/frontend.c b/mupen64plus-core/src/api/frontend.c index f11b8b7..9363bad 100644 --- a/mupen64plus-core/src/api/frontend.c +++ b/mupen64plus-core/src/api/frontend.c @@ -425,7 +425,6 @@ EXPORT m64p_error CALL CoreGetRomSettings(m64p_rom_settings *RomSettings, int Ro RomSettings->transferpak = entry->transferpak; RomSettings->mempak = entry->mempak; RomSettings->disableextramem = entry->disableextramem; - RomSettings->countperop = entry->countperop; RomSettings->savetype = entry->savetype; RomSettings->sidmaduration = entry->sidmaduration; RomSettings->aidmamodifier = entry->aidmamodifier; diff --git a/mupen64plus-core/src/api/m64p_types.h b/mupen64plus-core/src/api/m64p_types.h index 14c20bc..c9dd1ce 100644 --- a/mupen64plus-core/src/api/m64p_types.h +++ b/mupen64plus-core/src/api/m64p_types.h @@ -280,7 +280,6 @@ typedef struct unsigned char mempak; /* 0 - No, 1 - Yes boolean for memory pak support. */ unsigned char biopak; /* 0 - No, 1 - Yes boolean for bio pak support. */ unsigned char disableextramem; /* 0 - No, 1 - Yes boolean for disabling 4MB expansion RAM pack */ - unsigned int countperop; /* Number of CPU cycles per instruction. */ unsigned int sidmaduration; /* Default SI DMA duration */ unsigned int aidmamodifier; /* Percentage modifier for AI DMA duration */ unsigned int rspdelaytime; /* Cycles to delay RSP when needed */ diff --git a/mupen64plus-core/src/asm_defines/asm_defines.c b/mupen64plus-core/src/asm_defines/asm_defines.c index 6ac2280..0fb0b5f 100644 --- a/mupen64plus-core/src/asm_defines/asm_defines.c +++ b/mupen64plus-core/src/asm_defines/asm_defines.c @@ -113,7 +113,6 @@ DEFINE(cp0, regs); DEFINE(cp0, next_interrupt); #endif DEFINE(cp0, last_addr); -DEFINE(cp0, count_per_op); DEFINE(cp0, tlb); DEFINE(tlb, entries); diff --git a/mupen64plus-core/src/device/cart/cart.c b/mupen64plus-core/src/device/cart/cart.c index b28e6c4..74aea92 100644 --- a/mupen64plus-core/src/device/cart/cart.c +++ b/mupen64plus-core/src/device/cart/cart.c @@ -188,51 +188,45 @@ void write_cart_dom2(void* opaque, uint32_t address, uint32_t value, uint32_t ma } } -unsigned int cart_dom2_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) +void cart_dom2_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) { struct cart* cart = (struct cart*)opaque; - unsigned int cycles; if (cart->use_flashram != 1) { - cycles = sram_dma_read(&cart->sram, dram, dram_addr, cart_addr, length); + sram_dma_read(&cart->sram, dram, dram_addr, cart_addr, length); cart->use_flashram = -1; } else { - cycles = flashram_dma_read(&cart->flashram, dram, dram_addr, cart_addr, length); + flashram_dma_read(&cart->flashram, dram, dram_addr, cart_addr, length); } - - return cycles; } -unsigned int cart_dom2_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) +void cart_dom2_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) { struct cart* cart = (struct cart*)opaque; - unsigned int cycles; if (cart->use_flashram != 1) { - cycles = sram_dma_write(&cart->sram, dram, dram_addr, cart_addr, length); + sram_dma_write(&cart->sram, dram, dram_addr, cart_addr, length); cart->use_flashram = -1; } else { - cycles = flashram_dma_write(&cart->flashram, dram, dram_addr, cart_addr, length); + flashram_dma_write(&cart->flashram, dram, dram_addr, cart_addr, length); } - - return cycles; } -unsigned int cart_dom3_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) +void cart_dom3_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) { struct cart* cart = (struct cart*)opaque; - return cart_rom_dma_read(&cart->cart_rom, dram, dram_addr, cart_addr, length); + cart_rom_dma_read(&cart->cart_rom, dram, dram_addr, cart_addr, length); } -unsigned int cart_dom3_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) +void cart_dom3_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) { struct cart* cart = (struct cart*)opaque; - return cart_rom_dma_write(&cart->cart_rom, dram, dram_addr, cart_addr, length); + cart_rom_dma_write(&cart->cart_rom, dram, dram_addr, cart_addr, length); } diff --git a/mupen64plus-core/src/device/cart/cart.h b/mupen64plus-core/src/device/cart/cart.h index 3ccf3ce..3a83d5a 100644 --- a/mupen64plus-core/src/device/cart/cart.h +++ b/mupen64plus-core/src/device/cart/cart.h @@ -72,10 +72,10 @@ void poweron_cart(struct cart* cart); void read_cart_dom2(void* opaque, uint32_t address, uint32_t* value); void write_cart_dom2(void* opaque, uint32_t address, uint32_t value, uint32_t mask); -unsigned int cart_dom2_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); -unsigned int cart_dom2_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); -unsigned int cart_dom3_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); -unsigned int cart_dom3_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); +void cart_dom2_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); +void cart_dom2_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); +void cart_dom3_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); +void cart_dom3_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); extern const struct joybus_device_interface g_ijoybus_device_cart; diff --git a/mupen64plus-core/src/device/cart/cart_rom.c b/mupen64plus-core/src/device/cart/cart_rom.c index 86657df..0a993d1 100644 --- a/mupen64plus-core/src/device/cart/cart_rom.c +++ b/mupen64plus-core/src/device/cart/cart_rom.c @@ -78,20 +78,17 @@ void write_cart_rom(void* opaque, uint32_t address, uint32_t value, uint32_t mas /* Mark IO as busy */ cart_rom->pi->regs[PI_STATUS_REG] |= PI_STATUS_IO_BUSY; - cp0_update_count(cart_rom->r4300); add_interrupt_event(&cart_rom->r4300->cp0, PI_INT, 0x1000); } -unsigned int cart_rom_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) +void cart_rom_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) { cart_addr &= CART_ROM_ADDR_MASK; DebugMessage(M64MSG_WARNING, "DMA Writing to CART_ROM: 0x%" PRIX32 " -> 0x%" PRIX32 " (0x%" PRIX32 ")", dram_addr, cart_addr, length); - - return /* length / 8 */0x1000; } -unsigned int cart_rom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) +void cart_rom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) { size_t i; struct cart_rom* cart_rom = (struct cart_rom*)opaque; @@ -122,7 +119,5 @@ unsigned int cart_rom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, /* invalidate cached code */ invalidate_r4300_cached_code(cart_rom->r4300, 0x80000000 + dram_addr, length); invalidate_r4300_cached_code(cart_rom->r4300, 0xa0000000 + dram_addr, length); - - return (length / 8) + add_random_interrupt_time(cart_rom->r4300); } diff --git a/mupen64plus-core/src/device/cart/cart_rom.h b/mupen64plus-core/src/device/cart/cart_rom.h index 2bba5a3..e7a6b31 100644 --- a/mupen64plus-core/src/device/cart/cart_rom.h +++ b/mupen64plus-core/src/device/cart/cart_rom.h @@ -56,7 +56,7 @@ void poweron_cart_rom(struct cart_rom* cart_rom); void read_cart_rom(void* opaque, uint32_t address, uint32_t* value); void write_cart_rom(void* opaque, uint32_t address, uint32_t value, uint32_t mask); -unsigned int cart_rom_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); -unsigned int cart_rom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); +void cart_rom_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); +void cart_rom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); #endif diff --git a/mupen64plus-core/src/device/cart/flashram.c b/mupen64plus-core/src/device/cart/flashram.c index 64dc112..eb2d93e 100644 --- a/mupen64plus-core/src/device/cart/flashram.c +++ b/mupen64plus-core/src/device/cart/flashram.c @@ -181,7 +181,7 @@ void write_flashram(void* opaque, uint32_t address, uint32_t value, uint32_t mas } -unsigned int flashram_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) +void flashram_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) { size_t i; struct flashram* flashram = (struct flashram*)opaque; @@ -216,11 +216,9 @@ unsigned int flashram_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, DebugMessage(M64MSG_WARNING, "unknown Flashram DMA Write (mode=%x) @%08x <- %08x length=%08x", flashram->mode, dram_addr, cart_addr, length); } - - return /* length / 8 */0x1000; } -unsigned int flashram_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) +void flashram_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) { struct flashram* flashram = (struct flashram*)opaque; unsigned int i; @@ -236,7 +234,5 @@ unsigned int flashram_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_ DebugMessage(M64MSG_WARNING, "unknown Flashram DMA Read (mode=%x) @%08x <- %08x length=%08x", flashram->mode, cart_addr, dram_addr, length); } - - return /* length / 8 */0x1000; } diff --git a/mupen64plus-core/src/device/cart/flashram.h b/mupen64plus-core/src/device/cart/flashram.h index 76d7c65..c60e271 100644 --- a/mupen64plus-core/src/device/cart/flashram.h +++ b/mupen64plus-core/src/device/cart/flashram.h @@ -75,7 +75,7 @@ void format_flashram(uint8_t* flash); void read_flashram(void* opaque, uint32_t address, uint32_t* value); void write_flashram(void* opaque, uint32_t address, uint32_t value, uint32_t mask); -unsigned int flashram_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); -unsigned int flashram_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); +void flashram_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); +void flashram_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); #endif diff --git a/mupen64plus-core/src/device/cart/sram.c b/mupen64plus-core/src/device/cart/sram.c index 508447f..b9648cf 100644 --- a/mupen64plus-core/src/device/cart/sram.c +++ b/mupen64plus-core/src/device/cart/sram.c @@ -42,7 +42,7 @@ void init_sram(struct sram* sram, sram->istorage = istorage; } -unsigned int sram_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) +void sram_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) { size_t i; struct sram* sram = (struct sram*)opaque; @@ -55,11 +55,9 @@ unsigned int sram_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr } sram->istorage->save(sram->storage, cart_addr, length); - - return /* length / 8 */0x1000; } -unsigned int sram_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) +void sram_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) { size_t i; struct sram* sram = (struct sram*)opaque; @@ -70,8 +68,6 @@ unsigned int sram_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uin for (i = 0; i < length; ++i) { dram[(dram_addr+i)^S8] = mem[(cart_addr+i)^S8]; } - - return /* length / 8 */0x1000; } void read_sram(void* opaque, uint32_t address, uint32_t* value) diff --git a/mupen64plus-core/src/device/cart/sram.h b/mupen64plus-core/src/device/cart/sram.h index 872e2a3..e98759b 100644 --- a/mupen64plus-core/src/device/cart/sram.h +++ b/mupen64plus-core/src/device/cart/sram.h @@ -39,8 +39,8 @@ void format_sram(uint8_t* sram); void init_sram(struct sram* sram, void* storage, const struct storage_backend_interface* istorage); -unsigned int sram_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); -unsigned int sram_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); +void sram_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); +void sram_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); void read_sram(void* opaque, uint32_t address, uint32_t* value); void write_sram(void* opaque, uint32_t address, uint32_t value, uint32_t mask); diff --git a/mupen64plus-core/src/device/dd/dd_controller.c b/mupen64plus-core/src/device/dd/dd_controller.c index 77b258c..1db2574 100644 --- a/mupen64plus-core/src/device/dd/dd_controller.c +++ b/mupen64plus-core/src/device/dd/dd_controller.c @@ -547,7 +547,7 @@ void write_dd_rom(void* opaque, uint32_t address, uint32_t value, uint32_t mask) DebugMessage(M64MSG_VERBOSE, "DD ROM: %08X <- %08x & %08x", address, value, mask); } -unsigned int dd_dom_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) +void dd_dom_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) { struct dd_controller* dd = (struct dd_controller*)opaque; uint8_t* mem; @@ -562,29 +562,22 @@ unsigned int dd_dom_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_ad } else if (cart_addr == MM_DD_MS_RAM) { /* MS is not emulated, we silence warnings for now */ - /* Recommended Count Per Op = 1, this seems to break very easily */ - return (length * 63) / 25; + return; } else { DebugMessage(M64MSG_ERROR, "Unknown DD dma read dram=%08x cart=%08x length=%08x", dram_addr, cart_addr, length); - - /* Recommended Count Per Op = 1, this seems to break very easily */ - return (length * 63) / 25; + return; } for (i = 0; i < length; ++i) { mem[(cart_addr + i) ^ S8] = dram[(dram_addr + i) ^ S8]; } - - /* Recommended Count Per Op = 1, this seems to break very easily */ - return (length * 63) / 25; } -unsigned int dd_dom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) +void dd_dom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) { struct dd_controller* dd = (struct dd_controller*)opaque; - unsigned int cycles; const uint8_t* mem; size_t i; @@ -606,20 +599,13 @@ unsigned int dd_dom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, u DebugMessage(M64MSG_ERROR, "Unknown DD dma write dram=%08x cart=%08x length=%08x", dram_addr, cart_addr, length); - /* Recommended Count Per Op = 1, this seems to break very easily */ - return (length * 63) / 25; + return; } - - /* Recommended Count Per Op = 1, this seems to break very easily */ - cycles = (length * 63) / 25; } else { /* DD ROM */ cart_addr = (cart_addr - MM_DD_ROM); mem = (const uint8_t*)dd->rom; - - /* Recommended Count Per Op = 1, this seems to break very easily */ - cycles = (length * 63) / 25; } for (i = 0; i < length; ++i) { @@ -628,8 +614,6 @@ unsigned int dd_dom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, u invalidate_r4300_cached_code(dd->r4300, R4300_KSEG0 + dram_addr, length); invalidate_r4300_cached_code(dd->r4300, R4300_KSEG1 + dram_addr, length); - - return cycles; } void dd_on_pi_cart_addr_write(struct dd_controller* dd, uint32_t address) diff --git a/mupen64plus-core/src/device/dd/dd_controller.h b/mupen64plus-core/src/device/dd/dd_controller.h index 4f87d4f..da8e2a6 100644 --- a/mupen64plus-core/src/device/dd/dd_controller.h +++ b/mupen64plus-core/src/device/dd/dd_controller.h @@ -117,8 +117,8 @@ void write_dd_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask void read_dd_rom(void* opaque, uint32_t address, uint32_t* value); void write_dd_rom(void* opaque, uint32_t address, uint32_t value, uint32_t mask); -unsigned int dd_dom_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); -unsigned int dd_dom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); +void dd_dom_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); +void dd_dom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); void dd_on_pi_cart_addr_write(struct dd_controller* dd, uint32_t address); void dd_update_bm(void* opaque); diff --git a/mupen64plus-core/src/device/device.c b/mupen64plus-core/src/device/device.c index ea5824d..a3782e2 100644 --- a/mupen64plus-core/src/device/device.c +++ b/mupen64plus-core/src/device/device.c @@ -82,8 +82,6 @@ void init_device(struct device* dev, void* base, /* r4300 */ unsigned int emumode, - unsigned int count_per_op, - unsigned int count_per_op_denom_pot, int no_compiled_jump, int randomize_interrupt, uint32_t start_address, @@ -182,7 +180,7 @@ void init_device(struct device* dev, init_rdram(&dev->rdram, mem_base_u32(base, MM_RDRAM_DRAM), dram_size, &dev->r4300); init_r4300(&dev->r4300, &dev->mem, &dev->mi, &dev->rdram, interrupt_handlers, - emumode, count_per_op, count_per_op_denom_pot, no_compiled_jump, randomize_interrupt, start_address); + emumode, no_compiled_jump, randomize_interrupt, start_address); init_rdp(&dev->dp, &dev->sp, &dev->mi, &dev->mem, &dev->rdram, &dev->r4300); init_rsp(&dev->sp, mem_base_u32(base, MM_RSP_MEM), &dev->mi, &dev->dp, &dev->ri, rsp_delay_time); init_ai(&dev->ai, &dev->mi, &dev->ri, &dev->vi, aout, iaout, dma_modifier); diff --git a/mupen64plus-core/src/device/device.h b/mupen64plus-core/src/device/device.h index a232759..558aa13 100644 --- a/mupen64plus-core/src/device/device.h +++ b/mupen64plus-core/src/device/device.h @@ -120,8 +120,6 @@ void init_device(struct device* dev, void* base, /* r4300 */ unsigned int emumode, - unsigned int count_per_op, - unsigned int count_per_op_denom_pot, int no_compiled_jump, int randomize_interrupt, uint32_t start_address, diff --git a/mupen64plus-core/src/device/memory/dcache.c b/mupen64plus-core/src/device/memory/dcache.c new file mode 100644 index 0000000..e28c49c --- /dev/null +++ b/mupen64plus-core/src/device/memory/dcache.c @@ -0,0 +1,96 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus - dcache.c * + * Mupen64Plus homepage: https://mupen64plus.org/ * + * Copyright (C) 2022 loganmc10 * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include + +#include "device/r4300/r4300_core.h" +#include "device/memory/memory.h" + +void init_dcache(struct datacache *lines) +{ + memset(lines, 0, 512 * sizeof(lines[0])); + for (uint32_t i = 0; i < 512; ++i) + lines[i].index = i << 4 & UINT32_C(0xFF0); +} + +void dcache_writeback(struct r4300_core* r4300, struct datacache *line) +{ + cp0_add_count(r4300, 22, 0); + line->dirty = 0; + uint32_t cache_address = line->tag | line->index; + invalidate_r4300_cached_code(r4300, cache_address, 16); + invalidate_r4300_cached_code(r4300, cache_address ^ UINT32_C(0x20000000), 16); + cache_address &= UINT32_C(0x1ffffffc); + const struct mem_handler* handler = mem_get_handler(r4300->mem, cache_address); + mem_write32(handler, cache_address | UINT32_C(0x0), line->words[0], ~UINT32_C(0)); + mem_write32(handler, cache_address | UINT32_C(0x4), line->words[1], ~UINT32_C(0)); + mem_write32(handler, cache_address | UINT32_C(0x8), line->words[2], ~UINT32_C(0)); + mem_write32(handler, cache_address | UINT32_C(0xC), line->words[3], ~UINT32_C(0)); +} + +uint32_t dcache_hit(struct datacache *line, uint32_t address) +{ + return line->valid && line->tag == (address & ~UINT32_C(0xFFF)); +} + +static void dcache_fill(struct datacache *line, struct r4300_core* r4300, uint32_t address) +{ + cp0_add_count(r4300, 22, 0); + line->valid = 1; + line->dirty = 0; + line->tag = address & ~UINT32_C(0xFFF); + uint32_t cache_address = line->tag | line->index; + cache_address &= UINT32_C(0x1ffffffc); + const struct mem_handler* handler = mem_get_handler(r4300->mem, cache_address); + mem_read32(handler, cache_address | UINT32_C(0x0), &line->words[0]); + mem_read32(handler, cache_address | UINT32_C(0x4), &line->words[1]); + mem_read32(handler, cache_address | UINT32_C(0x8), &line->words[2]); + mem_read32(handler, cache_address | UINT32_C(0xC), &line->words[3]); +} + +void dcache_read32(struct r4300_core* r4300, uint32_t address, uint32_t *value) +{ + struct datacache *line = &r4300->mem->dcache[(address >> 4) & UINT32_C(0x1FF)]; + if(!dcache_hit(line, address)) + { + if(line->valid && line->dirty) + dcache_writeback(r4300, line); + dcache_fill(line, r4300, address); + } + else + cp0_add_count(r4300, 0, 1); + *value = line->words[(address >> 2) & UINT32_C(3)]; +} + +void dcache_write32(struct r4300_core* r4300, uint32_t address, uint32_t value, uint32_t mask) +{ + struct datacache *line = &r4300->mem->dcache[(address >> 4) & UINT32_C(0x1FF)]; + if(!dcache_hit(line, address)) + { + if(line->valid && line->dirty) + dcache_writeback(r4300, line); + dcache_fill(line, r4300, address); + } + else + cp0_add_count(r4300, 0, 1); + masked_write(&line->words[(address >> 2) & UINT32_C(3)], value, mask); + line->dirty = 1; +} diff --git a/mupen64plus-core/src/device/memory/dcache.h b/mupen64plus-core/src/device/memory/dcache.h new file mode 100644 index 0000000..3e37d43 --- /dev/null +++ b/mupen64plus-core/src/device/memory/dcache.h @@ -0,0 +1,44 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus - dcache.h * + * Mupen64Plus homepage: https://mupen64plus.org/ * + * Copyright (C) 2022 loganmc10 * + * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef M64P_DEVICE_MEMORY_DCACHE_H +#define M64P_DEVICE_MEMORY_DCACHE_H + +#include + +struct r4300_core; + +struct datacache +{ + uint8_t valid; + uint8_t dirty; + uint32_t tag; + uint16_t index; + uint32_t words[4]; +}; + +void init_dcache(struct datacache *lines); +void dcache_writeback(struct r4300_core* r4300, struct datacache *line); +uint32_t dcache_hit(struct datacache *line, uint32_t address); +void dcache_read32(struct r4300_core* r4300, uint32_t address, uint32_t *value); +void dcache_write32(struct r4300_core* r4300, uint32_t address, uint32_t value, uint32_t mask); + +#endif diff --git a/mupen64plus-core/src/device/memory/icache.c b/mupen64plus-core/src/device/memory/icache.c new file mode 100644 index 0000000..05fe312 --- /dev/null +++ b/mupen64plus-core/src/device/memory/icache.c @@ -0,0 +1,100 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus - icache.c * + * Mupen64Plus homepage: https://mupen64plus.org/ * + * Copyright (C) 2022 loganmc10 * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include + +#include "device/r4300/r4300_core.h" +#include "device/memory/memory.h" + +void init_icache(struct instcache *lines) +{ + memset(lines, 0, 512 * sizeof(lines[0])); + for (uint32_t i = 0; i < 512; ++i) + lines[i].index = i << 5 & UINT32_C(0xFE0); +} + +void icache_writeback(struct r4300_core* r4300, struct instcache *line) +{ + cp0_add_count(r4300, 24, 0); + uint32_t cache_address = line->tag | line->index; + invalidate_r4300_cached_code(r4300, cache_address, 32); + invalidate_r4300_cached_code(r4300, cache_address ^ UINT32_C(0x20000000), 32); + cache_address &= UINT32_C(0x1ffffffc); + const struct mem_handler* handler = mem_get_handler(r4300->mem, cache_address); + mem_write32(handler, cache_address | UINT32_C(0x0), line->words[0], ~UINT32_C(0)); + mem_write32(handler, cache_address | UINT32_C(0x4), line->words[1], ~UINT32_C(0)); + mem_write32(handler, cache_address | UINT32_C(0x8), line->words[2], ~UINT32_C(0)); + mem_write32(handler, cache_address | UINT32_C(0xC), line->words[3], ~UINT32_C(0)); + mem_write32(handler, cache_address | UINT32_C(0x10), line->words[4], ~UINT32_C(0)); + mem_write32(handler, cache_address | UINT32_C(0x14), line->words[5], ~UINT32_C(0)); + mem_write32(handler, cache_address | UINT32_C(0x18), line->words[6], ~UINT32_C(0)); + mem_write32(handler, cache_address | UINT32_C(0x1C), line->words[7], ~UINT32_C(0)); +} + +uint32_t icache_hit(struct instcache *line, uint32_t address) +{ + return line->valid && line->tag == (address & ~UINT32_C(0xFFF)); +} + +void icache_fill(struct instcache *line, struct r4300_core* r4300, uint32_t address) +{ + cp0_add_count(r4300, 24, 0); + line->valid = 1; + line->tag = address & ~UINT32_C(0xFFF); + uint32_t cache_address = line->tag | line->index; + cache_address &= UINT32_C(0x1ffffffc); + const struct mem_handler* handler = mem_get_handler(r4300->mem, cache_address); + mem_read32(handler, cache_address | UINT32_C(0x0), &line->words[0]); + mem_read32(handler, cache_address | UINT32_C(0x4), &line->words[1]); + mem_read32(handler, cache_address | UINT32_C(0x8), &line->words[2]); + mem_read32(handler, cache_address | UINT32_C(0xC), &line->words[3]); + mem_read32(handler, cache_address | UINT32_C(0x10), &line->words[4]); + mem_read32(handler, cache_address | UINT32_C(0x14), &line->words[5]); + mem_read32(handler, cache_address | UINT32_C(0x18), &line->words[6]); + mem_read32(handler, cache_address | UINT32_C(0x1C), &line->words[7]); +} + +uint32_t* icache_fetch(struct r4300_core* r4300, uint32_t address) +{ + struct instcache *line = &r4300->mem->icache[(address >> 5) & UINT32_C(0x1FF)]; + if(!icache_hit(line, address)) + icache_fill(line, r4300, address); + else + cp0_add_count(r4300, 1, 0); + + return &line->words[address >> 2 & 7]; +} + +void icache_step(struct r4300_core* r4300, uint32_t address) +{ + struct instcache *line = &r4300->mem->icache[(address >> 5) & UINT32_C(0x1FF)]; + uint8_t cached = 0; + r4300_translate_address(r4300, &address, &cached, 2, 0); + if (cached) + { + if(!icache_hit(line, address)) + icache_fill(line, r4300, address); + else + cp0_add_count(r4300, 1, 0); + } + else + cp0_add_count(r4300, 18, 1); +} diff --git a/mupen64plus-core/src/device/memory/icache.h b/mupen64plus-core/src/device/memory/icache.h new file mode 100644 index 0000000..fa51578 --- /dev/null +++ b/mupen64plus-core/src/device/memory/icache.h @@ -0,0 +1,44 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus - icache.h * + * Mupen64Plus homepage: https://mupen64plus.org/ * + * Copyright (C) 2022 loganmc10 * + * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef M64P_DEVICE_MEMORY_ICACHE_H +#define M64P_DEVICE_MEMORY_ICACHE_H + +#include + +struct r4300_core; + +struct instcache +{ + uint8_t valid; + uint32_t tag; + uint16_t index; + uint32_t words[8]; +}; + +void init_icache(struct instcache *lines); +void icache_writeback(struct r4300_core* r4300, struct instcache *line); +uint32_t icache_hit(struct instcache *line, uint32_t address); +void icache_fill(struct instcache *line, struct r4300_core* r4300, uint32_t address); +uint32_t* icache_fetch(struct r4300_core* r4300, uint32_t address); +void icache_step(struct r4300_core* r4300, uint32_t address); + +#endif diff --git a/mupen64plus-core/src/device/memory/memory.c b/mupen64plus-core/src/device/memory/memory.c index 38eee8e..90becba 100644 --- a/mupen64plus-core/src/device/memory/memory.c +++ b/mupen64plus-core/src/device/memory/memory.c @@ -180,6 +180,9 @@ void init_memory(struct memory* mem, for(m = 0; m < mappings_count; ++m) { apply_mem_mapping(mem, &mappings[m]); } + + init_dcache(&mem->dcache[0]); + init_icache(&mem->icache[0]); } static void map_region(struct memory* mem, diff --git a/mupen64plus-core/src/device/memory/memory.h b/mupen64plus-core/src/device/memory/memory.h index 7cb02e2..ac7f56a 100644 --- a/mupen64plus-core/src/device/memory/memory.h +++ b/mupen64plus-core/src/device/memory/memory.h @@ -25,6 +25,8 @@ #include #include +#include "dcache.h" +#include "icache.h" #include "osal/preproc.h" enum { RDRAM_MAX_SIZE = 0x800000 }; @@ -53,6 +55,8 @@ struct memory { struct mem_handler handlers[0x10000]; void* base; + struct datacache dcache[512]; + struct instcache icache[512]; #ifdef DBG int memtype[0x10000]; diff --git a/mupen64plus-core/src/device/pif/pif.c b/mupen64plus-core/src/device/pif/pif.c index 720ef07..7e43936 100644 --- a/mupen64plus-core/src/device/pif/pif.c +++ b/mupen64plus-core/src/device/pif/pif.c @@ -279,7 +279,6 @@ static void process_cic_challenge(struct pif* pif) void poweron_pif(struct pif* pif) { memset(pif->ram, 0, PIF_RAM_SIZE); - pif->update_counter = 0; reset_pif(pif, 0); /* cold reset */ } @@ -309,7 +308,6 @@ void write_pif_mem(void* opaque, uint32_t address, uint32_t value, uint32_t mask pif->si->dma_dir = SI_DMA_WRITE; - cp0_update_count(pif->r4300); pif->si->regs[SI_STATUS_REG] |= (SI_STATUS_DMA_BUSY | SI_STATUS_IO_BUSY); add_interrupt_event(&pif->r4300->cp0, SI_INT, pif->si->dma_duration); } @@ -368,13 +366,6 @@ void process_pif_ram(struct pif* pif) pif->ram[0x3f] &= ~clrmask; } -static void update_pif_counter(struct pif* pif) -{ - /* check if controller 0 was polled for input */ - if (pif->channels[0].tx && (pif->channels[0].tx_buf[0] == JCMD_CONTROLLER_READ)) - ++pif->update_counter; -} - void update_pif_ram(struct pif* pif) { size_t k; @@ -388,7 +379,6 @@ void update_pif_ram(struct pif* pif) if (input.readController) { input.readController(-1, NULL); } - update_pif_counter(pif); netplay_update_input(pif); diff --git a/mupen64plus-core/src/device/pif/pif.h b/mupen64plus-core/src/device/pif/pif.h index d2429a6..4bdb090 100644 --- a/mupen64plus-core/src/device/pif/pif.h +++ b/mupen64plus-core/src/device/pif/pif.h @@ -59,8 +59,6 @@ struct pif struct cic cic; - uint32_t update_counter; - struct r4300_core* r4300; struct si_controller* si; }; diff --git a/mupen64plus-core/src/device/r4300/cached_interp.c b/mupen64plus-core/src/device/r4300/cached_interp.c index 184dac1..185d03a 100644 --- a/mupen64plus-core/src/device/r4300/cached_interp.c +++ b/mupen64plus-core/src/device/r4300/cached_interp.c @@ -83,8 +83,8 @@ void cached_interp_##name(void) \ (*r4300_pc_struct(r4300))++; \ r4300->delay_slot=1; \ UPDATE_DEBUGGER(); \ + icache_step(r4300, (*r4300_pc_struct(r4300))->addr); \ (*r4300_pc_struct(r4300))->ops(); \ - cp0_update_count(r4300); \ r4300->delay_slot=0; \ if (take_jump && !r4300->skip_jump) \ { \ @@ -94,7 +94,6 @@ void cached_interp_##name(void) \ else \ { \ (*r4300_pc_struct(r4300)) += 2; \ - cp0_update_count(r4300); \ } \ r4300->cp0.last_addr = *r4300_pc(r4300); \ if (*r4300_cp0_cycle_count(&r4300->cp0) >= 0) gen_interrupt(r4300); \ @@ -116,8 +115,8 @@ void cached_interp_##name##_OUT(void) \ (*r4300_pc_struct(r4300))++; \ r4300->delay_slot=1; \ UPDATE_DEBUGGER(); \ + icache_step(r4300, (*r4300_pc_struct(r4300))->addr); \ (*r4300_pc_struct(r4300))->ops(); \ - cp0_update_count(r4300); \ r4300->delay_slot=0; \ if (take_jump && !r4300->skip_jump) \ { \ @@ -127,7 +126,6 @@ void cached_interp_##name##_OUT(void) \ else \ { \ (*r4300_pc_struct(r4300)) += 2; \ - cp0_update_count(r4300); \ } \ r4300->cp0.last_addr = *r4300_pc(r4300); \ if (*r4300_cp0_cycle_count(&r4300->cp0) >= 0) gen_interrupt(r4300); \ @@ -142,7 +140,6 @@ void cached_interp_##name##_IDLE(void) \ if (cop1 && check_cop1_unusable(r4300)) return; \ if (take_jump) \ { \ - cp0_update_count(r4300); \ if(*cp0_cycle_count < 0) \ { \ cp0_regs[CP0_COUNT_REG] -= *cp0_cycle_count; \ @@ -203,6 +200,7 @@ void cached_interp_FIN_BLOCK(void) #endif Used by dynarec only, check should be unnecessary */ + icache_step(r4300, (*r4300_pc_struct(r4300))->addr); (*r4300_pc_struct(r4300))->ops(); } else @@ -219,6 +217,7 @@ Used by dynarec only, check should be unnecessary */ if (!r4300->skip_jump) { + icache_step(r4300, (*r4300_pc_struct(r4300))->addr); (*r4300_pc_struct(r4300))->ops(); r4300->cached_interp.actual = blk; (*r4300_pc_struct(r4300)) = inst+1; @@ -231,7 +230,7 @@ Used by dynarec only, check should be unnecessary void cached_interp_NOTCOMPILED(void) { DECLARE_R4300 - uint32_t *mem = fast_mem_access(r4300, r4300->cached_interp.blocks[*r4300_pc(r4300)>>12]->start); + uint32_t *mem = fast_mem_access(r4300, r4300->cached_interp.blocks[*r4300_pc(r4300)>>12]->start, 0); #ifdef DBG DebugMessage(M64MSG_INFO, "NOTCOMPILED: addr = %x ops = %lx", *r4300_pc(r4300), (long) (*r4300_pc_struct(r4300))->ops); #endif @@ -250,6 +249,7 @@ void cached_interp_NOTCOMPILED(void) The preceeding update_debugger SHOULD be unnecessary since it should have been called before NOTCOMPILED would have been executed */ + icache_step(r4300, (*r4300_pc_struct(r4300))->addr); (*r4300_pc_struct(r4300))->ops(); } @@ -514,6 +514,7 @@ enum r4300_opcode r4300_decode(struct precomp_instr* inst, struct r4300_core* r4 case R4300_OP_LWC1: case R4300_OP_SDC1: case R4300_OP_SWC1: + case R4300_OP_CACHE: idec_u53(iw, idec->u53[2], &inst->f.lf.base); idec_u53(iw, idec->u53[1], &inst->f.lf.ft); inst->f.lf.offset = (uint16_t)iw; @@ -672,7 +673,6 @@ enum r4300_opcode r4300_decode(struct precomp_instr* inst, struct r4300_core* r4 break; case R4300_OP_BREAK: - case R4300_OP_CACHE: case R4300_OP_ERET: case R4300_OP_SYNC: case R4300_OP_SYSCALL: @@ -714,7 +714,7 @@ static uint32_t update_invalid_addr(struct r4300_core* r4300, uint32_t addr) } else { - uint32_t paddr = virtual_to_physical_address(r4300, addr, 2); + uint32_t paddr = virtual_to_physical_address(r4300, addr, 2, &(uint8_t){0}); if (paddr) { uint32_t beg_paddr = paddr - (addr - (addr & ~0xfff)); @@ -799,7 +799,7 @@ void cached_interp_init_block(struct r4300_core* r4300, uint32_t address) if (b->end < UINT32_C(0x80000000) || b->start >= UINT32_C(0xc0000000)) { - uint32_t paddr = virtual_to_physical_address(r4300, b->start, 2); + uint32_t paddr = virtual_to_physical_address(r4300, b->start, 2, &(uint8_t){0}); r4300->cached_interp.invalid_code[paddr>>12] = 0; cached_interp_init_block(r4300, paddr); @@ -854,7 +854,7 @@ void cached_interp_recompile_block(struct r4300_core* r4300, const uint32_t* iw, if (block_start_in_tlb) { - uint32_t address2 = virtual_to_physical_address(r4300, inst->addr, 0); + uint32_t address2 = virtual_to_physical_address(r4300, inst->addr, 0, &(uint8_t){0}); if (r4300->cached_interp.blocks[address2>>12]->block[(address2&UINT32_C(0xFFF))/4].ops == cached_interp_NOTCOMPILED) { r4300->cached_interp.blocks[address2>>12]->block[(address2&UINT32_C(0xFFF))/4].ops = cached_interp_NOTCOMPILED2; } @@ -992,12 +992,13 @@ void run_cached_interpreter(struct r4300_core* r4300) { #ifdef COMPARE_CORE if ((*r4300_pc_struct(r4300))->ops == cached_interp_FIN_BLOCK && ((*r4300_pc_struct(r4300))->addr < 0x80000000 || (*r4300_pc_struct(r4300))->addr >= 0xc0000000)) - virtual_to_physical_address(r4300, (*r4300_pc_struct(r4300))->addr, 2); + virtual_to_physical_address(r4300, (*r4300_pc_struct(r4300))->addr, 2, &(uint8_t){0}); CoreCompareCallback(); #endif #ifdef DBG if (g_DebuggerActive) update_debugger((*r4300_pc_struct(r4300))->addr); #endif + icache_step(r4300, (*r4300_pc_struct(r4300))->addr); (*r4300_pc_struct(r4300))->ops(); } } diff --git a/mupen64plus-core/src/device/r4300/cp0.c b/mupen64plus-core/src/device/r4300/cp0.c index ecf4818..86bc03d 100644 --- a/mupen64plus-core/src/device/r4300/cp0.c +++ b/mupen64plus-core/src/device/r4300/cp0.c @@ -36,10 +36,8 @@ #endif /* global functions */ -void init_cp0(struct cp0* cp0, unsigned int count_per_op, unsigned int count_per_op_denom_pot, struct new_dynarec_hot_state* new_dynarec_hot_state, const struct interrupt_handler* interrupt_handlers) +void init_cp0(struct cp0* cp0, struct new_dynarec_hot_state* new_dynarec_hot_state, const struct interrupt_handler* interrupt_handlers) { - cp0->count_per_op = count_per_op; - cp0->count_per_op_denom_pot = count_per_op_denom_pot; #ifdef NEW_DYNAREC cp0->new_dynarec_hot_state = new_dynarec_hot_state; #endif @@ -73,6 +71,7 @@ void poweron_cp0(struct cp0* cp0) cp0->interrupt_unsafe_state = 0; *cp0_next_interrupt = 0; *cp0_cycle_count = 0; + cp0->half_count = 0; cp0->last_addr = UINT32_C(0xbfc00000); init_interrupt(cp0); @@ -125,41 +124,22 @@ int check_cop1_unusable(struct r4300_core* r4300) return 0; } -void cp0_update_count(struct r4300_core* r4300) +void cp0_add_count(struct r4300_core* r4300, uint32_t count, uint8_t half) { struct cp0* cp0 = &r4300->cp0; uint32_t* cp0_regs = r4300_cp0_regs(cp0); - -#ifdef NEW_DYNAREC - if (r4300->emumode != EMUMODE_DYNAREC) + if (half) { -#endif - uint32_t count = ((*r4300_pc(r4300) - cp0->last_addr) >> 2) * cp0->count_per_op; - if (r4300->cp0.count_per_op_denom_pot) { - count += (1 << r4300->cp0.count_per_op_denom_pot) - 1; - count >>= r4300->cp0.count_per_op_denom_pot; - } - cp0_regs[CP0_COUNT_REG] += count; - *r4300_cp0_cycle_count(cp0) += count; - cp0->last_addr = *r4300_pc(r4300); -#ifdef NEW_DYNAREC + cp0->half_count ^= 1; + half = cp0->half_count; } - else - cp0_regs[CP0_COUNT_REG] = *r4300_cp0_next_interrupt(cp0) + *r4300_cp0_cycle_count(cp0); -#endif - -#ifdef COMPARE_CORE - if (r4300->delay_slot) - CoreCompareCallback(); -#endif -/*#ifdef DBG - if (g_DebuggerActive && !r4300->delay_slot) update_debugger(*r4300_pc(r4300)); -#endif -*/ + cp0_regs[CP0_COUNT_REG] += count + half; + *r4300_cp0_cycle_count(cp0) += count + half; } static void exception_epilog(struct r4300_core* r4300) { + cp0_add_count(r4300, 1, 0); #ifndef NO_ASM #ifndef NEW_DYNAREC if (r4300->emumode == EMUMODE_DYNAREC) @@ -193,10 +173,6 @@ void TLB_refill_exception(struct r4300_core* r4300, uint32_t address, int w) uint32_t* cp0_regs = r4300_cp0_regs(&r4300->cp0); int usual_handler = 0, i; - if (r4300->emumode != EMUMODE_DYNAREC && w != 2) { - cp0_update_count(r4300); - } - cp0_regs[CP0_CAUSE_REG] = (w == 1) ? CP0_CAUSE_EXCCODE_TLBS : CP0_CAUSE_EXCCODE_TLBL; @@ -276,7 +252,6 @@ void exception_general(struct r4300_core* r4300) { uint32_t* cp0_regs = r4300_cp0_regs(&r4300->cp0); - cp0_update_count(r4300); cp0_regs[CP0_STATUS_REG] |= CP0_STATUS_EXL; cp0_regs[CP0_EPC_REG] = *r4300_pc(r4300); diff --git a/mupen64plus-core/src/device/r4300/cp0.h b/mupen64plus-core/src/device/r4300/cp0.h index 5e1ecd5..8af56f6 100644 --- a/mupen64plus-core/src/device/r4300/cp0.h +++ b/mupen64plus-core/src/device/r4300/cp0.h @@ -201,10 +201,9 @@ struct cp0 #endif uint32_t last_addr; - unsigned int count_per_op; - unsigned int count_per_op_denom_pot; struct tlb tlb; + uint8_t half_count; }; #ifndef NEW_DYNAREC @@ -217,7 +216,7 @@ struct cp0 offsetof(struct new_dynarec_hot_state, cp0_regs)) #endif -void init_cp0(struct cp0* cp0, unsigned int count_per_op, unsigned int count_per_op_denom_pot, struct new_dynarec_hot_state* new_dynarec_hot_state, const struct interrupt_handler* interrupt_handlers); +void init_cp0(struct cp0* cp0, struct new_dynarec_hot_state* new_dynarec_hot_state, const struct interrupt_handler* interrupt_handlers); void poweron_cp0(struct cp0* cp0); uint32_t* r4300_cp0_regs(struct cp0* cp0); @@ -231,7 +230,7 @@ int* r4300_cp0_cycle_count(struct cp0* cp0); int check_cop1_unusable(struct r4300_core* r4300); -void cp0_update_count(struct r4300_core* r4300); +void cp0_add_count(struct r4300_core* r4300, uint32_t count, uint8_t half); void TLB_refill_exception(struct r4300_core* r4300, uint32_t address, int w); void exception_general(struct r4300_core* r4300); diff --git a/mupen64plus-core/src/device/r4300/interrupt.c b/mupen64plus-core/src/device/r4300/interrupt.c index 6c0e64d..b613ade 100644 --- a/mupen64plus-core/src/device/r4300/interrupt.c +++ b/mupen64plus-core/src/device/r4300/interrupt.c @@ -278,11 +278,11 @@ void translate_event_queue(struct cp0* cp0, unsigned int base) cp0_regs[CP0_COUNT_REG] = base; add_interrupt_event_count(cp0, SPECIAL_INT, ((cp0_regs[CP0_COUNT_REG] & UINT32_C(0x80000000)) ^ UINT32_C(0x80000000))); - /* Add count_per_op to avoid wrong event order in case CP0_COUNT_REG == CP0_COMPARE_REG */ - cp0_regs[CP0_COUNT_REG] += cp0->count_per_op; - *cp0_cycle_count += cp0->count_per_op; + /* Add 2 to avoid wrong event order in case CP0_COUNT_REG == CP0_COMPARE_REG */ + cp0_regs[CP0_COUNT_REG] += 2; + *cp0_cycle_count += 2; add_interrupt_event_count(cp0, COMPARE_INT, cp0_regs[CP0_COMPARE_REG]); - cp0_regs[CP0_COUNT_REG] -= cp0->count_per_op; + cp0_regs[CP0_COUNT_REG] -= 2; /* Update next interrupt in case first event is COMPARE_INT */ *cp0_cycle_count = cp0_regs[CP0_COUNT_REG] - cp0->q.first->data.count; @@ -399,11 +399,11 @@ void compare_int_handler(void* opaque) uint32_t* cp0_regs = r4300_cp0_regs(&r4300->cp0); int* cp0_cycle_count = r4300_cp0_cycle_count(&r4300->cp0); - /* Add count_per_op to avoid wrong event order in case CP0_COUNT_REG == CP0_COMPARE_REG */ - cp0_regs[CP0_COUNT_REG] += r4300->cp0.count_per_op; - *cp0_cycle_count += r4300->cp0.count_per_op; + /* Add 2 to avoid wrong event order in case CP0_COUNT_REG == CP0_COMPARE_REG */ + cp0_regs[CP0_COUNT_REG] += 2; + *cp0_cycle_count += 2; add_interrupt_event_count(&r4300->cp0, COMPARE_INT, cp0_regs[CP0_COMPARE_REG]); - cp0_regs[CP0_COUNT_REG] -= r4300->cp0.count_per_op; + cp0_regs[CP0_COUNT_REG] -= 2; /* Update next interrupt in case first event is COMPARE_INT */ *cp0_cycle_count = cp0_regs[CP0_COUNT_REG] - r4300->cp0.q.first->data.count; diff --git a/mupen64plus-core/src/device/r4300/mips_instructions.def b/mupen64plus-core/src/device/r4300/mips_instructions.def index 89218aa..0a16e69 100644 --- a/mupen64plus-core/src/device/r4300/mips_instructions.def +++ b/mupen64plus-core/src/device/r4300/mips_instructions.def @@ -105,7 +105,7 @@ DECLARE_INSTRUCTION(NI) { DECLARE_R4300 DebugMessage(M64MSG_ERROR, "NI() @ 0x%" PRIX32, PCADDR); - DebugMessage(M64MSG_ERROR, "opcode not implemented: %" PRIX32 ":%" PRIX32, PCADDR, *fast_mem_access(r4300, PCADDR)); + DebugMessage(M64MSG_ERROR, "opcode not implemented: %" PRIX32 ":%" PRIX32, PCADDR, *fast_mem_access(r4300, PCADDR, 0)); *r4300_stop(r4300) = 1; } @@ -114,7 +114,7 @@ DECLARE_INSTRUCTION(NI) DECLARE_INSTRUCTION(RESERVED) { DECLARE_R4300 - DebugMessage(M64MSG_ERROR, "reserved opcode: %" PRIX32 ":%" PRIX32, PCADDR, *fast_mem_access(r4300, PCADDR)); + DebugMessage(M64MSG_ERROR, "reserved opcode: %" PRIX32 ":%" PRIX32, PCADDR, *fast_mem_access(r4300, PCADDR, 0)); *r4300_stop(r4300) = 1; } @@ -591,6 +591,7 @@ DECLARE_INSTRUCTION(NOR) { DECLARE_R4300 rrd = ~(rrs | rrt); + cp0_add_count(r4300, 28, 1); ADD_TO_PC(1); } @@ -723,6 +724,7 @@ DECLARE_INSTRUCTION(MULT) temp = rrs32 * (int64_t)rrt32; *r4300_mult_hi(r4300) = temp >> 32; *r4300_mult_lo(r4300) = SE32(temp); + cp0_add_count(r4300, 2, 1); ADD_TO_PC(1); } @@ -733,6 +735,7 @@ DECLARE_INSTRUCTION(MULTU) temp = (uint32_t) rrs * (uint64_t) ((uint32_t) rrt); *r4300_mult_hi(r4300) = (int64_t) temp >> 32; *r4300_mult_lo(r4300) = SE32(temp); + cp0_add_count(r4300, 2, 1); ADD_TO_PC(1); } @@ -780,6 +783,7 @@ DECLARE_INSTRUCTION(DMULT) if (!*r4300_mult_lo(r4300)) { (*r4300_mult_hi(r4300))++; } else { *r4300_mult_lo(r4300) = ~*r4300_mult_lo(r4300) + 1; } } + cp0_add_count(r4300, 4, 0); ADD_TO_PC(1); } @@ -808,6 +812,7 @@ DECLARE_INSTRUCTION(DMULTU) *r4300_mult_lo(r4300) = result1 | (result2 << 32); *r4300_mult_hi(r4300) = (result3 & UINT64_C(0xFFFFFFFF)) | (result4 << 32); + cp0_add_count(r4300, 4, 0); ADD_TO_PC(1); } @@ -832,6 +837,7 @@ DECLARE_INSTRUCTION(DIV) *r4300_mult_lo(r4300) = rrs32 < 0 ? 1 : -1; *r4300_mult_hi(r4300) = SE32(rrs32); } + cp0_add_count(r4300, 18, 1); ADD_TO_PC(1); } @@ -848,6 +854,7 @@ DECLARE_INSTRUCTION(DIVU) *r4300_mult_lo(r4300) = -1; *r4300_mult_hi(r4300) = SE32(rrs32); } + cp0_add_count(r4300, 18, 1); ADD_TO_PC(1); } @@ -872,6 +879,7 @@ DECLARE_INSTRUCTION(DDIV) *r4300_mult_lo(r4300) = rrs < 0 ? 1 : -1; *r4300_mult_hi(r4300) = rrs; } + cp0_add_count(r4300, 34, 1); ADD_TO_PC(1); } @@ -888,6 +896,7 @@ DECLARE_INSTRUCTION(DDIVU) *r4300_mult_lo(r4300) = -1; *r4300_mult_hi(r4300) = rrs; } + cp0_add_count(r4300, 34, 1); ADD_TO_PC(1); } @@ -959,6 +968,83 @@ DECLARE_JUMP(BC1TL, PCADDR + (iimmediate+1)*4, ((*r4300_cp1_fcr31(&r4300->cp1)) DECLARE_INSTRUCTION(CACHE) { DECLARE_R4300 + uint32_t lslfaddr = (uint32_t) r4300_regs(r4300)[lfbase] + lfoffset; + if (r4300_translate_address(r4300, &lslfaddr, &(uint8_t){0}, 2, 0)) + return; // TLB exception + uint32_t* cp0_regs = r4300_cp0_regs(&r4300->cp0); + const unsigned char lslfft = lfft; + struct datacache *dcache_line = &r4300->mem->dcache[lslfaddr >> 4 & UINT32_C(0x1FF)]; + struct instcache *icache_line = &r4300->mem->icache[lslfaddr >> 5 & UINT32_C(0x1FF)]; + switch (lslfft) + { + case 0x00: //icache index invalidate + icache_line->valid = 0; + break; + case 0x04: //icache load tag + masked_write(&cp0_regs[CP0_TAGLO_REG], icache_line->valid << 7, UINT32_C(0x80)); + masked_write(&cp0_regs[CP0_TAGLO_REG], 0, UINT32_C(0x40)); + masked_write(&cp0_regs[CP0_TAGLO_REG], icache_line->tag >> 4, UINT32_C(0xFFFFF00)); + break; + case 0x08: //icache store tag + icache_line->valid = (cp0_regs[CP0_TAGLO_REG] & UINT32_C(0x80)) >> 7; + icache_line->tag = (cp0_regs[CP0_TAGLO_REG] & UINT32_C(0xFFFFF00)) << 4; + break; + case 0x10: //icache hit invalidate + if(icache_hit(icache_line, lslfaddr)) + icache_line->valid = 0; + break; + case 0x14: //icache fill + icache_fill(icache_line, r4300, lslfaddr); + break; + case 0x18: //icache hit write back + if(icache_hit(icache_line, lslfaddr)) + icache_writeback(r4300, icache_line); + break; + case 0x01: //dcache index write back invalidate + if (dcache_line->dirty && dcache_line->valid) + dcache_writeback(r4300, dcache_line); + dcache_line->valid = 0; + break; + case 0x05: //dcache index load tag + masked_write(&cp0_regs[CP0_TAGLO_REG], dcache_line->valid << 7, UINT32_C(0x80)); + masked_write(&cp0_regs[CP0_TAGLO_REG], dcache_line->dirty << 6, UINT32_C(0x40)); + masked_write(&cp0_regs[CP0_TAGLO_REG], dcache_line->tag >> 4, UINT32_C(0xFFFFF00)); + break; + case 0x09: //dcache index store tag + dcache_line->valid = (cp0_regs[CP0_TAGLO_REG] & UINT32_C(0x80)) >> 7; + dcache_line->dirty = (cp0_regs[CP0_TAGLO_REG] & UINT32_C(0x40)) >> 6; + dcache_line->tag = (cp0_regs[CP0_TAGLO_REG] & UINT32_C(0xFFFFF00)) << 4; + break; + case 0x0D: //dcache create dirty exclusive + if(!dcache_hit(dcache_line, lslfaddr) && dcache_line->dirty) + dcache_writeback(r4300, dcache_line); + dcache_line->tag = lslfaddr & ~UINT32_C(0xFFF); + dcache_line->valid = 1; + dcache_line->dirty = 1; + break; + case 0x11: //dcache hit invalidate + if(dcache_hit(dcache_line, lslfaddr)) + { + dcache_line->valid = 0; + dcache_line->dirty = 0; + } + break; + case 0x15: //dcache hit write back invalidate + if(dcache_hit(dcache_line, lslfaddr)) + { + if(dcache_line->dirty) + dcache_writeback(r4300, dcache_line); + dcache_line->valid = 0; + } + break; + case 0x19: //dcache hit write back + if(dcache_hit(dcache_line, lslfaddr)) + { + if(dcache_line->dirty) + dcache_writeback(r4300, dcache_line); + } + break; + } ADD_TO_PC(1); } @@ -968,7 +1054,6 @@ DECLARE_INSTRUCTION(ERET) uint32_t* cp0_regs = r4300_cp0_regs(&r4300->cp0); int* cp0_cycle_count = r4300_cp0_cycle_count(&r4300->cp0); - cp0_update_count(r4300); if (cp0_regs[CP0_STATUS_REG] & CP0_STATUS_ERL) { DebugMessage(M64MSG_ERROR, "error in ERET"); @@ -1191,8 +1276,7 @@ DECLARE_INSTRUCTION(TLBWR) { DECLARE_R4300 uint32_t* cp0_regs = r4300_cp0_regs(&r4300->cp0); - cp0_update_count(r4300); - cp0_regs[CP0_RANDOM_REG] = (cp0_regs[CP0_COUNT_REG]/r4300->cp0.count_per_op % (32 - cp0_regs[CP0_WIRED_REG])) + cp0_regs[CP0_RANDOM_REG] = (cp0_regs[CP0_COUNT_REG]/2 % (32 - cp0_regs[CP0_WIRED_REG])) + cp0_regs[CP0_WIRED_REG]; TLBWrite(r4300, cp0_regs[CP0_RANDOM_REG]); ADD_TO_PC(1); @@ -1217,12 +1301,10 @@ DECLARE_INSTRUCTION(MFC0) switch(rfs) { case CP0_RANDOM_REG: - cp0_update_count(r4300); - cp0_regs[CP0_RANDOM_REG] = (cp0_regs[CP0_COUNT_REG]/r4300->cp0.count_per_op % (32 - cp0_regs[CP0_WIRED_REG])) + cp0_regs[CP0_RANDOM_REG] = (cp0_regs[CP0_COUNT_REG]/2 % (32 - cp0_regs[CP0_WIRED_REG])) + cp0_regs[CP0_WIRED_REG]; break; case CP0_COUNT_REG: - cp0_update_count(r4300); break; } rrt = SE32(cp0_regs[rfs]); @@ -1267,7 +1349,6 @@ DECLARE_INSTRUCTION(MTC0) case CP0_BADVADDR_REG: break; case CP0_COUNT_REG: - cp0_update_count(r4300); r4300->cp0.interrupt_unsafe_state |= INTR_UNSAFE_R4300; if (*cp0_cycle_count >= 0) { gen_interrupt(r4300); } r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_R4300; @@ -1277,14 +1358,13 @@ DECLARE_INSTRUCTION(MTC0) cp0_regs[CP0_ENTRYHI_REG] = rrt32 & UINT32_C(0xFFFFE0FF); break; case CP0_COMPARE_REG: - cp0_update_count(r4300); remove_event(&r4300->cp0.q, COMPARE_INT); - /* Add count_per_op to avoid wrong event order in case CP0_COUNT_REG == CP0_COMPARE_REG */ - cp0_regs[CP0_COUNT_REG] += r4300->cp0.count_per_op; - *cp0_cycle_count += r4300->cp0.count_per_op; + /* Add 2 to avoid wrong event order in case CP0_COUNT_REG == CP0_COMPARE_REG */ + cp0_regs[CP0_COUNT_REG] += 2; + *cp0_cycle_count += 2; add_interrupt_event_count(&r4300->cp0, COMPARE_INT, rrt32); - cp0_regs[CP0_COUNT_REG] -= r4300->cp0.count_per_op; + cp0_regs[CP0_COUNT_REG] -= 2; /* Update next interrupt in case first event is COMPARE_INT */ *cp0_cycle_count = cp0_regs[CP0_COUNT_REG] - r4300->cp0.q.first->data.count; @@ -1297,7 +1377,6 @@ DECLARE_INSTRUCTION(MTC0) cp0_regs[CP0_STATUS_REG] = rrt32; ADD_TO_PC(1); - cp0_update_count(r4300); r4300_check_interrupt(r4300, CP0_CAUSE_IP2, r4300->mi->regs[MI_INTR_REG] & r4300->mi->regs[MI_INTR_MASK_REG]); // ??? r4300->cp0.interrupt_unsafe_state |= INTR_UNSAFE_R4300; if (*cp0_cycle_count >= 0) { gen_interrupt(r4300); } diff --git a/mupen64plus-core/src/device/r4300/new_dynarec/new_dynarec.c b/mupen64plus-core/src/device/r4300/new_dynarec/new_dynarec.c index b371631..25fa9a5 100644 --- a/mupen64plus-core/src/device/r4300/new_dynarec/new_dynarec.c +++ b/mupen64plus-core/src/device/r4300/new_dynarec/new_dynarec.c @@ -1858,7 +1858,6 @@ void* ERET_new(void) struct r4300_core* r4300 = &g_dev.r4300; struct new_dynarec_hot_state* state = &r4300->new_dynarec_hot_state; - cp0_update_count(r4300); if (state->cp0_regs[CP0_STATUS_REG] & CP0_STATUS_ERL) { DebugMessage(M64MSG_ERROR, "error in ERET"); @@ -1976,7 +1975,6 @@ static void TLBWR_new(int pcaddr, int count) unsigned int i; UPDATE_COUNT_IN state->pcaddr = pcaddr; - cp0_update_count(r4300); state->cp0_regs[CP0_RANDOM_REG] = (state->cp0_regs[CP0_COUNT_REG]/r4300->cp0.count_per_op % (32 - state->cp0_regs[CP0_WIRED_REG])) + state->cp0_regs[CP0_WIRED_REG]; /* Remove old entries */ unsigned int old_start_even=r4300->cp0.tlb.entries[state->cp0_regs[CP0_RANDOM_REG]&0x3F].start_even; @@ -3021,7 +3019,6 @@ void dynarec_gen_interrupt(void) { struct r4300_core* r4300 = &g_dev.r4300; struct new_dynarec_hot_state* state = &r4300->new_dynarec_hot_state; - cp0_update_count(r4300); uint32_t page = ((state->cp0_regs[CP0_COUNT_REG]>>19)&0x1fc); unsigned int *candidate = (unsigned int *)&restore_candidate[page]; page <<= 3; diff --git a/mupen64plus-core/src/device/r4300/pure_interp.c b/mupen64plus-core/src/device/r4300/pure_interp.c index 09d1a4c..ba5fe4e 100644 --- a/mupen64plus-core/src/device/r4300/pure_interp.c +++ b/mupen64plus-core/src/device/r4300/pure_interp.c @@ -59,7 +59,6 @@ static void InterpretOpcode(struct r4300_core* r4300); r4300->interp_PC.addr += 4; \ r4300->delay_slot=1; \ InterpretOpcode(r4300); \ - cp0_update_count(r4300); \ r4300->delay_slot=0; \ if (take_jump && !r4300->skip_jump) \ { \ @@ -69,7 +68,6 @@ static void InterpretOpcode(struct r4300_core* r4300); else \ { \ r4300->interp_PC.addr += 8; \ - cp0_update_count(r4300); \ } \ r4300->cp0.last_addr = r4300->interp_PC.addr; \ if (*r4300_cp0_cycle_count(&r4300->cp0) >= 0) gen_interrupt(r4300); \ @@ -82,7 +80,6 @@ static void InterpretOpcode(struct r4300_core* r4300); if (cop1 && check_cop1_unusable(r4300)) return; \ if (take_jump) \ { \ - cp0_update_count(r4300); \ if(*cp0_cycle_count < 0) \ { \ cp0_regs[CP0_COUNT_REG] -= *cp0_cycle_count; \ @@ -108,7 +105,7 @@ static void InterpretOpcode(struct r4300_core* r4300); * relative to the instruction in the delay slot, so 1 instruction backwards * (-1) goes back to the jump. */ #define IS_RELATIVE_IDLE_LOOP(r4300, op, addr) \ - (IMM16S_OF(op) == -1 && *fast_mem_access((r4300), (addr) + 4) == 0) + (IMM16S_OF(op) == -1 && *fast_mem_access((r4300), (addr) + 4, 0) == 0) /* Determines whether an absolute jump in a 26-bit immediate goes back to the * same instruction without doing any work in its delay slot. The jump is @@ -117,7 +114,7 @@ static void InterpretOpcode(struct r4300_core* r4300); #define IS_ABSOLUTE_IDLE_LOOP(r4300, op, addr) \ (JUMP_OF(op) == ((addr) & UINT32_C(0x0FFFFFFF)) >> 2 \ && ((addr) & UINT32_C(0x0FFFFFFF)) != UINT32_C(0x0FFFFFFC) \ - && *fast_mem_access((r4300), (addr) + 4) == 0) + && *fast_mem_access((r4300), (addr) + 4, 0) == 0) /* These macros parse opcode fields. */ #define rrt r4300_regs(r4300)[RT_OF(op)] @@ -164,7 +161,7 @@ static void InterpretOpcode(struct r4300_core* r4300); void InterpretOpcode(struct r4300_core* r4300) { - uint32_t* op_address = fast_mem_access(r4300, *r4300_pc(r4300)); + uint32_t* op_address = fast_mem_access(r4300, *r4300_pc(r4300), 1); if (op_address == NULL) return; uint32_t op = *op_address; diff --git a/mupen64plus-core/src/device/r4300/r4300_core.c b/mupen64plus-core/src/device/r4300/r4300_core.c index e87a3d8..cc80b7c 100644 --- a/mupen64plus-core/src/device/r4300/r4300_core.c +++ b/mupen64plus-core/src/device/r4300/r4300_core.c @@ -41,7 +41,7 @@ #include void init_r4300(struct r4300_core* r4300, struct memory* mem, struct mi_controller* mi, struct rdram* rdram, const struct interrupt_handler* interrupt_handlers, - unsigned int emumode, unsigned int count_per_op, unsigned int count_per_op_denom_pot, int no_compiled_jump, int randomize_interrupt, uint32_t start_address) + unsigned int emumode, int no_compiled_jump, int randomize_interrupt, uint32_t start_address) { struct new_dynarec_hot_state* new_dynarec_hot_state = #ifdef NEW_DYNAREC @@ -51,7 +51,7 @@ void init_r4300(struct r4300_core* r4300, struct memory* mem, struct mi_controll #endif r4300->emumode = emumode; - init_cp0(&r4300->cp0, count_per_op, count_per_op_denom_pot, new_dynarec_hot_state, interrupt_handlers); + init_cp0(&r4300->cp0, new_dynarec_hot_state, interrupt_handlers); init_cp1(&r4300->cp1, new_dynarec_hot_state); #ifndef NEW_DYNAREC @@ -63,6 +63,7 @@ void init_r4300(struct r4300_core* r4300, struct memory* mem, struct mi_controll r4300->rdram = rdram; r4300->randomize_interrupt = randomize_interrupt; r4300->start_address = start_address; + r4300->clock_rate = 93750000 / 2; srand((unsigned int) time(NULL)); } @@ -277,19 +278,38 @@ unsigned int get_r4300_emumode(struct r4300_core* r4300) return r4300->emumode; } -uint32_t *fast_mem_access(struct r4300_core* r4300, uint32_t address) +uint8_t r4300_translate_address(struct r4300_core* r4300, uint32_t* address, uint8_t* cached, uint8_t tlb_mode, uint8_t write) +{ + if ((*address & UINT32_C(0xc0000000)) != UINT32_C(0x80000000)) { + if (write) + invalidate_r4300_cached_code(r4300, *address, write); + *address = virtual_to_physical_address(r4300, *address, tlb_mode, cached); + if (*address == 0) // TLB exception + return 1; + } else if (!(*address & UINT32_C(0x20000000))) + *cached = 1; + + if (write) + { + invalidate_r4300_cached_code(r4300, *address, write); + invalidate_r4300_cached_code(r4300, *address ^ UINT32_C(0x20000000), write); + } + return 0; +} + +uint32_t *fast_mem_access(struct r4300_core* r4300, uint32_t address, uint8_t use_cache) { /* This code is performance critical, specially on pure interpreter mode. * Removing error checking saves some time, but the emulator may crash. */ + uint8_t cached = 0; + if (r4300_translate_address(r4300, &address, &cached, 2, 0)) + return NULL; // TLB exception - if ((address & UINT32_C(0xc0000000)) != UINT32_C(0x80000000)) { - address = virtual_to_physical_address(r4300, address, 2); - if (address == 0) // TLB exception - return NULL; - } - + if (use_cache && cached) + return icache_fetch(r4300, address); + if (use_cache && !cached) + cp0_add_count(r4300, 18, 1); address &= UINT32_C(0x1ffffffc); - return mem_base_u32(r4300->mem->base, address); } @@ -299,17 +319,19 @@ uint32_t *fast_mem_access(struct r4300_core* r4300, uint32_t address) */ int r4300_read_aligned_word(struct r4300_core* r4300, uint32_t address, uint32_t* value) { - if ((address & UINT32_C(0xc0000000)) != UINT32_C(0x80000000)) { - address = virtual_to_physical_address(r4300, address, 0); - if (address == 0) { - return 0; - } + uint8_t cached = 0; + if (r4300_translate_address(r4300, &address, &cached, 0, 0)) + return 0; // TLB exception + + if (cached) + dcache_read32(r4300, address & ~UINT32_C(3), value); + else + { + cp0_add_count(r4300, 18, 1); + address &= UINT32_C(0x1ffffffc); + mem_read32(mem_get_handler(r4300->mem, address), address & ~UINT32_C(3), value); } - address &= UINT32_C(0x1ffffffc); - - mem_read32(mem_get_handler(r4300->mem, address), address & ~UINT32_C(3), value); - return 1; } @@ -317,6 +339,7 @@ int r4300_read_aligned_word(struct r4300_core* r4300, uint32_t address, uint32_t int r4300_read_aligned_dword(struct r4300_core* r4300, uint32_t address, uint64_t* value) { uint32_t w[2]; + uint8_t cached = 0; /* XXX: unaligned dword accesses should trigger a address error, * but inaccurate timing of the core can lead to unaligned address on reset @@ -325,18 +348,22 @@ int r4300_read_aligned_dword(struct r4300_core* r4300, uint32_t address, uint64_ DebugMessage(M64MSG_WARNING, "Unaligned dword read %08x", address); } - if ((address & UINT32_C(0xc0000000)) != UINT32_C(0x80000000)) { - address = virtual_to_physical_address(r4300, address, 0); - if (address == 0) { - return 0; - } + if (r4300_translate_address(r4300, &address, &cached, 0, 0)) + return 0; // TLB exception + + if (cached) + { + dcache_read32(r4300, address + 0, &w[0]); + dcache_read32(r4300, address + 4, &w[1]); + } + else + { + cp0_add_count(r4300, 18, 1); + address &= UINT32_C(0x1ffffffc); + const struct mem_handler* handler = mem_get_handler(r4300->mem, address); + mem_read32(handler, address + 0, &w[0]); + mem_read32(handler, address + 4, &w[1]); } - - address &= UINT32_C(0x1ffffffc); - - const struct mem_handler* handler = mem_get_handler(r4300->mem, address); - mem_read32(handler, address + 0, &w[0]); - mem_read32(handler, address + 4, &w[1]); *value = ((uint64_t)w[0] << 32) | w[1]; @@ -349,29 +376,26 @@ int r4300_read_aligned_dword(struct r4300_core* r4300, uint32_t address, uint64_ */ int r4300_write_aligned_word(struct r4300_core* r4300, uint32_t address, uint32_t value, uint32_t mask) { - if ((address & UINT32_C(0xc0000000)) != UINT32_C(0x80000000)) { + uint8_t cached = 0; + if (r4300_translate_address(r4300, &address, &cached, 1, 4)) + return 0; // TLB exception - invalidate_r4300_cached_code(r4300, address, 4); - - address = virtual_to_physical_address(r4300, address, 1); - if (address == 0) { - return 0; - } + if (cached) + dcache_write32(r4300, address & ~UINT32_C(3), value, mask); + else + { + cp0_add_count(r4300, 18, 1); + address &= UINT32_C(0x1ffffffc); + mem_write32(mem_get_handler(r4300->mem, address), address & ~UINT32_C(3), value, mask); } - invalidate_r4300_cached_code(r4300, address, 4); - invalidate_r4300_cached_code(r4300, address ^ UINT32_C(0x20000000), 4); - - address &= UINT32_C(0x1ffffffc); - - mem_write32(mem_get_handler(r4300->mem, address), address & ~UINT32_C(3), value, mask); - return 1; } /* Write aligned dword to memory */ int r4300_write_aligned_dword(struct r4300_core* r4300, uint32_t address, uint64_t value, uint64_t mask) { + uint8_t cached = 0; /* XXX: unaligned dword accesses should trigger a address error, * but inaccurate timing of the core can lead to unaligned address on reset * so just emit a warning and keep going */ @@ -379,24 +403,22 @@ int r4300_write_aligned_dword(struct r4300_core* r4300, uint32_t address, uint64 DebugMessage(M64MSG_WARNING, "Unaligned dword write %08x", address); } - if ((address & UINT32_C(0xc0000000)) != UINT32_C(0x80000000)) { + if (r4300_translate_address(r4300, &address, &cached, 1, 8)) + return 0; // TLB exception - invalidate_r4300_cached_code(r4300, address, 8); - - address = virtual_to_physical_address(r4300, address, 1); - if (address == 0) { - return 0; - } + if (cached) + { + dcache_write32(r4300, address + 0, value >> 32, mask >> 32); + dcache_write32(r4300, address + 4, (uint32_t) value, (uint32_t) mask); + } + else + { + cp0_add_count(r4300, 18, 1); + address &= UINT32_C(0x1ffffffc); + const struct mem_handler* handler = mem_get_handler(r4300->mem, address); + mem_write32(handler, address + 0, value >> 32, mask >> 32); + mem_write32(handler, address + 4, (uint32_t) value, (uint32_t) mask); } - - invalidate_r4300_cached_code(r4300, address, 8); - invalidate_r4300_cached_code(r4300, address ^ UINT32_C(0x20000000), 8); - - address &= UINT32_C(0x1ffffffc); - - const struct mem_handler* handler = mem_get_handler(r4300->mem, address); - mem_write32(handler, address + 0, value >> 32, mask >> 32); - mem_write32(handler, address + 4, (uint32_t) value, (uint32_t) mask ); return 1; } diff --git a/mupen64plus-core/src/device/r4300/r4300_core.h b/mupen64plus-core/src/device/r4300/r4300_core.h index 335b10e..2b3e644 100644 --- a/mupen64plus-core/src/device/r4300/r4300_core.h +++ b/mupen64plus-core/src/device/r4300/r4300_core.h @@ -197,6 +197,7 @@ struct r4300_core uint32_t randomize_interrupt; uint32_t start_address; + uint32_t clock_rate; }; #define R4300_KSEG0 UINT32_C(0x80000000) @@ -211,7 +212,7 @@ struct r4300_core offsetof(struct new_dynarec_hot_state, regs)) #endif -void init_r4300(struct r4300_core* r4300, struct memory* mem, struct mi_controller* mi, struct rdram* rdram, const struct interrupt_handler* interrupt_handlers, unsigned int emumode, unsigned int count_per_op, unsigned int count_per_op_denom_pot, int no_compiled_jump, int randomize_interrupt, uint32_t start_address); +void init_r4300(struct r4300_core* r4300, struct memory* mem, struct mi_controller* mi, struct rdram* rdram, const struct interrupt_handler* interrupt_handlers, unsigned int emumode, int no_compiled_jump, int randomize_interrupt, uint32_t start_address); void poweron_r4300(struct r4300_core* r4300); void run_r4300(struct r4300_core* r4300); @@ -229,7 +230,9 @@ unsigned int get_r4300_emumode(struct r4300_core* r4300); /* Returns a pointer to a block of contiguous memory * Can access RDRAM, SP_DMEM, SP_IMEM and ROM, using TLB if necessary * Useful for getting fast access to a zone with executable code. */ -uint32_t *fast_mem_access(struct r4300_core* r4300, uint32_t address); +uint32_t *fast_mem_access(struct r4300_core* r4300, uint32_t address, uint8_t use_cache); + +uint8_t r4300_translate_address(struct r4300_core* r4300, uint32_t* address, uint8_t* cached, uint8_t tlb_mode, uint8_t write); int r4300_read_aligned_word(struct r4300_core* r4300, uint32_t address, uint32_t* value); int r4300_read_aligned_dword(struct r4300_core* r4300, uint32_t address, uint64_t* value); diff --git a/mupen64plus-core/src/device/r4300/recomp.c b/mupen64plus-core/src/device/r4300/recomp.c index d31c691..674d02e 100644 --- a/mupen64plus-core/src/device/r4300/recomp.c +++ b/mupen64plus-core/src/device/r4300/recomp.c @@ -578,7 +578,7 @@ void dynarec_init_block(struct r4300_core* r4300, uint32_t address) r4300->cached_interp.invalid_code[b->start>>12] = 0; if (b->end < UINT32_C(0x80000000) || b->start >= UINT32_C(0xc0000000)) { - uint32_t paddr = virtual_to_physical_address(r4300, b->start, 2); + uint32_t paddr = virtual_to_physical_address(r4300, b->start, 2, &(uint8_t){0}); r4300->cached_interp.invalid_code[paddr>>12] = 0; dynarec_init_block(r4300, paddr); @@ -655,7 +655,7 @@ void dynarec_recompile_block(struct r4300_core* r4300, const uint32_t* iw, struc if (block_start_in_tlb) { - uint32_t address2 = virtual_to_physical_address(r4300, r4300->recomp.dst->addr, 0); + uint32_t address2 = virtual_to_physical_address(r4300, r4300->recomp.dst->addr, 0, &(uint8_t){0}); if (r4300->cached_interp.blocks[address2>>12]->block[(address2&UINT32_C(0xFFF))/4].ops == r4300->cached_interp.not_compiled) { r4300->cached_interp.blocks[address2>>12]->block[(address2&UINT32_C(0xFFF))/4].ops = r4300->cached_interp.not_compiled2; } @@ -923,7 +923,6 @@ int dynarec_check_cop1_unusable(void) /* Parameterless version of cp0_update_count to ease usage in dynarec. */ void dynarec_cp0_update_count(void) { - cp0_update_count(&g_dev.r4300); } /* Parameterless version of gen_interrupt to ease usage in dynarec. */ diff --git a/mupen64plus-core/src/device/r4300/tlb.c b/mupen64plus-core/src/device/r4300/tlb.c index b7a29e8..f4d16d4 100644 --- a/mupen64plus-core/src/device/r4300/tlb.c +++ b/mupen64plus-core/src/device/r4300/tlb.c @@ -34,6 +34,8 @@ void poweron_tlb(struct tlb* tlb) memset(tlb->entries, 0, 32 * sizeof(tlb->entries[0])); memset(tlb->LUT_r, 0, 0x100000 * sizeof(tlb->LUT_r[0])); memset(tlb->LUT_w, 0, 0x100000 * sizeof(tlb->LUT_w[0])); + memset(tlb->r_cached, 0, 0x100000 * sizeof(tlb->r_cached[0])); + memset(tlb->w_cached, 0, 0x100000 * sizeof(tlb->w_cached[0])); } void tlb_unmap(struct tlb* tlb, size_t entry) @@ -47,19 +49,31 @@ void tlb_unmap(struct tlb* tlb, size_t entry) if (e->v_even) { for (i=e->start_even; iend_even; i += 0x1000) + { tlb->LUT_r[i>>12] = 0; + tlb->r_cached[i>>12] = 0; + } if (e->d_even) for (i=e->start_even; iend_even; i += 0x1000) + { tlb->LUT_w[i>>12] = 0; + tlb->w_cached[i>>12] = 0; + } } if (e->v_odd) { for (i=e->start_odd; iend_odd; i += 0x1000) + { tlb->LUT_r[i>>12] = 0; + tlb->r_cached[i>>12] = 0; + } if (e->d_odd) for (i=e->start_odd; iend_odd; i += 0x1000) + { tlb->LUT_w[i>>12] = 0; + tlb->w_cached[i>>12] = 0; + } } } @@ -78,10 +92,16 @@ void tlb_map(struct tlb* tlb, size_t entry) e->phys_even < 0x20000000) { for (i=e->start_even;iend_even;i+=0x1000) + { tlb->LUT_r[i>>12] = UINT32_C(0x80000000) | (e->phys_even + (i - e->start_even) + 0xFFF); + tlb->r_cached[i>>12] = e->c_even != 2; + } if (e->d_even) for (i=e->start_even;iend_even;i+=0x1000) + { tlb->LUT_w[i>>12] = UINT32_C(0x80000000) | (e->phys_even + (i - e->start_even) + 0xFFF); + tlb->w_cached[i>>12] = e->c_even != 2; + } } } @@ -92,15 +112,21 @@ void tlb_map(struct tlb* tlb, size_t entry) e->phys_odd < 0x20000000) { for (i=e->start_odd;iend_odd;i+=0x1000) + { tlb->LUT_r[i>>12] = UINT32_C(0x80000000) | (e->phys_odd + (i - e->start_odd) + 0xFFF); + tlb->r_cached[i>>12] = e->c_odd != 2; + } if (e->d_odd) for (i=e->start_odd;iend_odd;i+=0x1000) + { tlb->LUT_w[i>>12] = UINT32_C(0x80000000) | (e->phys_odd + (i - e->start_odd) + 0xFFF); + tlb->w_cached[i>>12] = e->c_odd != 2; + } } } } -uint32_t virtual_to_physical_address(struct r4300_core* r4300, uint32_t address, int w) +uint32_t virtual_to_physical_address(struct r4300_core* r4300, uint32_t address, int w, uint8_t *cached) { const struct tlb* tlb = &r4300->cp0.tlb; unsigned int addr = address >> 12; @@ -130,12 +156,18 @@ uint32_t virtual_to_physical_address(struct r4300_core* r4300, uint32_t address, if (w == 1) { if (tlb->LUT_w[addr]) + { + *cached = tlb->w_cached[addr]; return (tlb->LUT_w[addr] & UINT32_C(0xFFFFF000)) | (address & UINT32_C(0xFFF)); + } } else { if (tlb->LUT_r[addr]) + { + *cached = tlb->r_cached[addr]; return (tlb->LUT_r[addr] & UINT32_C(0xFFFFF000)) | (address & UINT32_C(0xFFF)); + } } //printf("tlb exception !!! @ %x, %x, add:%x\n", address, w, r4300->pc->addr); //getchar(); diff --git a/mupen64plus-core/src/device/r4300/tlb.h b/mupen64plus-core/src/device/r4300/tlb.h index e0def6e..e0eb3a2 100644 --- a/mupen64plus-core/src/device/r4300/tlb.h +++ b/mupen64plus-core/src/device/r4300/tlb.h @@ -57,6 +57,8 @@ struct tlb struct tlb_entry entries[32]; uint32_t LUT_r[0x100000]; uint32_t LUT_w[0x100000]; + uint8_t r_cached[0x100000]; + uint8_t w_cached[0x100000]; }; void poweron_tlb(struct tlb* tlb); @@ -64,6 +66,6 @@ void poweron_tlb(struct tlb* tlb); void tlb_unmap(struct tlb* tlb, size_t entry); void tlb_map(struct tlb* tlb, size_t entry); -uint32_t virtual_to_physical_address(struct r4300_core* r4300, uint32_t address, int w); +uint32_t virtual_to_physical_address(struct r4300_core* r4300, uint32_t address, int w, uint8_t *cached); #endif /* M64P_DEVICE_R4300_TLB_H */ diff --git a/mupen64plus-core/src/device/rcp/ai/ai_controller.c b/mupen64plus-core/src/device/rcp/ai/ai_controller.c index bc46a5f..07d9fc6 100644 --- a/mupen64plus-core/src/device/rcp/ai/ai_controller.c +++ b/mupen64plus-core/src/device/rcp/ai/ai_controller.c @@ -45,7 +45,6 @@ static uint32_t get_remaining_dma_length(struct ai_controller* ai) if (ai->fifo[0].duration == 0) return 0; - cp0_update_count(ai->mi->r4300); next_ai_event = get_event(&ai->mi->r4300->cp0.q, AI_INT); if (next_ai_event == NULL) return 0; @@ -64,9 +63,9 @@ static unsigned int get_dma_duration(struct ai_controller* ai) { unsigned int samples_per_sec = ai->vi->clock / (1 + ai->regs[AI_DACRATE_REG]); unsigned int bytes_per_sample = 4; /* XXX: assume 16bit stereo - should depends on bitrate instead */ - unsigned int cpu_counts_per_sec = ai->vi->delay == 0 ? ai->vi->clock : ai->vi->delay * ai->vi->expected_refresh_rate; /* estimate cpu counts/sec using VI */ + unsigned int length = (ai->regs[AI_LEN_REG] & ~UINT32_C(7)) - 8; - return ai->regs[AI_LEN_REG] * (cpu_counts_per_sec / (bytes_per_sample * samples_per_sec)); + return length * (ai->mi->r4300->clock_rate / (bytes_per_sample * samples_per_sec)); } @@ -94,7 +93,6 @@ static void do_dma(struct ai_controller* ai, struct ai_dma* dma) ai->delayed_carry = 0; /* schedule end of dma event */ - cp0_update_count(ai->mi->r4300); add_interrupt_event(&ai->mi->r4300->cp0, AI_INT, dma->duration); } diff --git a/mupen64plus-core/src/device/rcp/mi/mi_controller.c b/mupen64plus-core/src/device/rcp/mi/mi_controller.c index 05ecdd7..02d35c9 100644 --- a/mupen64plus-core/src/device/rcp/mi/mi_controller.c +++ b/mupen64plus-core/src/device/rcp/mi/mi_controller.c @@ -105,7 +105,6 @@ void write_mi_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask update_mi_intr_mask(&mi->regs[MI_INTR_MASK_REG], value & mask); r4300_check_interrupt(mi->r4300, CP0_CAUSE_IP2, mi->regs[MI_INTR_REG] & mi->regs[MI_INTR_MASK_REG]); - cp0_update_count(mi->r4300); if (*cp0_cycle_count >= 0) gen_interrupt(mi->r4300); break; } diff --git a/mupen64plus-core/src/device/rcp/pi/pi_controller.c b/mupen64plus-core/src/device/rcp/pi/pi_controller.c index c78a840..29ab265 100644 --- a/mupen64plus-core/src/device/rcp/pi/pi_controller.c +++ b/mupen64plus-core/src/device/rcp/pi/pi_controller.c @@ -48,6 +48,54 @@ int validate_pi_request(struct pi_controller* pi) return 1; } +static uint32_t dma_pi_calculate_cycles(struct pi_controller* pi, uint32_t length) +{ + uint32_t cycles = 0; + uint8_t domain = 0; + uint32_t latency; + uint32_t pulse_width; + uint32_t release; + uint32_t page_size; + uint32_t pages; + if (pi->regs[PI_CART_ADDR_REG] >= 0x1FC04000 && pi->regs[PI_CART_ADDR_REG] < 0x80000000) + domain = 1; + else if (pi->regs[PI_CART_ADDR_REG] >= 0x10000000 && pi->regs[PI_CART_ADDR_REG] < 0x1FC00000) + domain = 1; + else if (pi->regs[PI_CART_ADDR_REG] >= 0x08000000 && pi->regs[PI_CART_ADDR_REG] < 0x10000000) + domain = 2; + else if (pi->regs[PI_CART_ADDR_REG] >= 0x06000000 && pi->regs[PI_CART_ADDR_REG] < 0x08000000) + domain = 1; + else if (pi->regs[PI_CART_ADDR_REG] >= 0x05000000 && pi->regs[PI_CART_ADDR_REG] < 0x06000000) + domain = 2; + else + { + DebugMessage(M64MSG_WARNING, "Unknown PI DMA domain: 0x%x", pi->regs[PI_CART_ADDR_REG]); + return length / 8; + } + + if (domain == 1) + { + latency = pi->regs[PI_BSD_DOM1_LAT_REG] + 1; + pulse_width = pi->regs[PI_BSD_DOM1_PWD_REG] + 1; + release = pi->regs[PI_BSD_DOM1_RLS_REG] + 1; + page_size = 2 ^ (pi->regs[PI_BSD_DOM1_PGS_REG] + 2); + } + else if (domain == 2) + { + latency = pi->regs[PI_BSD_DOM2_LAT_REG] + 1; + pulse_width = pi->regs[PI_BSD_DOM2_PWD_REG] + 1; + release = pi->regs[PI_BSD_DOM2_RLS_REG] + 1; + page_size = 2 ^ (pi->regs[PI_BSD_DOM2_PGS_REG] + 2); + } + pages = length / page_size; + + cycles += (14 + latency) * pages; + cycles += (pulse_width + release) * (length / 2); + cycles += 5 * pages; + cycles /= 2; + return cycles; +} + static void dma_pi_read(struct pi_controller* pi) { if (!validate_pi_request(pi)) @@ -73,7 +121,7 @@ static void dma_pi_read(struct pi_controller* pi) /* PI seems to treat the first 128 bytes differently, see https://n64brew.dev/wiki/Peripheral_Interface#Unaligned_DMA_transfer */ if (length >= 0x7f && (length & 1)) length += 1; - unsigned int cycles = handler->dma_read(opaque, dram, dram_addr, cart_addr, length); + handler->dma_read(opaque, dram, dram_addr, cart_addr, length); /* Mark DMA as busy */ pi->regs[PI_STATUS_REG] |= PI_STATUS_DMA_BUSY; @@ -82,7 +130,7 @@ static void dma_pi_read(struct pi_controller* pi) pi->regs[PI_CART_ADDR_REG] = (pi->regs[PI_CART_ADDR_REG] + length + 1) & ~1; /* schedule end of dma interrupt event */ - cp0_update_count(pi->mi->r4300); + uint32_t cycles = dma_pi_calculate_cycles(pi, length); add_interrupt_event(&pi->mi->r4300->cp0, PI_INT, cycles); } @@ -111,7 +159,7 @@ static void dma_pi_write(struct pi_controller* pi) length += 1; if (length <= 0x80) length -= dram_addr & 0x7; - unsigned int cycles = handler->dma_write(opaque, dram, dram_addr, cart_addr, length); + handler->dma_write(opaque, dram, dram_addr, cart_addr, length); post_framebuffer_write(&pi->dp->fb, dram_addr, length); @@ -122,7 +170,7 @@ static void dma_pi_write(struct pi_controller* pi) pi->regs[PI_CART_ADDR_REG] = (pi->regs[PI_CART_ADDR_REG] + length + 1) & ~1; /* schedule end of dma interrupt event */ - cp0_update_count(pi->mi->r4300); + uint32_t cycles = dma_pi_calculate_cycles(pi, length); add_interrupt_event(&pi->mi->r4300->cp0, PI_INT, cycles); } @@ -146,6 +194,12 @@ void init_pi(struct pi_controller* pi, void poweron_pi(struct pi_controller* pi) { memset(pi->regs, 0, PI_REGS_COUNT*sizeof(uint32_t)); + pi->regs[PI_BSD_DOM1_LAT_REG] = 0xFF; + pi->regs[PI_BSD_DOM1_PWD_REG] = 0xFF; + pi->regs[PI_BSD_DOM1_PGS_REG] = 0x03; + pi->regs[PI_BSD_DOM2_LAT_REG] = 0xFF; + pi->regs[PI_BSD_DOM2_PWD_REG] = 0xFF; + pi->regs[PI_BSD_DOM2_PGS_REG] = 0x03; } void read_pi_regs(void* opaque, uint32_t address, uint32_t* value) diff --git a/mupen64plus-core/src/device/rcp/pi/pi_controller.h b/mupen64plus-core/src/device/rcp/pi/pi_controller.h index 8f2dafd..00ff7aa 100644 --- a/mupen64plus-core/src/device/rcp/pi/pi_controller.h +++ b/mupen64plus-core/src/device/rcp/pi/pi_controller.h @@ -66,8 +66,8 @@ enum struct pi_dma_handler { - unsigned int (*dma_read)(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); - unsigned int (*dma_write)(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); + void (*dma_read)(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); + void (*dma_write)(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length); }; typedef void (*pi_dma_handler_getter)(struct cart* cart, struct dd_controller* dd, uint32_t address, void** opaque, const struct pi_dma_handler** handler); diff --git a/mupen64plus-core/src/device/rcp/rsp/rsp_core.c b/mupen64plus-core/src/device/rcp/rsp/rsp_core.c index 9b47e21..ab30bc4 100644 --- a/mupen64plus-core/src/device/rcp/rsp/rsp_core.c +++ b/mupen64plus-core/src/device/rcp/rsp/rsp_core.c @@ -80,8 +80,7 @@ static void do_sp_dma(struct rsp_core* sp, const struct sp_dma* dma) } /* schedule end of dma event */ - cp0_update_count(sp->mi->r4300); - add_interrupt_event(&sp->mi->r4300->cp0, RSP_DMA_EVT, (count * length) / 8); + add_interrupt_event(&sp->mi->r4300->cp0, RSP_DMA_EVT, ((count * length) / 16) + 4); } static void fifo_push(struct rsp_core* sp, uint32_t dir) @@ -312,6 +311,7 @@ void do_SP_Task(struct rsp_core* sp) uint32_t save_pc = sp->regs2[SP_PC_REG] & ~0xfff; uint32_t sp_delay_time; + uint32_t saved_status = sp->regs[SP_STATUS_REG]; if (sp->mem[0xfc0/4] == 1) { @@ -335,11 +335,10 @@ void do_SP_Task(struct rsp_core* sp) if (sp->dp->dpc_regs[DPC_STATUS_REG] & DPC_STATUS_FREEZE) { sp->dp->do_on_unfreeze |= DELAY_DP_INT; } else { - cp0_update_count(sp->mi->r4300); add_interrupt_event(&sp->mi->r4300->cp0, DP_INT, 4000); } } - sp_delay_time = 1000; + sp_delay_time = 4000; protect_framebuffers(&sp->dp->fb); } @@ -356,7 +355,7 @@ void do_SP_Task(struct rsp_core* sp) #endif sp->regs2[SP_PC_REG] |= save_pc; - sp_delay_time = 4000; + sp_delay_time = 8000; } else { @@ -367,7 +366,6 @@ void do_SP_Task(struct rsp_core* sp) sp_delay_time = 0; } - cp0_update_count(sp->mi->r4300); if (sp->mi->regs[MI_INTR_REG] & MI_INTR_SP) { add_interrupt_event(&sp->mi->r4300->cp0, SP_INT, sp_delay_time); @@ -388,16 +386,18 @@ void do_SP_Task(struct rsp_core* sp) add_interrupt_event(&sp->mi->r4300->cp0, RSP_TSK_EVT, sp_delay_time); sp->mi->r4300->cp0.interrupt_unsafe_state |= INTR_UNSAFE_RSP_TASK; } - - sp->rsp_status = sp->regs[SP_STATUS_REG] & (SP_STATUS_BROKE | SP_STATUS_HALT); - sp->regs[SP_STATUS_REG] &= ~(SP_STATUS_BROKE | SP_STATUS_HALT); + sp->rsp_status = sp->regs[SP_STATUS_REG]; + if (sp->regs[SP_STATUS_REG] & (SP_STATUS_HALT | SP_STATUS_BROKE)) + { + sp->regs[SP_STATUS_REG] = saved_status; + } } void rsp_interrupt_event(void* opaque) { struct rsp_core* sp = (struct rsp_core*)opaque; - sp->regs[SP_STATUS_REG] |= sp->rsp_status; + sp->regs[SP_STATUS_REG] = sp->rsp_status; sp->rsp_status = 0; sp->mi->r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_RSP; raise_rcp_interrupt(sp->mi, MI_INTR_SP); diff --git a/mupen64plus-core/src/device/rcp/si/si_controller.c b/mupen64plus-core/src/device/rcp/si/si_controller.c index 6c4fa33..35a144c 100644 --- a/mupen64plus-core/src/device/rcp/si/si_controller.c +++ b/mupen64plus-core/src/device/rcp/si/si_controller.c @@ -80,7 +80,6 @@ static void dma_si_write(struct si_controller* si) copy_pif_rdram(si); - cp0_update_count(si->mi->r4300); si->regs[SI_STATUS_REG] |= SI_STATUS_DMA_BUSY; add_interrupt_event(&si->mi->r4300->cp0, SI_INT, si->dma_duration + add_random_interrupt_time(si->mi->r4300)); } @@ -94,7 +93,6 @@ static void dma_si_read(struct si_controller* si) update_pif_ram(si->pif); - cp0_update_count(si->mi->r4300); si->regs[SI_STATUS_REG] |= SI_STATUS_DMA_BUSY; add_interrupt_event(&si->mi->r4300->cp0, SI_INT, si->dma_duration + add_random_interrupt_time(si->mi->r4300)); } @@ -174,14 +172,3 @@ void si_end_of_dma_event(void* opaque) si->regs[SI_STATUS_REG] |= SI_STATUS_INTERRUPT; raise_rcp_interrupt(si->mi, MI_INTR_SI); } - -void si_dynamic_dma_duration(struct si_controller* si) -{ - /* try to keep controller polling to 1 per VI */ - if (si->pif->update_counter > 1) - si->dma_duration += 1000; - else if (si->pif->update_counter < 1 && si->dma_duration > 0x900) - si->dma_duration -= 1000; - - si->pif->update_counter = 0; -} diff --git a/mupen64plus-core/src/device/rcp/si/si_controller.h b/mupen64plus-core/src/device/rcp/si/si_controller.h index e5e0756..01a371f 100644 --- a/mupen64plus-core/src/device/rcp/si/si_controller.h +++ b/mupen64plus-core/src/device/rcp/si/si_controller.h @@ -89,6 +89,4 @@ void write_si_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask void si_end_of_dma_event(void* opaque); -void si_dynamic_dma_duration(struct si_controller* si); - #endif diff --git a/mupen64plus-core/src/device/rcp/vi/vi_controller.c b/mupen64plus-core/src/device/rcp/vi/vi_controller.c index 0a2be0d..723e8d8 100644 --- a/mupen64plus-core/src/device/rcp/vi/vi_controller.c +++ b/mupen64plus-core/src/device/rcp/vi/vi_controller.c @@ -61,7 +61,6 @@ void set_vi_vertical_interrupt(struct vi_controller* vi) { if (!get_event(&vi->mi->r4300->cp0.q, VI_INT) && (vi->regs[VI_V_INTR_REG] < vi->regs[VI_V_SYNC_REG])) { - cp0_update_count(vi->mi->r4300); add_interrupt_event(&vi->mi->r4300->cp0, VI_INT, vi->delay); } } @@ -80,7 +79,7 @@ void poweron_vi(struct vi_controller* vi) { memset(vi->regs, 0, VI_REGS_COUNT*sizeof(uint32_t)); vi->field = 0; - vi->delay = 0; + vi->delay = vi->mi->r4300->clock_rate / vi->expected_refresh_rate; vi->count_per_scanline = 0; } @@ -94,7 +93,6 @@ void read_vi_regs(void* opaque, uint32_t address, uint32_t* value) { uint32_t* next_vi = get_event(&vi->mi->r4300->cp0.q, VI_INT); if (next_vi != NULL) { - cp0_update_count(vi->mi->r4300); vi->regs[VI_CURRENT_REG] = (vi->delay - (*next_vi - cp0_regs[CP0_COUNT_REG])) / vi->count_per_scanline; /* wrap around VI_CURRENT_REG if needed */ @@ -140,8 +138,7 @@ void write_vi_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask if ((vi->regs[VI_V_SYNC_REG] & mask) != (value & mask)) { masked_write(&vi->regs[VI_V_SYNC_REG], value, mask); - vi->count_per_scanline = (vi->clock / vi->expected_refresh_rate) / (vi->regs[VI_V_SYNC_REG] + 1); - vi->delay = (vi->regs[VI_V_SYNC_REG] + 1) * vi->count_per_scanline; + vi->count_per_scanline = (vi->mi->r4300->clock_rate / vi->expected_refresh_rate) / (vi->regs[VI_V_SYNC_REG] + 1); set_vi_vertical_interrupt(vi); } return; @@ -165,7 +162,6 @@ void vi_vertical_interrupt_event(void* opaque) /* allow main module to do things on VI event */ new_vi(); - si_dynamic_dma_duration(vi->si); /* toggle vi field if in interlaced mode */ vi->field ^= (vi->regs[VI_STATUS_REG] >> 6) & 0x1; diff --git a/mupen64plus-core/src/main/main.c b/mupen64plus-core/src/main/main.c index 98d617a..e30b518 100644 --- a/mupen64plus-core/src/main/main.c +++ b/mupen64plus-core/src/main/main.c @@ -347,8 +347,6 @@ int main_set_core_defaults(void) #endif ConfigSetDefaultBool(g_CoreConfig, "NoCompiledJump", 0, "Disable compiled jump commands in dynamic recompiler (should be set to False) "); ConfigSetDefaultBool(g_CoreConfig, "DisableExtraMem", 0, "Disable 4MB expansion RAM pack. May be necessary for some games"); - ConfigSetDefaultInt(g_CoreConfig, "CountPerOp", 0, "Force number of cycles per emulated instruction"); - ConfigSetDefaultInt(g_CoreConfig, "CountPerOpDenomPot", 0, "Reduce number of cycles per update by power of two when set greater than 0 (overclock)"); ConfigSetDefaultBool(g_CoreConfig, "AutoStateSlotIncrement", 0, "Increment the save state slot after each save operation"); ConfigSetDefaultInt(g_CoreConfig, "CurrentStateSlot", 0, "Save state slot (0-9) to use when saving/loading the emulator state"); ConfigSetDefaultBool(g_CoreConfig, "EnableDebugger", 0, "Activate the R4300 debugger when ROM execution begins, if core was built with Debugger support"); @@ -1474,8 +1472,6 @@ m64p_error main_run(void) { size_t i, k; size_t rdram_size; - uint32_t count_per_op; - uint32_t count_per_op_denom_pot; uint32_t emumode; uint32_t disable_extra_mem; int32_t si_dma_duration; @@ -1523,8 +1519,6 @@ m64p_error main_run(void) no_compiled_jump = ConfigGetParamBool(g_CoreConfig, "NoCompiledJump"); //We disable any randomness for netplay randomize_interrupt = !netplay_is_init() ? ConfigGetParamBool(g_CoreConfig, "RandomizeInterrupt") : 0; - count_per_op = ConfigGetParamInt(g_CoreConfig, "CountPerOp"); - count_per_op_denom_pot = ConfigGetParamInt(g_CoreConfig, "CountPerOpDenomPot"); if (ROM_SETTINGS.disableextramem) disable_extra_mem = ROM_SETTINGS.disableextramem; @@ -1534,18 +1528,14 @@ m64p_error main_run(void) rdram_size = (disable_extra_mem == 0) ? 0x800000 : 0x400000; - if (count_per_op <= 0) - count_per_op = ROM_SETTINGS.countperop; - - if (count_per_op_denom_pot > 11) - count_per_op_denom_pot = 11; - si_dma_duration = ConfigGetParamInt(g_CoreConfig, "SiDmaDuration"); if (si_dma_duration < 0) si_dma_duration = ROM_SETTINGS.sidmaduration; rsp_delay_time = ROM_SETTINGS.rspdelaytime; + uint32_t count_per_op; //UNUSED + uint32_t count_per_op_denom_pot; //UNUSED //During netplay, player 1 is the source of truth for these settings netplay_sync_settings(&count_per_op, &count_per_op_denom_pot, &disable_extra_mem, &si_dma_duration, &emumode, &no_compiled_jump, &rsp_delay_time); @@ -1789,8 +1779,6 @@ m64p_error main_run(void) init_device(&g_dev, g_mem_base, emumode, - count_per_op, - count_per_op_denom_pot, no_compiled_jump, randomize_interrupt, g_start_address, diff --git a/mupen64plus-core/src/main/rom.c b/mupen64plus-core/src/main/rom.c index 08c0c78..12eea5b 100644 --- a/mupen64plus-core/src/main/rom.c +++ b/mupen64plus-core/src/main/rom.c @@ -46,12 +46,10 @@ #define CHUNKSIZE 1024*128 /* Read files 128KB at a time. */ -/* Number of cpu cycles per instruction */ -enum { DEFAULT_COUNT_PER_OP = 2 }; /* by default, extra mem is enabled */ enum { DEFAULT_DISABLE_EXTRA_MEM = 0 }; /* Default SI DMA duration */ -enum { DEFAULT_SI_DMA_DURATION = 0x900 }; +enum { DEFAULT_SI_DMA_DURATION = 0x3000 }; /* Default AI DMA modifier */ enum { DEFAULT_AI_DMA_MODIFIER = 100 }; /* Default RSP delay time */ @@ -189,7 +187,6 @@ m64p_error open_rom(const unsigned char* romimage, unsigned int size) ROM_SETTINGS.transferpak = entry->transferpak; ROM_SETTINGS.mempak = entry->mempak; ROM_SETTINGS.biopak = entry->biopak; - ROM_SETTINGS.countperop = entry->countperop; ROM_SETTINGS.disableextramem = entry->disableextramem; ROM_SETTINGS.sidmaduration = entry->sidmaduration; ROM_SETTINGS.aidmamodifier = entry->aidmamodifier; @@ -208,7 +205,6 @@ m64p_error open_rom(const unsigned char* romimage, unsigned int size) ROM_SETTINGS.transferpak = 0; ROM_SETTINGS.mempak = 1; ROM_SETTINGS.biopak = 0; - ROM_SETTINGS.countperop = DEFAULT_COUNT_PER_OP; ROM_SETTINGS.disableextramem = DEFAULT_DISABLE_EXTRA_MEM; ROM_SETTINGS.sidmaduration = DEFAULT_SI_DMA_DURATION; ROM_SETTINGS.aidmamodifier = DEFAULT_AI_DMA_MODIFIER; @@ -338,12 +334,6 @@ static size_t romdatabase_resolve_round(void) entry->entry.set_flags |= ROMDATABASE_ENTRY_RUMBLE; } - if (!isset_bitmask(entry->entry.set_flags, ROMDATABASE_ENTRY_COUNTEROP) && - isset_bitmask(ref->set_flags, ROMDATABASE_ENTRY_COUNTEROP)) { - entry->entry.countperop = ref->countperop; - entry->entry.set_flags |= ROMDATABASE_ENTRY_COUNTEROP; - } - if (!isset_bitmask(entry->entry.set_flags, ROMDATABASE_ENTRY_CHEATS) && isset_bitmask(ref->set_flags, ROMDATABASE_ENTRY_CHEATS)) { if (ref->cheats) @@ -482,7 +472,6 @@ void romdatabase_open(void) search->entry.savetype = SAVETYPE_EEPROM_4K; search->entry.players = 4; search->entry.rumble = 1; - search->entry.countperop = DEFAULT_COUNT_PER_OP; search->entry.disableextramem = DEFAULT_DISABLE_EXTRA_MEM; search->entry.cheats = NULL; search->entry.transferpak = 0; @@ -598,15 +587,6 @@ void romdatabase_open(void) DebugMessage(M64MSG_WARNING, "ROM Database: Invalid rumble string on line %i", lineno); } } - else if(!strcmp(l.name, "CountPerOp")) - { - if (string_to_int(l.value, &value) && value > 0 && value <= 4) { - search->entry.countperop = value; - search->entry.set_flags |= ROMDATABASE_ENTRY_COUNTEROP; - } else { - DebugMessage(M64MSG_WARNING, "ROM Database: Invalid CountPerOp on line %i", lineno); - } - } else if (!strcmp(l.name, "DisableExtraMem")) { search->entry.disableextramem = atoi(l.value); @@ -680,7 +660,7 @@ void romdatabase_open(void) } else if(!strcmp(l.name, "SiDmaDuration")) { - if (string_to_int(l.value, &value) && value >= 0 && value <= 0x10000) { + if (string_to_int(l.value, &value) && value >= 0 && value <= 0x30000) { search->entry.sidmaduration = value; search->entry.set_flags |= ROMDATABASE_ENTRY_SIDMADURATION; } else { diff --git a/mupen64plus-core/src/main/rom.h b/mupen64plus-core/src/main/rom.h index 522a4f0..0470f39 100644 --- a/mupen64plus-core/src/main/rom.h +++ b/mupen64plus-core/src/main/rom.h @@ -107,7 +107,6 @@ typedef struct unsigned char savetype; unsigned char players; /* Local players 0-4, 2/3/4 way Netplay indicated by 5/6/7. */ unsigned char rumble; /* 0 - No, 1 - Yes boolean for rumble support. */ - unsigned char countperop; unsigned char disableextramem; unsigned char transferpak; /* 0 - No, 1 - Yes boolean for transferpak support. */ unsigned char mempak; /* 0 - No, 1 - Yes boolean for mempak support. */ @@ -125,7 +124,6 @@ typedef struct #define ROMDATABASE_ENTRY_SAVETYPE BIT(3) #define ROMDATABASE_ENTRY_PLAYERS BIT(4) #define ROMDATABASE_ENTRY_RUMBLE BIT(5) -#define ROMDATABASE_ENTRY_COUNTEROP BIT(6) #define ROMDATABASE_ENTRY_CHEATS BIT(7) #define ROMDATABASE_ENTRY_EXTRAMEM BIT(8) #define ROMDATABASE_ENTRY_TRANSFERPAK BIT(9)