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)