From 1e19b648fb6b5bcecfe99b6c17d7c3c987945f0a Mon Sep 17 00:00:00 2001 From: Mateusz Faderewski Date: Sun, 12 Mar 2023 00:23:43 +0100 Subject: [PATCH] [SC64][FW][SW] New loader application rewritten in Rust language (#34) (#36) --- .gitattributes | 1 + .github/workflows/build.yml | 103 +- assets/sc64_logo_256_256.png | Bin 54087 -> 0 bytes build.sh | 35 +- docs/00_quick_startup_guide.md | 74 +- docs/06_manufacturing_guidelines.md | 30 +- sw/bootloader/src/exception.c | 27 +- sw/bootloader/src/menu.c | 22 +- sw/controller/src/cfg.c | 6 +- sw/controller/src/cfg.h | 2 +- sw/controller/src/flash.c | 17 +- sw/controller/src/flash.h | 2 +- sw/controller/src/update.c | 18 + sw/controller/src/update.h | 1 + sw/controller/src/usb.c | 93 +- sw/controller/src/version.c | 10 +- sw/controller/src/version.h | 2 +- sw/deployer/.gitignore | 9 + sw/deployer/Cargo.lock | 1335 ++ sw/deployer/Cargo.toml | 27 + sw/deployer/data/mupen64plus.ini | 18178 ++++++++++++++++++++++++++ sw/deployer/src/debug.rs | 396 + sw/deployer/src/disk.rs | 306 + sw/deployer/src/main.rs | 841 ++ sw/deployer/src/n64.rs | 88 + sw/deployer/src/sc64/cic.rs | 220 + sw/deployer/src/sc64/error.rs | 34 + sw/deployer/src/sc64/firmware.rs | 149 + sw/deployer/src/sc64/link.rs | 505 + sw/deployer/src/sc64/mod.rs | 788 ++ sw/deployer/src/sc64/types.rs | 856 ++ sw/deployer/src/sc64/utils.rs | 39 + sw/pc/.gitignore | 11 - sw/pc/sc64.py | 1422 -- sw/{pc => tools}/primer.py | 1229 +- sw/{pc => tools}/requirements.txt | 1 - sw/{update => tools}/update.py | 23 +- sw/update/.gitignore | 1 - 38 files changed, 24738 insertions(+), 2163 deletions(-) delete mode 100644 assets/sc64_logo_256_256.png create mode 100644 sw/deployer/.gitignore create mode 100644 sw/deployer/Cargo.lock create mode 100644 sw/deployer/Cargo.toml create mode 100644 sw/deployer/data/mupen64plus.ini create mode 100644 sw/deployer/src/debug.rs create mode 100644 sw/deployer/src/disk.rs create mode 100644 sw/deployer/src/main.rs create mode 100644 sw/deployer/src/n64.rs create mode 100644 sw/deployer/src/sc64/cic.rs create mode 100644 sw/deployer/src/sc64/error.rs create mode 100644 sw/deployer/src/sc64/firmware.rs create mode 100644 sw/deployer/src/sc64/link.rs create mode 100644 sw/deployer/src/sc64/mod.rs create mode 100644 sw/deployer/src/sc64/types.rs create mode 100644 sw/deployer/src/sc64/utils.rs delete mode 100644 sw/pc/.gitignore delete mode 100755 sw/pc/sc64.py rename sw/{pc => tools}/primer.py (73%) rename sw/{pc => tools}/requirements.txt (50%) rename sw/{update => tools}/update.py (95%) mode change 100755 => 100644 delete mode 100644 sw/update/.gitignore diff --git a/.gitattributes b/.gitattributes index 89d0169..7613e20 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,3 +5,4 @@ hw/pcb/*.html linguist-generated sw/bootloader/src/fatfs/* linguist-vendored sw/bootloader/src/fatfs/diskio.c -linguist-vendored sw/controller/inc/* linguist-vendored +sw/deployer/data/* linguist-vendored diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 83bf2bc..a36b892 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,65 +13,65 @@ on: workflow_dispatch: jobs: - build-fw-hw-sw: + build-firmware: runs-on: ubuntu-latest steps: - name: Download SummerCart64 repository uses: actions/checkout@v3 - - name: Set SC64 version + - name: Set package version uses: frabert/replace-string-action@v2 - id: sc64version + id: version with: pattern: '\/' - string: '-${{ github.ref_name }}' + string: '${{ github.ref_name }}' replace-with: '-' - - name: Build everything + - name: Build firmware run: ./docker_build.sh release --force-clean env: - SC64_VERSION: ${{ steps.sc64version.outputs.replaced }} + SC64_VERSION: ${{ steps.version.outputs.replaced }} - name: Upload artifact uses: actions/upload-artifact@v3 with: - name: sc64-pkg${{ steps.sc64version.outputs.replaced }} + name: sc64-pkg-${{ steps.version.outputs.replaced }} path: | - sc64-extra${{ steps.sc64version.outputs.replaced }}.zip - sc64-firmware${{ steps.sc64version.outputs.replaced }}.bin + sc64-extra-${{ steps.version.outputs.replaced }}.zip + sc64-firmware-${{ steps.version.outputs.replaced }}.bin - name: Upload release assets if: github.event_name == 'release' && github.event.action == 'created' uses: softprops/action-gh-release@v0.1.15 with: files: | - sc64-extra${{ steps.sc64version.outputs.replaced }}.zip - sc64-firmware${{ steps.sc64version.outputs.replaced }}.bin + sc64-extra-${{ steps.version.outputs.replaced }}.zip + sc64-firmware-${{ steps.version.outputs.replaced }}.bin - build-sc64-py: + build-deployer: strategy: matrix: os: [windows-latest, ubuntu-latest, macos-latest] include: - os: windows-latest - pyinstaller-build-options: --target-arch=64bit - pyinstaller-options: --onefile --console --icon ../../assets/sc64_logo_256_256.png - package-name: sc64-windows - package-options: -c -a -f - package-extension: zip + executable: sc64deployer.exe + name: sc64-deployer-windows + options: -c -a -f + extension: zip - os: ubuntu-latest - pyinstaller-options: --onefile - package-name: sc64-linux - package-options: -czf - package-extension: tar.gz + linux-packages: libudev-dev + executable: sc64deployer + name: sc64-deployer-linux + options: -czf + extension: tar.gz - os: macos-latest - pyinstaller-options: --onedir --console --icon ../../assets/sc64_logo_256_256.png - package-name: sc64-macos - package-options: -czf - package-extension: tgz + executable: sc64deployer + name: sc64-deployer-macos + options: -czf + extension: tgz runs-on: ${{ matrix.os }} @@ -79,61 +79,40 @@ jobs: - name: Download SummerCart64 repository uses: actions/checkout@v3 - - name: Set SC64 version + - name: Set package version uses: frabert/replace-string-action@v2 - id: sc64version + id: version with: pattern: '\/' - string: '-${{ github.ref_name }}' + string: '${{ github.ref_name }}' replace-with: '-' - - name: Setup python - uses: actions/setup-python@v4 - with: - python-version: '3.11' - - - name: Download pyinstaller repository - uses: actions/checkout@v3 - with: - repository: 'pyinstaller/pyinstaller' - ref: 'v5.8.0' - path: pyinstaller - - - name: Compile and install pyinstaller + - name: Install linux packages + if: matrix.linux-packages run: | - pip3 uninstall pyinstaller - pip3 install wheel - pushd bootloader - python3 ./waf all ${{ matrix.pyinstaller-build-options }} - popd - pip3 install . - working-directory: pyinstaller + sudo apt-get update + sudo apt-get -y install ${{ matrix.linux-packages }} - - name: Install sc64.py requirements - run: pip3 install -r requirements.txt - working-directory: sw/pc - - - name: Create sc64.py executable - run: python3 -m PyInstaller --clean ${{ matrix.pyinstaller-options }} sc64.py - working-directory: sw/pc + - name: Build deployer + run: cargo b -r + working-directory: sw/deployer - name: Package executable run: | mkdir package - pushd dist - tar ${{ matrix.package-options }} ../package/${{ matrix.package-name }}${{ steps.sc64version.outputs.replaced }}.${{ matrix.package-extension }} * - popd - working-directory: sw/pc + cd target/release + tar ${{ matrix.options }} ../../package/${{ matrix.name }}-${{ steps.version.outputs.replaced }}.${{ matrix.extension }} ${{ matrix.executable }} + working-directory: sw/deployer - name: Upload artifact uses: actions/upload-artifact@v3 with: - name: ${{ matrix.package-name }}${{ steps.sc64version.outputs.replaced }} - path: sw/pc/package/${{ matrix.package-name }}${{ steps.sc64version.outputs.replaced }}.${{ matrix.package-extension }} + name: ${{ matrix.name }}-${{ steps.version.outputs.replaced }} + path: sw/deployer/package/${{ matrix.name }}-${{ steps.version.outputs.replaced }}.${{ matrix.extension }} - name: Upload release assets if: github.event_name == 'release' && github.event.action == 'created' uses: softprops/action-gh-release@v0.1.15 with: files: | - sw/pc/package/${{ matrix.package-name }}${{ steps.sc64version.outputs.replaced }}.${{ matrix.package-extension }} + sw/deployer/package/${{ matrix.name }}-${{ steps.version.outputs.replaced }}.${{ matrix.extension }} diff --git a/assets/sc64_logo_256_256.png b/assets/sc64_logo_256_256.png deleted file mode 100644 index 670d1dfdf5e7060e90880c70b0a0b122313866e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54087 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⩔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 z z#HH0l{nt@Zyg?tiQL^igH`VO_F0QkYbL5^PiVO$jKO@6Ss{p$mMYP(k2dJJS#>G13 zDr6yxK!XJkYTr&QLLR>+Hnc6Ju;5 z{Y~0NMT3~QcMCKyU{Whg^XlbsXH;-wxuJgybBuAhjN7COSs~Xs#fKuMYUr(DN1C>K zo(r%wH}+I`WpYB#zBr$14v8%>dk9clY8>%`p1q78YoLA-S~eNfT63yG0%{d(83)e< zKD__SRW*w&=^g`Ztq<}*D%JtI3G{!1O^^>xP($+M}ubUl7^ z^5i&!L)TG~uauv=r-b?gsm5K#${wl3un1Tu5T~?P_cQ^z5H~vlyX;bfVRnHt6wuH0 zZv2f{4hrdEdQ8*iFt?3i*Rv+szb?7QMGnhT(xPf$?E4uD79ajgVi zybd33XNj{j8h%fF6Sk6Q{K_&@gqd48A)^EOyKwa&MmHExIru!rGH^m#xQsz_7t2?Mnj${fzPTl~k8$0ysp$FY1vOlLJp^tE#EI41tF^@uzQrW;bB!JlK^4tLB(w-P@7q}<% zJRIG8Z4C!Ra->omeX-p4t zbu!f^cFMVCFtZdKf`DqJ@t?qLo0OSZWa^${a9#IWrP4-*bis)an(k-XQ$)HMQ9F0R z?QL0dV()3+ln?(^?O2!EuENeTqgWv?HssUYW6nqWEr5^F#N=*SIiSUC_*7dK2j>-c za(P%r@X%{O7(9Sc+8kN3lleeQ+3MX+N02tvs1qp9TAGcKUPr|k37Jq?b&$8#v9;YI zIaxP`z|z(cOtCkK-X(<*6Jr|olz)st5IOQ<#N$QDpqMg(>;f`#ce#$u85g;wrG zEt~)P&55w%GY3z0rpyMiG@`YvR(f*}UdW2WBy8ZUjn-5DgIyFv00pi%NfxI1pUq>e#IcU}A>bO`Z28W=mQ-5I_hzu9%BkmbD#uj@JF5W}epgFGW0CQj5gr*M}i$?b(5k!6=g7YVY!tNFymL*HD2I=lgxt&i?W9gh W-sLH5;qL /dev/null + pushd sw/tools > /dev/null if [ "$FORCE_CLEAN" = true ]; then - rm -f ./sc64-firmware.bin + rm -f ../../sc64-firmware-*.bin fi GIT_INFO="" - if [ ! -z "${GIT_BRANCH}" ]; then GIT_INFO+="branch: [$GIT_BRANCH] "; fi - if [ ! -z "${GIT_TAG}" ]; then GIT_INFO+="tag: [$GIT_TAG] "; fi - if [ ! -z "${GIT_SHA}" ]; then GIT_INFO+="sha: [$GIT_SHA] "; fi - if [ ! -z "${GIT_MESSAGE}" ]; then GIT_INFO+="message: [$GIT_MESSAGE] "; fi - GIT_INFO=$(echo "$GIT_INFO" | xargs) + if [ ! -z "${SC64_VERSION}" ]; then GIT_INFO+=$'\n'"ver: $SC64_VERSION"; fi + if [ ! -z "${GIT_BRANCH}" ]; then GIT_INFO+=$'\n'"branch: $GIT_BRANCH"; fi + if [ ! -z "${GIT_TAG}" ]; then GIT_INFO+=$'\n'"tag: $GIT_TAG"; fi + if [ ! -z "${GIT_SHA}" ]; then GIT_INFO+=$'\n'"sha: $GIT_SHA"; fi + if [ ! -z "${GIT_MESSAGE}" ]; then GIT_INFO+=$'\n'"msg: $GIT_MESSAGE"; fi python3 update.py \ --git "$GIT_INFO" \ --mcu ../controller/build/app/app.bin \ --fpga ../../fw/project/lcmxo2/impl1/sc64_impl1.jed \ --boot ../bootloader/build/bootloader.bin \ --primer ../controller/build/primer/primer.bin \ - sc64-firmware.bin + ../../sc64-firmware-${SC64_VERSION}.bin popd > /dev/null BUILT_UPDATE=true @@ -111,15 +112,13 @@ build_release () { build_update - if [ -e "./${PACKAGE_FILE_NAME}.zip" ]; then - rm -f "./${PACKAGE_FILE_NAME}.zip" + if [ -e "./${PACKAGE_FILE_NAME}-${SC64_VERSION}.zip" ]; then + rm -f ./${PACKAGE_FILE_NAME}-${SC64_VERSION}.zip fi - PACKAGE="./${PACKAGE_FILE_NAME}${SC64_VERSION}.zip" + PACKAGE="./${PACKAGE_FILE_NAME}-${SC64_VERSION}.zip" zip -j -r $PACKAGE ${TOP_FILES[@]} zip -r $PACKAGE ${FILES[@]} - cp sw/update/sc64-firmware.bin ./sc64-firmware${SC64_VERSION}.bin - BUILT_RELEASE=true } diff --git a/docs/00_quick_startup_guide.md b/docs/00_quick_startup_guide.md index 98bd3da..6190405 100644 --- a/docs/00_quick_startup_guide.md +++ b/docs/00_quick_startup_guide.md @@ -1,7 +1,6 @@ - [First time setup](#first-time-setup) - [Firmware backup/update](#firmware-backupupdate) -- [Internal flashcart state](#internal-flashcart-state) -- [Uploading game/save](#uploading-gamesave) +- [Uploading game and/or save](#uploading-game-andor-save) - [Downloading save](#downloading-save) - [Running 64DD games](#running-64dd-games) - [Direct boot option](#direct-boot-option) @@ -12,81 +11,96 @@ ## First time setup -**Windows platform: replace `./sc64` in examples below with `sc64.exe`** +**Windows platform: replace `./sc64deployer` in examples below with `sc64deployer.exe`** -1. Download the latest `sc64-{os}-{version}.{ext}` (choose OS matching your system) and `sc64-firmware-{version}.bin` from GitHub releases page -2. Extract `sc64-{os}-{version}.{ext}` package contents to a folder and place `sc64-firmware-{version}.bin` inside it -3. Update SC64 firmware to the latest version with `./sc64 --update-firmware sc64-firmware-{version}.bin` -4. Run `./sc64 --print-state` to check if update process finished successfully and SC64 is detected correctly +1. Download the latest deployer tool (`sc64-deployer-{os}-{version}.{ext}`) and firmware (`sc64-firmware-{version}.bin`) from GitHub releases page +2. Extract deployer tool package contents to a folder and place firmware file inside it +3. Connect SC64 device to your computer with USB type C cable +4. Run `./sc64deployer list` to check if device is detected in the system +5. Update SC64 firmware to the latest version with `./sc64deployer firmware update sc64-firmware-{version}.bin` +6. Run `./sc64deployer info` to check if update process finished successfully and SC64 is detected correctly --- ## Firmware backup/update -Keeping SC64 firmware up to date is highly recommended. `sc64` executable is tightly coupled with specific firmware versions and will error out when it detects unsupported firmware version. +Keeping SC64 firmware up to date is highly recommended. +`sc64deployer` application is tightly coupled with specific firmware versions and will error out when it detects unsupported firmware version. -To download and backup current version of SC64 firmware run `./sc64 --backup-firmware sc64-firmware-backup.bin` +To download and backup current version of the SC64 firmware run `./sc64deployer firmware backup sc64-firmware-backup.bin` -To update SC64 firmware run `./sc64 --update-firmware sc64-firmware-{version}.bin` +To update SC64 firmware run `./sc64deployer firmware update sc64-firmware-{version}.bin` + +To print firmware metadata run `./sc64deployer firmware info sc64-firmware-{version}.bin` --- -## Internal flashcart state +## Uploading game and/or save -SC64 holds some internal configuration options after `sc64` executable finished running. To reset it simply run: `./sc64 --reset-state`. Internal flashcart state can be checked by running: `./sc64 --print-state` +`./sc64deployer upload path_to_rom.n64 --save-type eeprom4k --save path_to_save.sav` ---- - -## Uploading game/save - -`./sc64 --boot rom path_to_rom.n64 --save-type eeprom-4k --save path_to_save.sav` - -Replace `path_to_rom.n64` / `eeprom-4k` / `path_to_save.sav` with appropriate values for desired game. Script will try to autodetect used save type so explicitly setting save type usually isn't needed. Check included help in program to list available save types. -Arguments `--save-type` and/or `--save` can be omitted if game doesn't require any save or you want to start fresh. +Replace `path_to_rom.n64` / `eeprom4k` / `path_to_save.sav` with appropriate values for desired game. +Application will try to autodetect used save type so explicitly setting save type usually isn't needed. +Check included help in the application to list available save types. +Arguments `--save-type` and/or `--save` can be omitted if game doesn't require any save or you want to start with fresh save file. --- ## Downloading save -`./sc64 --backup-save path_to_save.sav` +`./sc64deployer download save path_to_save.sav` -Replace `path_to_save.sav` with appropriate value. Specifying save type isn't required when set correctly previously. +Replace `path_to_save.sav` with appropriate value. +Command will raise error when no save type is currently enabled in the SC64 device. --- ## Running 64DD games -64DD games require DDIPL ROM and disk images. To run disk game type `./sc64 --boot ddipl --ddipl path_to_ddipl.n64 --disk path_to_disk_1.ndd --disk path_to_disk_2.ndd`. +64DD games require DDIPL ROM and disk images. +To run disk game type `./sc64deployer 64dd path_to_ddipl.n64 path_to_disk_1.ndd path_to_disk_2.ndd`. -Replace `path_to_ddipl.n64` / `path_to_disk_x.ndd` with appropriate values. Argument `--disk` can be specified multiple times. Only `.ndd` disk format is supported currently. To change inserted disk press button on the back of SC64 flashcart. Make sure retail and development disks aren't mixed together. 64DD IPL can handle only one drive type at a time. +Replace `path_to_ddipl.n64` / `path_to_disk_x.ndd` with appropriate values. +Multiple disk files can be passed to the command. +Only `.ndd` disk format is supported. +To change inserted disk press button on the back of SC64 device. +Make sure retail and development disks formats aren't mixed together. +64DD IPL can handle only one drive type at a time. + +If disk game supports running in conjunction with cartridge game then `--rom path_to_rom.n64` argument can be added to command above. +N64 will boot cartridge game instead of 64DD IPL. --- ## Direct boot option If booting game through included bootloader isn't a desired option then flashcart can be put in special mode that omits this step. -Run `./sc64 --boot direct-rom path_to_rom.n64` to disable bootloader during boot and console reset. This option is useful only for very specific cases (e.g. testing custom IPL3 or running SC64 on top of GameShark). +Pass `--direct` option in `upload` or `64dd` command to disable bootloader during boot and console reset. +This option is useful only for very specific cases (e.g. testing custom IPL3 or running SC64 on top of GameShark). +TV type cannot be forced when direct boot mode is enabled. --- ## Debug terminal -`sc64` executable supports UNFLoader protocol and has same functionality implemented as aforementioned program. Use argument `--debug` to activate it. +`sc64deployer` application supports UNFLoader protocol and has same functionality implemented as aforementioned program. +Type `./sc64deployer debug` to activate it. --- ## LED blink patters -LED on SC64 board can blink in certain situations. Most of them during normal use are related to SD card access. Here's list of blink patters meaning: +LED on SC64 board can blink in certain situations. Most of them during normal use are related to SD card access. Here's list of blink patterns: | Pattern | Meaning | | ------------------------------------ | ------------------------------------------------------------------------------------------------------------ | -| Nx [Short ON - Short OFF] | SD card is being accessed (initialization or data read/write) or save writeback is in progress | -| Nx [Medium ON - Long OFF] | CIC region didn't match, please power off console and power on again | +| Nx [Short ON - Short OFF] | SD card access is in progress (initialization or data read/write) or save writeback is in progress | +| Nx [Medium ON - Long OFF] | CIC region did not match, please power off console and power on again | | 2x [Very short ON - Short OFF] | Pattern used during firmware update process, it means that specific part of firmware has started programming | | 10x [Very short ON - Very short OFF] | Firmware has been successfully updated | | 30x [Long ON - Long OFF] | There was serious problem during firmware update, device is most likely bricked | Nx means that blink count is varied. -LED blinking on SD card access can be disabled through `sc64` executable. Please refer to included help for option to change the LED behavior. +LED blinking on SD card access can be disabled through `sc64deployer` application. +Please refer to included help for option to change the LED behavior. diff --git a/docs/06_manufacturing_guidelines.md b/docs/06_manufacturing_guidelines.md index b287ee6..d5058ff 100644 --- a/docs/06_manufacturing_guidelines.md +++ b/docs/06_manufacturing_guidelines.md @@ -11,7 +11,8 @@ ## Step by step guide how to make SC64 -All necessary manufacturing files are packaged in every `sc64-extra-{version}.zip` file in GitHub releases. Please download latest release before proceeding with the instructions. +All necessary manufacturing files are packaged in every `sc64-extra-{version}.zip` file in GitHub releases. +Please download latest release before proceeding with the instructions. --- @@ -45,13 +46,16 @@ All necessary manufacturing files are packaged in every `sc64-extra-{version}.zi 1. Locate `.stl` files inside `hw/shell` folder 2. Use these files in the slicer and 3D printer of your choice or order ready made prints from 3D printing company - 3. Find matching screws, dimensions are the same as on retail N64 cartridges + 3. Find matching screws, go to discussions tab for community recommendations --- ### **Putting it together** -There are no special requirements for soldering components to board. All chips and connectors can be soldered with standard manual soldering iron, although hot air station is recommended. Interactive BOM has every component and its value highlighted on PCB drawings and it's strongly recommended to use during assembly process. You can skip this step if PCB assembly service was used in previous steps. +There are no special requirements for soldering components to board. +All chips and connectors can be soldered with standard manual soldering iron, although hot air station is recommended. +Interactive BOM has every component and its value highlighted on PCB drawings and it's strongly recommended to use during assembly process. +You can skip this step if PCB assembly service was used in previous steps. --- @@ -59,17 +63,18 @@ There are no special requirements for soldering components to board. All chips a **Please read the following instructions carefully before proceeding with programming.** -For initial programming you are going to need a PC and a USB to UART (serial) adapter (3.3V signaling is required). These steps assume you are using modern Windows OS (version 10 or higher). +For initial programming you are going to need a PC and a USB to UART (serial) adapter (3.3V signaling is required). +These steps assume you are using modern Windows OS (version 10 or higher). As for software here's list of required applications: - [FT_PROG](https://ftdichip.com/utilities/#ft_prog) - FTDI FT232H EEPROM programming software - - [Python 3](https://www.python.org/downloads/) with `pip3` - necessary for initial programming script, `primer.py` + - [Python 3](https://www.python.org/downloads/) with `pip3` - necessary for initial programming script: `primer.py` Programming must be done in specific order for `primer.py` script to work correctly. First, program FT232H EEPROM: 1. Connect SC64 board to the PC with USB-C cable - 2. Locate FT232H EEPROM template in `fw/ftdi` folder + 2. Locate FT232H EEPROM template `ft232h_config.xml` 3. Launch `FT_PROG` software 4. Click on `Scan and parse` if no device has shown up 5. Right click on SC64 device and choose `Apply Template -> From File` @@ -78,18 +83,18 @@ First, program FT232H EEPROM: Your SC64 should be ready for next programming step. -Second, program FPGA, microcontroller and Flash memory: +Second, program FPGA, microcontroller and bootloader: 1. Disconnect SC64 board from power (unplug USB-C cable) 2. Connect serial adapter to `TX/RX/GND` pads marked on the PCB 3. Connect serial adapter to the PC 4. Check in device manager which port number `COMx` is assigned to serial adapter 5. Connect SC64 board to the PC with USB-C cable (***IMPORTANT:*** connect it to the same computer as serial adapter) 6. Locate `primer.py` script in root folder - 7. Make sure these files are located in the same folder as `primer.py` script: `requirements.txt`, `sc64.py`, `sc64-firmware.bin` + 7. Make sure these files are located in the same folder as `primer.py` script: `requirements.txt`, `sc64-firmware-{version}.bin` 8. Run `pip3 install -r requirements.txt` to install required python packages - 9. Run `python3 primer.py COMx sc64-firmware.bin` (replace `COMx` with port located in step **4**) + 9. Run `python3 primer.py COMx sc64-firmware-{version}.bin` (replace `COMx` with port located in step **4**) 10. Follow the instructions on the screen - 11. Wait until programming process has finished (**DO NOT STOP PROGRAMMING PROCESS OR DISCONNECT SC64 BOARD FROM PC**, doing so might irrecoverably break programming through UART header and you would need to program microcontroller, FPGA and bootloader with separate dedicated programming interfaces through *Tag-Connect* connector on the PCB) + 11. Wait until programming process has finished (**DO NOT STOP PROGRAMMING PROCESS OR DISCONNECT SC64 BOARD FROM PC**, doing so might irrecoverably break programming through UART header and you would need to program FPGA and/or microcontroller with separate dedicated programming interfaces through *Tag-Connect* connector on the PCB) Congratulations! Your SC64 flashcart should be ready for use! @@ -99,4 +104,7 @@ Congratulations! Your SC64 flashcart should be ready for use! *`primer.py` threw error on `Bootloader -> SC64 FLASH` step* -This issue can be attributed to incorrectly programmed FT232H EEPROM in the first programming step. Check again in `FT_PROG` program if device was configured properly. Once FPGA and microcontroller has been programmed successfully `primer.py` script needs to be run in special mode. Please use command `python3 primer.py COMx sc64-firmware.bin --only-bootloader` to try programming bootloader again. +This issue can be attributed to incorrectly programmed FT232H EEPROM in the first programming step. +Check again in `FT_PROG` application if device was configured properly. +Once FPGA and microcontroller has been programmed successfully `primer.py` script needs to be run in special mode. +Please use command `python3 primer.py COMx sc64-firmware-{version}.bin --bootloader-only` to try programming bootloader again. diff --git a/sw/bootloader/src/exception.c b/sw/bootloader/src/exception.c index 9c967ee..f8bc750 100644 --- a/sw/bootloader/src/exception.c +++ b/sw/bootloader/src/exception.c @@ -47,20 +47,25 @@ void exception_fatal_handler (uint32_t exception_code, uint32_t interrupt_mask, display_init((uint32_t *) (&assets_sc64_logo_640_240_dimmed)); + display_printf("[ SC64 bootloader metadata ]\n"); display_printf("branch: %s | tag: %s\n", version->git_branch, version->git_tag); display_printf("sha: %s\n", version->git_sha); - display_printf("%s\n\n", version->git_message); + display_printf("msg: %s\n\n", version->git_message); - display_printf("%s\n", exception_get_description(exception_code)); - display_printf(" pc: 0x%08lX sr: 0x%08lX cr: 0x%08lX va: 0x%08lX\n", e->epc.u32, e->sr, e->cr, e->badvaddr.u32); - display_printf(" zr: 0x%08lX at: 0x%08lX v0: 0x%08lX v1: 0x%08lX\n", e->zr.u32, e->at.u32, e->v0.u32, e->v1.u32); - display_printf(" a0: 0x%08lX a1: 0x%08lX a2: 0x%08lX a3: 0x%08lX\n", e->a0.u32, e->a1.u32, e->a2.u32, e->a3.u32); - display_printf(" t0: 0x%08lX t1: 0x%08lX t2: 0x%08lX t3: 0x%08lX\n", e->t0.u32, e->t1.u32, e->t2.u32, e->t3.u32); - display_printf(" t4: 0x%08lX t5: 0x%08lX t6: 0x%08lX t7: 0x%08lX\n", e->t4.u32, e->t5.u32, e->t6.u32, e->t7.u32); - display_printf(" s0: 0x%08lX s1: 0x%08lX s2: 0x%08lX s3: 0x%08lX\n", e->s0.u32, e->s1.u32, e->s2.u32, e->s3.u32); - display_printf(" s4: 0x%08lX s5: 0x%08lX s6: 0x%08lX s7: 0x%08lX\n", e->s4.u32, e->s5.u32, e->s6.u32, e->s7.u32); - display_printf(" t8: 0x%08lX t9: 0x%08lX k0: 0x%08lX k1: 0x%08lX\n", e->t8.u32, e->t9.u32, e->k0.u32, e->k1.u32); - display_printf(" gp: 0x%08lX sp: 0x%08lX s8: 0x%08lX ra: 0x%08lX\n\n", e->gp.u32, e->sp.u32, e->s8.u32, e->ra.u32); + if (exception_code != EXCEPTION_SYSCALL) { + display_printf("%s\n", exception_get_description(exception_code)); + display_printf(" pc: 0x%08lX sr: 0x%08lX cr: 0x%08lX va: 0x%08lX\n", e->epc.u32, e->sr, e->cr, e->badvaddr.u32); + display_printf(" zr: 0x%08lX at: 0x%08lX v0: 0x%08lX v1: 0x%08lX\n", e->zr.u32, e->at.u32, e->v0.u32, e->v1.u32); + display_printf(" a0: 0x%08lX a1: 0x%08lX a2: 0x%08lX a3: 0x%08lX\n", e->a0.u32, e->a1.u32, e->a2.u32, e->a3.u32); + display_printf(" t0: 0x%08lX t1: 0x%08lX t2: 0x%08lX t3: 0x%08lX\n", e->t0.u32, e->t1.u32, e->t2.u32, e->t3.u32); + display_printf(" t4: 0x%08lX t5: 0x%08lX t6: 0x%08lX t7: 0x%08lX\n", e->t4.u32, e->t5.u32, e->t6.u32, e->t7.u32); + display_printf(" s0: 0x%08lX s1: 0x%08lX s2: 0x%08lX s3: 0x%08lX\n", e->s0.u32, e->s1.u32, e->s2.u32, e->s3.u32); + display_printf(" s4: 0x%08lX s5: 0x%08lX s6: 0x%08lX s7: 0x%08lX\n", e->s4.u32, e->s5.u32, e->s6.u32, e->s7.u32); + display_printf(" t8: 0x%08lX t9: 0x%08lX k0: 0x%08lX k1: 0x%08lX\n", e->t8.u32, e->t9.u32, e->k0.u32, e->k1.u32); + display_printf(" gp: 0x%08lX sp: 0x%08lX s8: 0x%08lX ra: 0x%08lX\n\n", e->gp.u32, e->sp.u32, e->s8.u32, e->ra.u32); + } else { + display_printf("[ Runtime error ]\n"); + } if (exception_code == EXCEPTION_INTERRUPT) { if (interrupt_mask & INTERRUPT_MASK_TIMER) { diff --git a/sw/bootloader/src/menu.c b/sw/bootloader/src/menu.c index de75ea9..ebad210 100644 --- a/sw/bootloader/src/menu.c +++ b/sw/bootloader/src/menu.c @@ -41,7 +41,7 @@ static const char *fatfs_error_codes[] = { #define FF_CHECK(x, message, ...) { \ fresult = x; \ if (fresult != FR_OK) { \ - error_display(message " [%s]:\n %s\n", __VA_ARGS__ __VA_OPT__(,) #x, fatfs_error_codes[fresult]); \ + error_display(message ".\nReason: %s", __VA_ARGS__ __VA_OPT__(,) fatfs_error_codes[fresult]); \ } \ } @@ -55,11 +55,11 @@ static void menu_check_load_address (void *address, size_t size) { void *bootloader_end = (void *) (&__bootloader_end); if ((menu_start < usable_ram_start) || (menu_end > usable_ram_end)) { - error_display("Incorrect menu load address/size:\n Outside of usable RAM space\n"); + error_display("Incorrect menu load address/size.\nReason: Outside of usable RAM space\n"); } if ((menu_start < bootloader_end) && (bootloader_start < menu_end)) { - error_display("Incorrect menu load address/size:\n Overlapping bootloader space\n"); + error_display("Incorrect menu load address/size.\nReason: Overlapping bootloader space\n"); } } @@ -72,21 +72,21 @@ void menu_load_and_run (void) { UINT br; size_t size = ROM_MAX_LOAD_SIZE; - FF_CHECK(f_mount(&fs, "", 1), "Couldn't mount drive"); - FF_CHECK(f_open(&fil, "sc64menu.n64", FA_READ), "Couldn't open menu file"); - FF_CHECK(f_lseek(&fil, ROM_ENTRY_OFFSET), "Couldn't seek to entry point offset"); - FF_CHECK(f_read(&fil, &menu, sizeof(menu), &br), "Couldn't read entry point"); - FF_CHECK(f_lseek(&fil, ROM_CODE_OFFSET), "Couldn't seek to code start offset"); + FF_CHECK(f_mount(&fs, "", 1), "SD card initialize error. No SD card or invalid partition table"); + FF_CHECK(f_open(&fil, "sc64menu.n64", FA_READ), "Could not open menu executable (sc64menu.n64)"); + FF_CHECK(f_lseek(&fil, ROM_ENTRY_OFFSET), "Could not seek to entry point offset"); + FF_CHECK(f_read(&fil, &menu, sizeof(menu), &br), "Could not read entry point"); + FF_CHECK(f_lseek(&fil, ROM_CODE_OFFSET), "Could not seek to code start offset"); if ((f_size(&fil) - ROM_CODE_OFFSET) < size) { size = (size_t) (f_size(&fil) - ROM_CODE_OFFSET); } menu_check_load_address(menu, size); cache_data_hit_writeback_invalidate(menu, size); cache_inst_hit_invalidate(menu, size); - FF_CHECK(f_read(&fil, menu, size, &br), "Couldn't read menu file"); + FF_CHECK(f_read(&fil, menu, size, &br), "Could not read menu file"); FF_CHECK((br != size) ? FR_INT_ERR : FR_OK, "Read size is different than expected"); - FF_CHECK(f_close(&fil), "Couldn't close menu file"); - FF_CHECK(f_unmount(""), "Couldn't unmount drive"); + FF_CHECK(f_close(&fil), "Could not close menu file"); + FF_CHECK(f_unmount(""), "Could not unmount drive"); deinit(); diff --git a/sw/controller/src/cfg.c b/sw/controller/src/cfg.c index 1e1c8e8..dcc1939 100644 --- a/sw/controller/src/cfg.c +++ b/sw/controller/src/cfg.c @@ -397,10 +397,8 @@ bool cfg_update_setting (uint32_t *args) { return false; } -bool cfg_set_rom_write_enable (bool value) { - uint32_t scr = fpga_reg_get(REG_CFG_SCR); +void cfg_set_rom_write_enable (bool value) { cfg_change_scr_bits(CFG_SCR_ROM_WRITE_ENABLED, value); - return (scr & CFG_SCR_ROM_WRITE_ENABLED); } save_type_t cfg_get_save_type (void) { @@ -472,7 +470,7 @@ void cfg_process (void) { break; case 'V': - args[0] = version_firmware(); + version_firmware(&args[0], &args[1]); break; case 'c': diff --git a/sw/controller/src/cfg.h b/sw/controller/src/cfg.h index cebc36f..bd67d20 100644 --- a/sw/controller/src/cfg.h +++ b/sw/controller/src/cfg.h @@ -21,7 +21,7 @@ bool cfg_query (uint32_t *args); bool cfg_update (uint32_t *args); bool cfg_query_setting (uint32_t *args); bool cfg_update_setting (uint32_t *args); -bool cfg_set_rom_write_enable (bool value); +void cfg_set_rom_write_enable (bool value); save_type_t cfg_get_save_type (void); void cfg_get_time (uint32_t *args); void cfg_set_time (uint32_t *args); diff --git a/sw/controller/src/flash.c b/sw/controller/src/flash.c index 8d32ca3..8ab204a 100644 --- a/sw/controller/src/flash.c +++ b/sw/controller/src/flash.c @@ -8,10 +8,10 @@ bool flash_program (uint32_t src, uint32_t dst, uint32_t length) { - if (((src + length) >= FLASH_ADDRESS) && (src < (FLASH_ADDRESS + FLASH_SIZE))) { + if (((src + length) > FLASH_ADDRESS) && (src < (FLASH_ADDRESS + FLASH_SIZE))) { return true; } - if ((dst < FLASH_ADDRESS) || ((dst + length) >= (FLASH_ADDRESS + FLASH_SIZE))) { + if ((dst < FLASH_ADDRESS) || ((dst + length) > (FLASH_ADDRESS + FLASH_SIZE))) { return true; } while (length > 0) { @@ -29,15 +29,18 @@ void flash_wait_busy (void) { fpga_mem_read(FLASH_ADDRESS, 2, dummy); } -bool flash_erase_block (uint32_t offset) { - if ((offset % FLASH_ERASE_BLOCK_SIZE) != 0) { +bool flash_erase_block (uint32_t address) { + if ((address % FLASH_ERASE_BLOCK_SIZE) != 0) { return true; } - offset &= (FLASH_SIZE - 1); + if ((address < FLASH_ADDRESS) || (address >= (FLASH_ADDRESS + FLASH_SIZE))) { + return true; + } + address &= (FLASH_SIZE - 1); for (int i = 0; i < (FLASH_ERASE_BLOCK_SIZE / ERASE_BLOCK_SIZE); i++) { - fpga_reg_set(REG_FLASH_SCR, offset); + fpga_reg_set(REG_FLASH_SCR, address); while (fpga_reg_get(REG_FLASH_SCR) & FLASH_SCR_BUSY); - offset += ERASE_BLOCK_SIZE; + address += ERASE_BLOCK_SIZE; } flash_wait_busy(); return false; diff --git a/sw/controller/src/flash.h b/sw/controller/src/flash.h index d2b2cb1..a54c535 100644 --- a/sw/controller/src/flash.h +++ b/sw/controller/src/flash.h @@ -11,7 +11,7 @@ bool flash_program (uint32_t src, uint32_t dst, uint32_t length); void flash_wait_busy (void); -bool flash_erase_block (uint32_t offset); +bool flash_erase_block (uint32_t address); #endif diff --git a/sw/controller/src/update.c b/sw/controller/src/update.c index 52549cf..521e6a3 100644 --- a/sw/controller/src/update.c +++ b/sw/controller/src/update.c @@ -6,6 +6,9 @@ #include "vendor.h" +#define SDRAM_ADDRESS (0x00000000UL) +#define SDRAM_LENGTH (64 * 1024 * 1024) + #define UPDATE_MAGIC_START (0x54535055UL) #define BOOTLOADER_ADDRESS (0x04E00000UL) #define BOOTLOADER_LENGTH (0x001E0000UL) @@ -191,6 +194,10 @@ update_error_t update_backup (uint32_t address, uint32_t *length) { uint32_t fpga_length; uint32_t bootloader_length; + if (address >= (SDRAM_ADDRESS + SDRAM_LENGTH)) { + return UPDATE_ERROR_ADDRESS; + } + *length = update_write_token(&address); *length += update_prepare_chunk(&address, CHUNK_ID_MCU_DATA); @@ -214,6 +221,10 @@ update_error_t update_backup (uint32_t address, uint32_t *length) { } *length += update_finalize_chunk(&address, bootloader_length); + if ((address + *length) > (SDRAM_ADDRESS + SDRAM_LENGTH)) { + return UPDATE_ERROR_ADDRESS; + } + return UPDATE_OK; } @@ -223,6 +234,13 @@ update_error_t update_prepare (uint32_t address, uint32_t length) { uint32_t data_address; uint32_t data_length; + if ((address >= (SDRAM_ADDRESS + SDRAM_LENGTH)) || (length > SDRAM_LENGTH)) { + return UPDATE_ERROR_ADDRESS; + } + if (end_address > (SDRAM_ADDRESS + SDRAM_LENGTH)) { + return UPDATE_ERROR_ADDRESS; + } + if (update_check_token(&address)) { return UPDATE_ERROR_TOKEN; } diff --git a/sw/controller/src/update.h b/sw/controller/src/update.h index b6f029c..1b2ff4d 100644 --- a/sw/controller/src/update.h +++ b/sw/controller/src/update.h @@ -13,6 +13,7 @@ typedef enum { UPDATE_ERROR_SIZE, UPDATE_ERROR_UNKNOWN_CHUNK, UPDATE_ERROR_READ, + UPDATE_ERROR_ADDRESS, } update_error_t; diff --git a/sw/controller/src/usb.c b/sw/controller/src/usb.c index a694694..52d531c 100644 --- a/sw/controller/src/usb.c +++ b/sw/controller/src/usb.c @@ -10,10 +10,20 @@ #include "version.h" +#define BOOTLOADER_ADDRESS (0x04E00000UL) +#define BOOTLOADER_LENGTH (1920 * 1024) + +#define MEMORY_LENGTH (0x05002980UL) + +#define RX_FLUSH_ADDRESS (0x07F00000UL) +#define RX_FLUSH_LENGTH (1 * 1024 * 1024) + + enum rx_state { RX_STATE_IDLE, RX_STATE_ARGS, RX_STATE_DATA, + RX_STATE_FLUSH, }; enum tx_state { @@ -129,6 +139,21 @@ static bool usb_rx_cmd (uint8_t *cmd) { return false; } +static bool usb_validate_address_length (uint32_t address, uint32_t length, bool exclude_bootloader) { + if ((address >= MEMORY_LENGTH) || (length > MEMORY_LENGTH)) { + return true; + } + if ((address + length) > MEMORY_LENGTH) { + return true; + } + if (exclude_bootloader) { + if (((address + length) > BOOTLOADER_ADDRESS) && (address < (BOOTLOADER_ADDRESS + BOOTLOADER_LENGTH))) { + return true; + } + } + return false; +} + static void usb_rx_process (void) { if (p.rx_state == RX_STATE_IDLE) { if (!p.response_pending && usb_rx_cmd(&p.rx_cmd)) { @@ -166,8 +191,8 @@ static void usb_rx_process (void) { case 'V': p.rx_state = RX_STATE_IDLE; p.response_pending = true; - p.response_info.data_length = 4; - p.response_info.data[0] = version_firmware(); + p.response_info.data_length = 8; + version_firmware(&p.response_info.data[0], &p.response_info.data[1]); break; case 'R': @@ -229,17 +254,25 @@ static void usb_rx_process (void) { case 'm': p.rx_state = RX_STATE_IDLE; p.response_pending = true; - p.response_info.dma_address = p.rx_args[0]; - p.response_info.dma_length = p.rx_args[1]; + if (usb_validate_address_length(p.rx_args[0], p.rx_args[1], false)) { + p.response_error = true; + } else { + p.response_info.dma_address = p.rx_args[0]; + p.response_info.dma_length = p.rx_args[1]; + } break; case 'M': if (usb_dma_ready()) { if (!p.rx_dma_running) { - fpga_reg_set(REG_USB_DMA_ADDRESS, p.rx_args[0]); - fpga_reg_set(REG_USB_DMA_LENGTH, p.rx_args[1]); - fpga_reg_set(REG_USB_DMA_SCR, DMA_SCR_DIRECTION | DMA_SCR_START); - p.rx_dma_running = true; + if (usb_validate_address_length(p.rx_args[0], p.rx_args[1], true)) { + p.rx_state = RX_STATE_FLUSH; + } else { + fpga_reg_set(REG_USB_DMA_ADDRESS, p.rx_args[0]); + fpga_reg_set(REG_USB_DMA_LENGTH, p.rx_args[1]); + fpga_reg_set(REG_USB_DMA_SCR, DMA_SCR_DIRECTION | DMA_SCR_START); + p.rx_dma_running = true; + } } else { p.rx_state = RX_STATE_IDLE; p.response_pending = true; @@ -248,7 +281,9 @@ static void usb_rx_process (void) { break; case 'U': - if ((p.read_length > 0) && usb_dma_ready()) { + if (p.rx_args[1] == 0) { + p.rx_state = RX_STATE_IDLE; + } else if ((p.read_length > 0) && usb_dma_ready()) { uint32_t length = (p.read_length > p.rx_args[1]) ? p.rx_args[1] : p.read_length; if (!p.rx_dma_running) { fpga_reg_set(REG_USB_DMA_ADDRESS, p.read_address); @@ -258,12 +293,10 @@ static void usb_rx_process (void) { p.read_ready = false; } else { p.rx_args[1] -= length; + p.rx_dma_running = false; p.read_length -= length; p.read_address += length; p.read_ready = true; - if (p.rx_args[1] == 0) { - p.rx_state = RX_STATE_IDLE; - } } } break; @@ -285,24 +318,26 @@ static void usb_rx_process (void) { break; case 'P': - p.response_error = flash_erase_block(p.rx_args[0]); + if (usb_validate_address_length(p.rx_args[0], FLASH_ERASE_BLOCK_SIZE, true)) { + p.response_error = true; + } else { + p.response_error = flash_erase_block(p.rx_args[0]); + } p.rx_state = RX_STATE_IDLE; p.response_pending = true; break; - case 'f': { - bool rom_write_enable_restore = cfg_set_rom_write_enable(false); + case 'f': + cfg_set_rom_write_enable(false); p.response_info.data[0] = update_backup(p.rx_args[0], &p.response_info.data[1]); p.rx_state = RX_STATE_IDLE; p.response_pending = true; p.response_error = (p.response_info.data[0] != UPDATE_OK); p.response_info.data_length = 8; - cfg_set_rom_write_enable(rom_write_enable_restore); break; - } - case 'F': { - bool rom_write_enable_restore = cfg_set_rom_write_enable(false); + case 'F': + cfg_set_rom_write_enable(false); p.response_info.data[0] = update_prepare(p.rx_args[0], p.rx_args[1]); p.rx_state = RX_STATE_IDLE; p.response_pending = true; @@ -311,10 +346,8 @@ static void usb_rx_process (void) { p.response_info.done_callback = update_start; } else { p.response_error = true; - cfg_set_rom_write_enable(rom_write_enable_restore); } break; - } case '?': p.rx_state = RX_STATE_IDLE; @@ -336,10 +369,26 @@ static void usb_rx_process (void) { p.response_pending = true; p.response_error = true; p.response_info.data_length = 4; - p.response_info.data[0] = 0xFF; + p.response_info.data[0] = 0xFFFFFFFF; break; } } + + if (p.rx_state == RX_STATE_FLUSH) { + if (usb_dma_ready()) { + if (p.rx_args[1] != 0) { + uint32_t length = (p.rx_args[1] > RX_FLUSH_LENGTH) ? RX_FLUSH_LENGTH : p.rx_args[1]; + fpga_reg_set(REG_USB_DMA_ADDRESS, RX_FLUSH_ADDRESS); + fpga_reg_set(REG_USB_DMA_LENGTH, length); + fpga_reg_set(REG_USB_DMA_SCR, DMA_SCR_DIRECTION | DMA_SCR_START); + p.rx_args[1] -= length; + } else { + p.rx_state = RX_STATE_IDLE; + p.response_pending = true; + p.response_error = true; + } + } + } } static void usb_tx_process (void) { diff --git a/sw/controller/src/version.c b/sw/controller/src/version.c index fb992ad..082e432 100644 --- a/sw/controller/src/version.c +++ b/sw/controller/src/version.c @@ -1,10 +1,12 @@ #include "version.h" -#define VERSION_MAJOR (2) -#define VERSION_MINOR (12) +#define VERSION_MAJOR (2) +#define VERSION_MINOR (12) +#define VERSION_REVISION (1) -uint32_t version_firmware (void) { - return ((VERSION_MAJOR << 16) | (VERSION_MINOR)); +void version_firmware (uint32_t *version, uint32_t *revision) { + *version = ((VERSION_MAJOR << 16) | (VERSION_MINOR)); + *revision = VERSION_REVISION; } diff --git a/sw/controller/src/version.h b/sw/controller/src/version.h index b5a3c0a..60d54d2 100644 --- a/sw/controller/src/version.h +++ b/sw/controller/src/version.h @@ -5,7 +5,7 @@ #include -uint32_t version_firmware (void); +void version_firmware (uint32_t *version, uint32_t *revision); #endif diff --git a/sw/deployer/.gitignore b/sw/deployer/.gitignore new file mode 100644 index 0000000..84c0ad1 --- /dev/null +++ b/sw/deployer/.gitignore @@ -0,0 +1,9 @@ +/target +*.bin +*.eep +*.fla +*.n64 +*.png +*.srm +*.v64 +*.z64 diff --git a/sw/deployer/Cargo.lock b/sw/deployer/Cargo.lock new file mode 100644 index 0000000..2bd78ad --- /dev/null +++ b/sw/deployer/Cargo.lock @@ -0,0 +1,1335 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "CoreFoundation-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0e9889e6db118d49d88d84728d0e964d973a5680befb5f85f55141beea5c20b" +dependencies = [ + "libc", + "mach", +] + +[[package]] +name = "IOKit-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99696c398cbaf669d2368076bdb3d627fb0ce51a26899d7c61228c5c0af3bf4a" +dependencies = [ + "CoreFoundation-sys", + "libc", + "mach", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "adler32" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bumpalo" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" + +[[package]] +name = "bytemuck" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-integer", + "num-traits", + "time", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "clap" +version = "4.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d7ae14b20b94cb02149ed21a86c423859cbe18dc7ed69845cace50e52b40a5" +dependencies = [ + "bitflags", + "clap_derive", + "clap_lex", + "is-terminal", + "once_cell", + "strsim", + "termcolor", +] + +[[package]] +name = "clap-num" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488557e97528174edaa2ee268b23a809e0c598213a4bbcb4f34575a46fda147e" +dependencies = [ + "num-traits", +] + +[[package]] +name = "clap_derive" +version = "4.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44bec8e5c9d09e439c4335b1af0abaab56dcf3b94999a936e1bb47b9134288f0" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "350b9cf31731f9957399229e9b2adc51eeabdfbe9d71d9a0552275fd12710d09" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "colored" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +dependencies = [ + "atty", + "lazy_static", + "winapi", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "ctrlc" +version = "3.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbcf33c2a618cbe41ee43ae6e9f2e48368cd9f9db2896f10167d8d762679f639" +dependencies = [ + "nix", + "windows-sys", +] + +[[package]] +name = "cxx" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a140f260e6f3f79013b8bfc65e7ce630c9ab4388c6a89c71e07226f49487b72" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da6383f459341ea689374bf0a42979739dc421874f112ff26f829b8040b8e613" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90201c1a650e95ccff1c8c0bb5a343213bdd317c6e600a93075bca2eff54ec97" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b75aed41bb2e6367cae39e6326ef817a851db13c13e4f3263714ca3cfb8de56" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dlv-list" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" + +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + +[[package]] +name = "encoding_rs" +version = "0.8.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "exr" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8af5ef47e2ed89d23d0ecbc1b681b30390069de70260937877514377fc24feb" +dependencies = [ + "bit_field", + "flume", + "half", + "lebe", + "miniz_oxide", + "smallvec", + "threadpool", + "zune-inflate", +] + +[[package]] +name = "flate2" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "flume" +version = "0.10.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "pin-project", + "spin", +] + +[[package]] +name = "futures-core" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" + +[[package]] +name = "futures-sink" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "gif" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3edd93c6756b4dfaf2709eafcc345ba2636565295c198a9cfbf75fa5e3e00b06" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "half" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" +dependencies = [ + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + +[[package]] +name = "image" +version = "0.24.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69b7ea949b537b0fd0af141fff8c77690f2ce96f4f41f042ccb6c69c6c965945" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "exr", + "gif", + "jpeg-decoder", + "num-rational", + "num-traits", + "png", + "scoped_threadpool", + "tiff", +] + +[[package]] +name = "include-flate" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e11569346406931d20276cc460215ee2826e7cad43aa986999cb244dd7adb0" +dependencies = [ + "include-flate-codegen-exports", + "lazy_static", + "libflate", +] + +[[package]] +name = "include-flate-codegen" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a7d6e1419fa3129eb0802b4c99603c0d425c79fb5d76191d5a20d0ab0d664e8" +dependencies = [ + "libflate", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "include-flate-codegen-exports" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75657043ffe3d8280f1cb8aef0f505532b392ed7758e0baeac22edadcee31a03" +dependencies = [ + "include-flate-codegen", + "proc-macro-hack", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfa919a82ea574332e2de6e74b4c36e74d41982b335080fa59d4ef31be20fdf3" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "is-terminal" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857" +dependencies = [ + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix", + "windows-sys", +] + +[[package]] +name = "jpeg-decoder" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" +dependencies = [ + "rayon", +] + +[[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lebe" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" + +[[package]] +name = "libc" +version = "0.2.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" + +[[package]] +name = "libflate" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97822bf791bd4d5b403713886a5fbe8bf49520fe78e323b0dc480ca1a03e50b0" +dependencies = [ + "adler32", + "crc32fast", + "libflate_lz77", +] + +[[package]] +name = "libflate_lz77" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a52d3a8bfc85f250440e4424db7d857e241a3aebbbe301f3eb606ab15c39acbf" +dependencies = [ + "rle-decode-fast", +] + +[[package]] +name = "libudev" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b324152da65df7bb95acfcaab55e3097ceaab02fb19b228a9eb74d55f135e0" +dependencies = [ + "libc", + "libudev-sys", +] + +[[package]] +name = "libudev-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "link-cplusplus" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "mach" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd13ee2dd61cc82833ba05ade5a30bb3d63f7ced605ef827063c63078302de9" +dependencies = [ + "libc", +] + +[[package]] +name = "mach2" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8" +dependencies = [ + "libc", +] + +[[package]] +name = "md5" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memoffset" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom", +] + +[[package]] +name = "nix" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +dependencies = [ + "bitflags", + "cfg-if", + "libc", + "static_assertions", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi 0.2.6", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "ordered-multimap" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a" +dependencies = [ + "dlv-list", + "hashbrown", +] + +[[package]] +name = "os_str_bytes" +version = "6.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" + +[[package]] +name = "panic-message" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384e52fd8fbd4cbe3c317e8216260c21a0f9134de108cea8a4dd4e7e152c472d" + +[[package]] +name = "pin-project" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pkg-config" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" + +[[package]] +name = "png" +version = "0.17.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638" +dependencies = [ + "bitflags", + "crc32fast", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro2" +version = "1.0.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rayon" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "regex" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" + +[[package]] +name = "rle-decode-fast" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422" + +[[package]] +name = "rust-ini" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df" +dependencies = [ + "cfg-if", + "ordered-multimap", +] + +[[package]] +name = "rustix" +version = "0.36.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd5c6ff11fecd55b40746d1995a02f2eb375bf8c00d192d521ee09f42bef37bc" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "sc64deployer" +version = "2.12.1" +dependencies = [ + "chrono", + "clap", + "clap-num", + "colored", + "crc32fast", + "ctrlc", + "encoding_rs", + "hex", + "image", + "include-flate", + "md5", + "panic-message", + "rust-ini", + "serialport", +] + +[[package]] +name = "scoped_threadpool" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "scratch" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" + +[[package]] +name = "serialport" +version = "4.2.1-alpha.0" +source = "git+https://github.com/serialport/serialport-rs?branch=main#e1f46eef5af7df2430f0a595681243e46f721b2a" +dependencies = [ + "CoreFoundation-sys", + "IOKit-sys", + "bitflags", + "cfg-if", + "libudev", + "mach2", + "nix", + "regex", + "winapi", +] + +[[package]] +name = "simd-adler32" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14a5df39617d7c8558154693a1bb8157a4aab8179209540cc0b10e5dc24e0b18" + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "spin" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dccf47db1b41fa1573ed27ccf5e08e3ca771cb994f776668c5ebda893b248fc" +dependencies = [ + "lock_api", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "tiff" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7449334f9ff2baf290d55d73983a7d6fa15e01198faef72af07e2a8db851e471" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] + +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + +[[package]] +name = "unicode-ident" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + +[[package]] +name = "weezl" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" + +[[package]] +name = "zune-inflate" +version = "0.2.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01728b79fb9b7e28a8c11f715e1cd8dc2cda7416a007d66cac55cebb3a8ac6b" +dependencies = [ + "simd-adler32", +] diff --git a/sw/deployer/Cargo.toml b/sw/deployer/Cargo.toml new file mode 100644 index 0000000..ba20d41 --- /dev/null +++ b/sw/deployer/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "sc64deployer" +version = "2.12.1" +edition = "2021" +authors = ["Polprzewodnikowy"] +description = "SC64 loader and control software" +documentation = "https://github.com/Polprzewodnikowy/SummerCart64" + +[dependencies] +chrono = "0.4.23" +clap = { version = "4.1.6", features = ["derive"] } +clap-num = "1.0.2" +colored = "2.0.0" +crc32fast = "1.3.2" +ctrlc = "3.2.5" +encoding_rs = "0.8.32" +hex = "0.4.3" +image = "0.24.5" +include-flate = { version = "0.2.0", features = ["stable"] } +md5 = "0.7.0" +panic-message = "0.3.0" +rust-ini = "0.18.0" +serialport = { git = "https://github.com/serialport/serialport-rs", branch = "main" } + +[profile.release] +lto = true +strip = true diff --git a/sw/deployer/data/mupen64plus.ini b/sw/deployer/data/mupen64plus.ini new file mode 100644 index 0000000..a4792bc --- /dev/null +++ b/sw/deployer/data/mupen64plus.ini @@ -0,0 +1,18178 @@ +; Mupen64Plus Rom Catalog +; Generated by M64P_INICreater.php +; Script coded by: okaygo +; +; Total Rom Count: 3048 +; Fri, 06 Jun 08 23:13:38 -0400 + +[A56B15FAF24389DD375E7AFB03A7D3C1] +GoodName=007 - Goldfinger +CRC=B2242748 FFBD61DA +Status=1 +Rumble=Yes +Players=4 +CountPerOp=1 + +[34AB1DEA3111A233A8B5C5679DE22E83] +GoodName=007 - The World is Not Enough (E) (M3) [!] +CRC=3B941695 F90A5EEB +SaveType=None +Mempak=Yes +Status=1 +Rumble=Yes +Players=4 + +[9D58996A8AA91263B5CD45C385F45FE4] +GoodName=007 - The World is Not Enough (U) [!] +CRC=033F4C13 319EE7A7 +SaveType=None +Mempak=Yes +Status=1 +Rumble=Yes +Players=4 + +[12BD3FAFB4E064B6B0C07B7EE156243B] +GoodName=007 - The World is Not Enough (U) (Beta) [!] +CRC=A92E0966 341C3912 +SaveType=None +Mempak=Yes +Status=1 +Rumble=Yes +Players=4 + +[0846FFFDA3081821EA0DCBB7D4DEAAA3] +GoodName=007 - The World is Not Enough (U) [t1] +CRC=5B6AC01B 8D1A562A +RefMD5=9D58996A8AA91263B5CD45C385F45FE4 + +[1D86AE43FF88E4583C8161815577F1CD] +GoodName=007 - The World is Not Enough (U) [t1][f1] (PAL-NTSC) +CRC=5B6AC01B 8D1A562A +RefMD5=9D58996A8AA91263B5CD45C385F45FE4 + +[632C98CF281CDA776E66685B278A4FA6] +GoodName=1080 Snowboarding (E) (M4) [!] +CRC=58FD3F25 D92EAA8D +SaveType=SRAM +Status=2 +Players=2 +Rumble=Yes + +[4E08D29B094C13C030AC73A1DA2F8CD2] +GoodName=1080 Snowboarding (E) (M4) [b1] +CRC=6BB11645 2C6F637E +RefMD5=632C98CF281CDA776E66685B278A4FA6 + +[4FCA132D6C96130371F4186A3DF85077] +GoodName=1080 Snowboarding (E) (M4) [b1][f2] (NTSC) +CRC=58FD3F25 D92EAA8D +RefMD5=632C98CF281CDA776E66685B278A4FA6 + +[EC9DB32624B6C16376429D0660F0710B] +GoodName=1080 Snowboarding (E) (M4) [f1] +CRC=AF61F386 29F1112C +RefMD5=632C98CF281CDA776E66685B278A4FA6 + +[5CA3A45C21E16EDAFBAFE1BD0491DC8D] +GoodName=1080 Snowboarding (E) (M4) [f2] (NTSC) +CRC=93C5ED78 F67E8528 +RefMD5=632C98CF281CDA776E66685B278A4FA6 + +[FA27089C425DBAB99F19245C5C997613] +GoodName=1080 Snowboarding (JU) (M2) [!] +CRC=1FBAF161 2C1C54F1 +SaveType=SRAM +Status=2 +Players=2 +Rumble=Yes + +[E428181D573E25DCC0DC7F9F3BF4D1E1] +GoodName=1080 Snowboarding (JU) (M2) [b1] +CRC=92072A84 275952F8 +RefMD5=FA27089C425DBAB99F19245C5C997613 + +[A3D30FBDFD84B5E7298568BBD5CED7FD] +GoodName=1080 Snowboarding (JU) (M2) [b2] +CRC=1FBAF161 2C1C54F1 +RefMD5=FA27089C425DBAB99F19245C5C997613 + +[FE15A6E7AF4E37487252369D6F0AB35B] +GoodName=1080 Snowboarding (JU) (M2) [b3] +CRC=92072A84 275952F8 +RefMD5=FA27089C425DBAB99F19245C5C997613 + +[7657C4BB92E3F6F126D94F5942FDB445] +GoodName=1080 Snowboarding (JU) (M2) [b4] +CRC=92072A84 275952F8 +RefMD5=FA27089C425DBAB99F19245C5C997613 + +[C7AC7460AF3897BB38D6745BC4557C8E] +GoodName=1080 Snowboarding (JU) (M2) [b5] +CRC=92072A84 275952F8 +RefMD5=FA27089C425DBAB99F19245C5C997613 + +[FE320327CF6EDC64D06BFA56D8E7A085] +GoodName=1080 Snowboarding (JU) (M2) [b6] +CRC=92072A84 275952F8 +RefMD5=FA27089C425DBAB99F19245C5C997613 + +[C36AC032E36C61723698344C33DC1F7E] +GoodName=1080 Snowboarding (JU) (M2) [b7] +CRC=92072A84 275952F8 +RefMD5=FA27089C425DBAB99F19245C5C997613 + +[DAFE880CEF56AF0231EBA2390259A2AC] +GoodName=1080 Snowboarding (JU) (M2) [b8] +CRC=92072A84 275952F8 +RefMD5=FA27089C425DBAB99F19245C5C997613 + +[A0B2E39FD3FE3802C369A6937416B38E] +GoodName=1080 Snowboarding (JU) (M2) [b9] +CRC=1FBAF161 2C1C54F1 +RefMD5=FA27089C425DBAB99F19245C5C997613 + +[2C6A75570997BA7A1244950AC8FE6CBF] +GoodName=1080 Snowboarding (JU) (M2) [ba] +CRC=35F53383 0C8D0AE4 +RefMD5=FA27089C425DBAB99F19245C5C997613 + +[3B5691B895B415056E4EA69695DC26B4] +GoodName=1080 Snowboarding (JU) (M2) [f1] (DS-1) +CRC=92072A84 275952F8 +RefMD5=FA27089C425DBAB99F19245C5C997613 + +[6CEACF73F03BA3DE740BDB00D7CC18A1] +GoodName=1080 Snowboarding (JU) (M2) [f2] (PAL) +CRC=9207357A E85D4001 +RefMD5=FA27089C425DBAB99F19245C5C997613 + +[765DC057507AA32DAAEC194E32FF26B1] +GoodName=1080 Snowboarding (JU) (M2) [f2][b1] +CRC=1FBAF161 2C1C54F1 +RefMD5=FA27089C425DBAB99F19245C5C997613 + +[1ED9C697BD2F2AEBE6B3B8BF0D24A8CA] +GoodName=1080 Snowboarding (JU) (M2) [f3][t1] +CRC=92072A84 275952F8 +RefMD5=FA27089C425DBAB99F19245C5C997613 + +[C70578054AA00D7F95AE1D64E3AA9995] +GoodName=1080 Snowboarding (JU) (M2) [f3][t2] (All Levels) +CRC=92072A84 275952F8 +RefMD5=FA27089C425DBAB99F19245C5C997613 + +[00CE20766866883063AF3A6C3368039F] +GoodName=1080 Snowboarding (JU) (M2) [f4] (PAL-Z64) +CRC=92072A84 275952F8 +RefMD5=FA27089C425DBAB99F19245C5C997613 + +[AEE3FA928B2C1B73D841B47074D91C71] +GoodName=1080 Snowboarding (JU) (M2) [f5] (SRAM) +CRC=92072A84 275952F8 +RefMD5=FA27089C425DBAB99F19245C5C997613 + +[B5AC31D584BB2EF93C2A229E19B6D9A1] +GoodName=1080 Snowboarding (JU) (M2) [h1C] +CRC=35F53383 0C8D0AE4 +RefMD5=FA27089C425DBAB99F19245C5C997613 + +[136245692E02003ED1A972F424CD9323] +GoodName=1080 Snowboarding (JU) (M2) [h2C] +CRC=92072A84 275952F8 +RefMD5=FA27089C425DBAB99F19245C5C997613 + +[EC4458443FBA0F09B8593AC5ED114C26] +GoodName=1964 Demo by Steb (PD) +CRC=5C450380 4B5CB6E6 + +[E76EA30A71F9DC19C6502591FA7CB8E2] +GoodName=2 Blokes & An Armchair - Nintendo 64 Remix Remix by Tesko (PD) [f1] +CRC=04815914 87141455 + +[B05E10857A76AB70A83017ADDE8A8ACC] +GoodName=2 Blokes & An Armchair - Nintendo 64 Remix Remix by Tesko (PD) +CRC=04815914 87141455 + +[8BEC4EDFA1446859DA896E4EBAE8F925] +GoodName=3DS Model Conversion by Snake (PD) +CRC=4C304819 2CBE7573 +Players=0 +Rumble=No +Status=4 +SaveType=None + +[DF6BC38C3D0C722DADD4EEDB5DFCE305] +GoodName=3DS Model Conversion by Snake (PD) [h1C] +CRC=4C304819 2CBE7573 +RefMD5=8BEC4EDFA1446859DA896E4EBAE8F925 + +[0A5ACFEA0C7CF68AE25202040D5AD1EB] +GoodName=40 Winks (E) (M3) (Prototype) +CRC=ABA51D09 C668BAD9 +Mempak=Yes +Rumble=Yes + +[66335F4DC6AB27034398BC26F263B897] +GoodName=64 Hanafuda - Tenshi no Yakusoku (J) [!] +CRC=36F22FBF 318912F2 +Players=1 +SaveType=Eeprom 4KB +Status=5 + +[2CF9EDB51ADA9DE2AE7AD9FD5ACC5580] +GoodName=64 Oozumou (J) [!] +CRC=9C961069 F5EA488D +Players=4 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes +Status=5 +CountPerOp=1 + +[88763C3FD50E036BBB9CF504F77C0741] +GoodName=64 Oozumou (J) [b1] +CRC=9C961069 F5EA488D +RefMD5=2CF9EDB51ADA9DE2AE7AD9FD5ACC5580 + +[9A737609D5A7565589DA44381C476FD3] +GoodName=64 Oozumou (J) [b2] +CRC=9C961069 F5EA488D +RefMD5=2CF9EDB51ADA9DE2AE7AD9FD5ACC5580 + +[CD4F6C55A7567A25954908DF613B236F] +GoodName=64 Oozumou (J) [b3] +CRC=9C961069 F5EA488D +RefMD5=2CF9EDB51ADA9DE2AE7AD9FD5ACC5580 + +[F7C796371E77E0A6FBD02EB866341952] +GoodName=64 Oozumou 2 (J) [!] +CRC=85C18B16 DF9622AF +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +Status=5 + +[6B947F654775CF5DACD1E5D53D577DA7] +GoodName=64 Trump Collection - Alice no Wakuwaku Trump World (J) [!] +CRC=7A6081FC FF8F7A78 +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes +Status=5 + +[2C6FDCF4A6A6614D09224EFAA55FB531] +GoodName=64 Trump Collection - Alice no Wakuwaku Trump World (J) [h1C] +CRC=7A6081FC FF8F7A78 +RefMD5=6B947F654775CF5DACD1E5D53D577DA7 + +[EA6A92DE5A221A00814F7448BF6F1B31] +GoodName=64 de Hakken!! Tamagotchi Minna de Tamagotchi World (J) [!] +CRC=B98BA456 5B2B76AF +Players=4 +Status=2 +SaveType=Eeprom 4KB +Mempak=Yes +CountPerOp=1 + +[11B20CFE8E3ECCC680AA8157A7906D6D] +GoodName=64 de Hakken!! Tamagotchi Minna de Tamagotchi World (J) [b1] +CRC=B98BA456 5B2B76AF +RefMD5=EA6A92DE5A221A00814F7448BF6F1B31 + +[D8F6D887B94BA913EF60A0B03F781AE6] +GoodName=64 de Hakken!! Tamagotchi Minna de Tamagotchi World (J) [h1C] +CRC=B98BA456 5B2B76AF +RefMD5=EA6A92DE5A221A00814F7448BF6F1B31 + +[326BF85C5EF158205364710454EE1AF1] +GoodName=64 de Hakken!! Tamagotchi Minna de Tamagotchi World (J) [h2C] +CRC=B98BA456 5B2B76AF +RefMD5=EA6A92DE5A221A00814F7448BF6F1B31 + +[11B891B7551BFBDB79732BFB94B45603] +GoodName=64 de Hakken!! Tamagotchi Minna de Tamagotchi World (J) [o1] +CRC=B98BA456 5B2B76AF +RefMD5=EA6A92DE5A221A00814F7448BF6F1B31 + +[14E8E1761B8994C54B304418CEA49773] +GoodName=77a Special Edition by Count0 (PD) +CRC=975B7845 A2505C18 +Players=2 +Status=1 +Rumble=No +SaveType=Eeprom 16KB + +[45C610FC443D0DF07ED9F07AC8B7C54A] +GoodName=77a Special Edition by Count0 (PD) [b1] +CRC=975B7845 A2505C18 +RefMD5=14E8E1761B8994C54B304418CEA49773 + +[7D6AC6295EF6A0ABB3D4594AF407B7A6] +GoodName=77a by Count0 (POM '98) (PD) +CRC=D6D29529 D4EADEE4 +Players=2 +Status=1 +Rumble=No +SaveType=None + +[A8426180C65A4C9DD1DF9FD033DDCBB6] +GoodName=77a by Count0 (POM '98) (PD) [b1] +CRC=D6D29529 D4EADEE4 +RefMD5=7D6AC6295EF6A0ABB3D4594AF407B7A6 + +[4A5C509A20DB7A429DC1DD4E219AD4A2] +GoodName=AI Shougi 3 (J) [!] +CRC=8CC182A6 C2D0CAB0 +Players=4 +Status=1 +SaveType=Eeprom 4KB +Mempak=Yes + +[D9FE93EBA610E60F8F5D9880E52DB056] +GoodName=Absolute Crap #2 by Lem (PD) +CRC=2E7E893C 4E68B642 +Status=3 +Players=0 +SaveType=None +Rumble=No + +[9E59882163EA99A45629B9B8B491D86B] +GoodName=Absolute Crap #2 by Lem (PD) [b1] +CRC=2E7E893C 4E68B642 +RefMD5=D9FE93EBA610E60F8F5D9880E52DB056 + +[D5F73BB1FC46328440C3BD9812A49284] +GoodName=Absolute Crap #2 by Lem (PD) [b2] +CRC=2E7E893C 4E68B642 +RefMD5=D9FE93EBA610E60F8F5D9880E52DB056 + +[2F02D478FC89E46FA143B128E29B434C] +GoodName=Absolute Crap Intro #1 by Kid Stardust (PD) [b1] +CRC=B0667DED BB39A4B8 +RefMD5=FF4D4FEFF0AF8A0F9B9AE509DA7D9071 + +[E06A7190B2DF9CCCCA30C1724DDFE95B] +GoodName=Absolute Crap Intro #1 by Kid Stardust (PD) [h1C] +CRC=B0667DED BB39A4B8 +RefMD5=FF4D4FEFF0AF8A0F9B9AE509DA7D9071 + +[FF4D4FEFF0AF8A0F9B9AE509DA7D9071] +GoodName=Absolute Crap Intro #1 by Kid Stardust (PD) +CRC=B0667DED BB39A4B8 +Players=0 +Status=5 +Rumble=No +SaveType=None + +[35BA407EA9E4EF7C0ACE8B4F58BEEC41] +GoodName=Action Replay Pro 64 V3.0 (Unl) +CRC=F1297BC9 42CDAE9D +Status=0 + +[0D77918E6C989261EEF81FE244E48EEF] +GoodName=Action Replay Pro 64 V3.0 (Unl) [b1] +CRC=158A155D C1538CDB +RefMD5=35BA407EA9E4EF7C0ACE8B4F58BEEC41 + +[FD8681CBF1A599FF2EA55DBF40EA7D27] +GoodName=Action Replay Pro 64 V3.0 (Unl) [f1] +CRC=8A155D15 53C1DB8C +RefMD5=35BA407EA9E4EF7C0ACE8B4F58BEEC41 + +[67AFA5DF80A5CFC91FCE1DC918EA0A4F] +GoodName=Action Replay Pro 64 V3.3 (Unl) +CRC=A8D1DAF2 31206B53 +Status=0 + +[7558E3DA7225712936D3BA3DCE210C36] +GoodName=AeroFighters Assault (E) (M3) [!] +CRC=62F6BE95 F102D6D6 +Players=2 +SaveType=Eeprom 4KB +Rumble=Yes +Status=3 + +[915E7762364C2449AAEBC4CA5278D1E8] +GoodName=AeroFighters Assault (E) (M3) [f1] (NTSC) +CRC=0BBCDFCF 2DD952CC +RefMD5=7558E3DA7225712936D3BA3DCE210C36 + +[6C25C8D7CE393C0214917A211A199F0C] +GoodName=AeroFighters Assault (E) (M3) [o1] +CRC=62F6BE95 F102D6D6 +RefMD5=7558E3DA7225712936D3BA3DCE210C36 + +[79FB6E2452AF077C5EF1DDE5FC810F04] +GoodName=AeroFighters Assault (U) [!] +CRC=1B598BF1 ECA29B45 +Players=2 +SaveType=Eeprom 4KB +Rumble=Yes +Status=3 + +[CF5FF92EED5FD3C714BC3C4D15C47AE3] +GoodName=AeroFighters Assault (U) [b1] +CRC=1B598BF1 ECA29B45 +RefMD5=79FB6E2452AF077C5EF1DDE5FC810F04 + +[7E3E9BC4188B37A4FC283E22BEDB5D49] +GoodName=AeroFighters Assault (U) [b2] +CRC=1B598BF1 ECA29B45 +RefMD5=79FB6E2452AF077C5EF1DDE5FC810F04 + +[48522CCF3D059DDF2DCF5D6AEE2D1FD7] +GoodName=AeroFighters Assault (U) [b3] +CRC=1B598BF1 ECA29B45 +RefMD5=79FB6E2452AF077C5EF1DDE5FC810F04 + +[24CA46D2C8E2D68978AEAE46C3862F1E] +GoodName=AeroFighters Assault (U) [f1] (PAL) +CRC=5C4EB1C9 12A49603 +RefMD5=79FB6E2452AF077C5EF1DDE5FC810F04 + +[0635FE16018BB216E5CD29C300CADC74] +GoodName=AeroFighters Assault (U) [h1C] +CRC=1B598BF1 ECA29B45 +RefMD5=79FB6E2452AF077C5EF1DDE5FC810F04 + +[6A56589EC8FADD1139EC4B6EED9D19AE] +GoodName=AeroFighters Assault (U) [h2C] +CRC=1B598BF1 ECA29B45 +RefMD5=79FB6E2452AF077C5EF1DDE5FC810F04 + +[63657276E7256DCA562F024FC71F4A47] +GoodName=AeroFighters Assault (U) [h3C] +CRC=1B598BF1 ECA29B45 +RefMD5=79FB6E2452AF077C5EF1DDE5FC810F04 + +[05056045447BF1FBA8F9878A7F6009F3] +GoodName=AeroGauge (E) (M3) [!] +CRC=D83045C8 F29D3A36 +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes +Status=4 + +[FD979768AC0EC6CBBCA8C5339D62BB05] +GoodName=AeroGauge (E) (M3) [f1] (NTSC) +CRC=440355A4 869CE5F9 +RefMD5=05056045447BF1FBA8F9878A7F6009F3 + +[E0256E4270887B99DA7E91A620FFEFF3] +GoodName=AeroGauge (E) (M3) [h1C] +CRC=D83045C8 F29D3A36 +RefMD5=05056045447BF1FBA8F9878A7F6009F3 + +[25D19487CB80DB724DB9D735F2C28E8B] +GoodName=AeroGauge (E) (M3) [h2C] +CRC=D83045C8 F29D3A36 +RefMD5=05056045447BF1FBA8F9878A7F6009F3 + +[E970AF3DE25BB5AE1154010E26AF776F] +GoodName=AeroGauge (J) (V1.0) (Kiosk Demo) [!] +CRC=B00903C9 3916C146 +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes +Status=4 + +[6A52188E8A7D008F1921AA8A6D40A74C] +GoodName=AeroGauge (J) (V1.0) (Kiosk Demo) [b1] +CRC=3F47EEA0 5DDF7A3C +RefMD5=E970AF3DE25BB5AE1154010E26AF776F + +[5AB4773BB270BE3A72BB79EF68DEA414] +GoodName=AeroGauge (J) (V1.0) (Kiosk Demo) [b2] +CRC=B00903C9 3916C146 +RefMD5=E970AF3DE25BB5AE1154010E26AF776F + +[13CCAA36D309B78D20C9C0C89A8CE650] +GoodName=AeroGauge (J) (V1.0) (Kiosk Demo) [b3] +CRC=B00903C9 3916C146 +RefMD5=E970AF3DE25BB5AE1154010E26AF776F + +[AC5828BA750A4DCDC840050DE66305E2] +GoodName=AeroGauge (J) (V1.0) (Kiosk Demo) [b4] +CRC=3F47EEA0 5DDF7A3C +RefMD5=E970AF3DE25BB5AE1154010E26AF776F + +[0620C2D134A0430F4AFA208FFEDA67B8] +GoodName=AeroGauge (J) (V1.1) [!] +CRC=80F41131 384645F6 +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes +Status=4 + +[CC8C56B4E37BC5A501087E7CE8C12CC5] +GoodName=AeroGauge (J) (V1.1) [b1] +CRC=80F41131 384645F6 +RefMD5=0620C2D134A0430F4AFA208FFEDA67B8 + +[426725BFE1A505D4C3B12862188A2526] +GoodName=AeroGauge (J) (V1.1) [b2] +CRC=80F41131 384645F6 +RefMD5=0620C2D134A0430F4AFA208FFEDA67B8 + +[A74429738648C96FAB23944CCB06AA6C] +GoodName=AeroGauge (J) (V1.1) [b3] +CRC=80F41131 384645F6 +RefMD5=0620C2D134A0430F4AFA208FFEDA67B8 + +[E38C4D24254BB3CB6C9EC75CD29A6566] +GoodName=AeroGauge (J) (V1.1) [b4] +CRC=80F41131 384645F6 +RefMD5=0620C2D134A0430F4AFA208FFEDA67B8 + +[E80AD38B3139CBA5A367CB9B0B21AAFA] +GoodName=AeroGauge (J) (V1.1) [b5] +CRC=80F41131 384645F6 +RefMD5=0620C2D134A0430F4AFA208FFEDA67B8 + +[CDCB7101471DD1129DF63D6076834337] +GoodName=AeroGauge (J) (V1.1) [b6] +CRC=80F41131 384645F6 +RefMD5=0620C2D134A0430F4AFA208FFEDA67B8 + +[AB36ED30033F4101D3F660951A568413] +GoodName=AeroGauge (J) (V1.1) [b7] +CRC=80F41131 384645F6 +RefMD5=0620C2D134A0430F4AFA208FFEDA67B8 + +[9D7DAD00EAAC504D459608AB30CB0C1E] +GoodName=AeroGauge (J) (V1.1) [f1] (PAL) +CRC=4795217F 63D42538 +RefMD5=0620C2D134A0430F4AFA208FFEDA67B8 + +[72C7FFCEA6C1430616867616F5E9D51A] +GoodName=AeroGauge (U) [!] +CRC=AEBE463E CC71464B +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes +Status=4 + +[B8BA26F0C27253B80E5C7D96B0FB66AB] +GoodName=AeroGauge (U) [T+Ita0.01_Cattivik66] +CRC=AEBE463E CC71464B +RefMD5=72C7FFCEA6C1430616867616F5E9D51A + +[3D6C792ED4FA3CE5C92013F15BCCD327] +GoodName=AeroGauge (U) [b1] +CRC=AEBE463E CC71464B +RefMD5=72C7FFCEA6C1430616867616F5E9D51A + +[B7DB0D2CDCAB307D744B6370F1BBA9C1] +GoodName=AeroGauge (U) [f1] (PAL) +CRC=FDAA963C FDCCD971 +RefMD5=72C7FFCEA6C1430616867616F5E9D51A + +[11BE82186C64EF407B28403D49B199DB] +GoodName=AeroGauge (U) [h1C] +CRC=AEBE463E CC71464B +RefMD5=72C7FFCEA6C1430616867616F5E9D51A + +[31E739E6420DA88ABF4980AD0C76439A] +GoodName=AeroGauge (U) [h2C] +CRC=AEBE463E CC71464B +RefMD5=72C7FFCEA6C1430616867616F5E9D51A + +[54D0A39123C15F74AABB1ECC24D4D6A0] +GoodName=Aidyn Chronicles - The First Mage (E) [!] +CRC=2DC4FFCC C8FF5A21 +Players=1 +SaveType=None +Mempak=Yes +Status=3 + +[AF149336B3DDB899598E7BE8740D7DC6] +GoodName=Aidyn Chronicles - The First Mage (U) (V1.0) [!] +CRC=E6A95A4F BAD2EA23 +Players=1 +SaveType=None +Mempak=Yes +Status=3 + +[31448B07CBC932018870F71D1254E317] +GoodName=Aidyn Chronicles - The First Mage (U) (V1.0) [o1] +CRC=E6A95A4F BAD2EA23 +RefMD5=AF149336B3DDB899598E7BE8740D7DC6 + +[E8CDDF0C52B72453D52DA385322DFE15] +GoodName=Aidyn Chronicles - The First Mage (U) (V1.1) [!] +CRC=112051D2 68BEF8AC +RefMD5=AF149336B3DDB899598E7BE8740D7DC6 + +[CD24763BECFA1D0053E5438B0EF5E75E] +GoodName=Aidyn Chronicles - The First Mage (U) (Beta) (2000-02-10) +CRC=40066883 9375D98F +RefMD5=AF149336B3DDB899598E7BE8740D7DC6 + +[CC6EAE9ED582044CC27945684FD396CD] +GoodName=Aidyn Chronicles - The First Mage (U) (Beta) (2000-05-09) +CRC=FC8BED44 D640D904 +RefMD5=AF149336B3DDB899598E7BE8740D7DC6 + +[E8891F8F498A615A6CBAF75B7DDC9FA6] +GoodName=Airboarder 64 (E) [!] +CRC=27C425D0 8C2D99C1 +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes +Status=4 +Rumble=Yes +CountPerOp=1 + +[DCFB92A4B106FE61E54579B1D3B7336E] +GoodName=Airboarder 64 (E) [f1] (NTSC) +CRC=89A498AE DE3CD49A +RefMD5=E8891F8F498A615A6CBAF75B7DDC9FA6 + +[A0EE7484500178BAB44FDE0AF6D5748F] +GoodName=Airboarder 64 (E) [h1C] +CRC=27C425D0 8C2D99C1 +RefMD5=E8891F8F498A615A6CBAF75B7DDC9FA6 + +[CCEE2FCF38DC2200128D75D15DB53283] +GoodName=Airboarder 64 (J) [!] +CRC=6C45B60C DCE50E30 +Players=2 +Status=4 +Rumble=Yes +SaveType=Eeprom 4KB +Mempak=Yes +CountPerOp=1 + +[F558165311C9CDCA73FB089E298F2056] +GoodName=Airboarder 64 (J) [b1] +CRC=6C45B60C DCE50E30 +RefMD5=CCEE2FCF38DC2200128D75D15DB53283 + +[62B005D0E9DAE96526443498D6420EC3] +GoodName=Airboarder 64 (J) [b1][t1] +CRC=F255D6F1 B65D6728 +RefMD5=CCEE2FCF38DC2200128D75D15DB53283 + +[C429FE5C86F14764923F08D44884C823] +GoodName=Airboarder 64 (J) [b2] +CRC=F255D6F1 B65D6728 +RefMD5=CCEE2FCF38DC2200128D75D15DB53283 + +[16CB66DD44F7A46EEAC5FFCB38FBE26B] +GoodName=Airboarder 64 (J) [b3] +CRC=6C45B60C DCE50E30 +RefMD5=CCEE2FCF38DC2200128D75D15DB53283 + +[278EF4B79B3544DE327CF7DBCDD60081] +GoodName=Airboarder 64 (J) [f1] (PAL) +CRC=26809B20 39A516A4 +RefMD5=CCEE2FCF38DC2200128D75D15DB53283 + +[C02C32351BD69CB2D3FAC355BE074DC0] +GoodName=Airboarder 64 (J) [h1C] +CRC=6C45B60C DCE50E30 +RefMD5=CCEE2FCF38DC2200128D75D15DB53283 + +[78CABB696CA4847BFAD09B01257C6FDA] +GoodName=Airboarder 64 (J) [h2C] +CRC=6C45B60C DCE50E30 +RefMD5=CCEE2FCF38DC2200128D75D15DB53283 + +[B6894826F5386019B19F0A775D11B042] +GoodName=Airboarder 64 (J) [h3C] +CRC=6C45B60C DCE50E30 +RefMD5=CCEE2FCF38DC2200128D75D15DB53283 + +[F9027DF3909C849CBADDAB1C1468BACC] +GoodName=Airboarder 64 (J) [h4C] +CRC=6C45B60C DCE50E30 +RefMD5=CCEE2FCF38DC2200128D75D15DB53283 + +[41BE85236052A2E8EED144989B0A3E0A] +GoodName=Airboarder 64 (J) [h5C] +CRC=F255D6F1 B65D6728 +RefMD5=CCEE2FCF38DC2200128D75D15DB53283 + +[037B58EE5FB4F3BFF408EE406E3539C0] +GoodName=Airboarder 64 (J) [h6C] +CRC=6C45B60C DCE50E30 +RefMD5=CCEE2FCF38DC2200128D75D15DB53283 + +[63F850D7CC829B287FF1DC61CA3F7CCA] +GoodName=Airboarder 64 (J) [t1] +CRC=F255D6F1 B65D6728 +RefMD5=CCEE2FCF38DC2200128D75D15DB53283 + +[256A1CB23F9E1A2762A7A171417B5D68] +GoodName=Akumajou Dracula Mokushiroku - Real Action Adventure (J) [!] +CRC=B6951A94 63C849AF +Players=1 +SaveType=Eeprom 16KB +Rumble=Yes + +[47EA239717C4D225C9D0E9FD37B9FCB3] +GoodName=Akumajou Dracula Mokushiroku Gaiden - Legend of Cornell (J) [!] +CRC=A5533106 B9F25E5B +Players=1 +SaveType=Eeprom 16KB +Rumble=Yes + +[ECD127A57E25CE8514307BB47ECC1E95] +GoodName=Alienstyle Intro by Renderman (PD) [a1] +CRC=43EFB5BB D8C62E2B +Players=0 +Status=5 +SaveType=None +Rumble=No + +[232A5DC2E98C6CAB1D9F73C1D1C1C73A] +GoodName=Alienstyle Intro by Renderman (PD) +CRC=888EEC7A 42361983 +Players=0 +Status=5 +SaveType=None +Rumble=No + +[E3F4C868917A12BD5E84D94D1C260C7D] +GoodName=All Star Tennis '99 (E) (M5) [!] +CRC=DFD784AD AE426603 +Players=4 +SaveType=Eeprom 4KB +Status=4 + +[4DC614B1022252F41E4E182249FA7BAA] +GoodName=All Star Tennis '99 (E) (M5) [f1] (NTSC) +CRC=3015A8AD 8CEAF5F8 +RefMD5=E3F4C868917A12BD5E84D94D1C260C7D + +[37962CB6D58C2D6B044EAECDCF70EC09] +GoodName=All Star Tennis '99 (E) (M5) [f2] (NTSC) +CRC=6FD0035D 371B785D +RefMD5=E3F4C868917A12BD5E84D94D1C260C7D + +[E034C969BCDC2E8DBE2C8A73BED57B53] +GoodName=All Star Tennis '99 (E) (M5) [f3] (NTSC) +CRC=2E341C3D 5AC8DEA3 +RefMD5=E3F4C868917A12BD5E84D94D1C260C7D + +[7FB6422E5BBF60FEE39651EFF3F79BAB] +GoodName=All Star Tennis '99 (E) (M5) [f4] (NTSC) +CRC=F3700A53 4795C23D +RefMD5=E3F4C868917A12BD5E84D94D1C260C7D + +[AFC3DC9BB737D81903F6CE4875B63AE9] +GoodName=All Star Tennis '99 (U) [!] +CRC=E185E291 4E50766D +Players=4 +SaveType=Eeprom 4KB +Status=4 + +[A90FE01FDAFFB70DD123C0BA04589FAA] +GoodName=All Star Tennis '99 (U) [T+Bra1.0_Guto] +CRC=E185E291 4E50766D +RefMD5=AFC3DC9BB737D81903F6CE4875B63AE9 + +[A2FA12A1DEFCB152DFD04E82968C7D3A] +GoodName=All Star Tennis '99 (U) [f1] (PAL) +CRC=2D56F77B CBE813FC +RefMD5=AFC3DC9BB737D81903F6CE4875B63AE9 + +[D341A40EA9FBE95B6F0F99DFC5901FB7] +GoodName=All Star Tennis '99 (U) [f2] (PAL) +CRC=35D13E0D E8652252 +RefMD5=AFC3DC9BB737D81903F6CE4875B63AE9 + +[953B00882A99D650E1F2817674595F0B] +GoodName=All Star Tennis '99 (U) [h1C] +CRC=E185E291 4E50766D +RefMD5=AFC3DC9BB737D81903F6CE4875B63AE9 + +[ED5F1E12DA36DBEC8A0A24ED98D4AED5] +GoodName=All-Star Baseball '99 (E) [!] +CRC=D9EDD54D 6BB8E274 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +Status=3 + +[78551D23F230B58B9F449CDB4A285761] +GoodName=All-Star Baseball '99 (U) [!] +CRC=C43E23A7 40B1681A +Players=4 +SaveType=None +Mempak=Yes +Status=3 +Rumble=Yes + +[045E0B801F70ADE69981FCBB2EDE5376] +GoodName=All-Star Baseball '99 (U) [f1] (PAL) +CRC=A6421764 ED1A13E9 +RefMD5=78551D23F230B58B9F449CDB4A285761 + +[13B5AE646CC09876D64366BB07796C78] +GoodName=All-Star Baseball '99 (U) [o1] +CRC=C43E23A7 40B1681A +RefMD5=78551D23F230B58B9F449CDB4A285761 + +[90448C4175EE9D0247674474DCABDFED] +GoodName=All-Star Baseball 2000 (E) [!] +CRC=A19F8089 77884B51 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +Status=0 + +[E4076E07DBDA9CEAB5EDCEF4D4648EAB] +GoodName=All-Star Baseball 2000 (E) [f1] (NTSC) +CRC=581900E5 8E662FC8 +RefMD5=90448C4175EE9D0247674474DCABDFED + +[AADA358CE97F06C4DF5BF55987268844] +GoodName=All-Star Baseball 2000 (U) [!] +CRC=5E547A4D 90E60795 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[5D29C01B96A738C3EB68254EF40552F3] +GoodName=All-Star Baseball 2000 (U) [f1] (PAL) +CRC=44127A31 6D341229 +RefMD5=AADA358CE97F06C4DF5BF55987268844 + +[93B98D93275F803EF4C925BAE5FB711F] +GoodName=All-Star Baseball 2000 (U) [h1C] +CRC=5E547A4D 90E60795 +RefMD5=AADA358CE97F06C4DF5BF55987268844 + +[07AB7C19DBE85C8CC0961BAAF3B5CA79] +GoodName=All-Star Baseball 2000 (U) [h2C] +CRC=5E547A4D 90E60795 +RefMD5=AADA358CE97F06C4DF5BF55987268844 + +[6E01B8D425AE74EF5A0F875C700A3B18] +GoodName=All-Star Baseball 2001 (U) [!] +CRC=5446C6EF E18E47BB +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[CD04ABC5979F22EF5D6FDC4DCFAA4D50] +GoodName=All-Star Baseball 2001 (U) [f1] (PAL) +CRC=993CC742 EE65D7A4 +RefMD5=6E01B8D425AE74EF5A0F875C700A3B18 + +[9BC0E3361385713BDF50F0EEBF59FFE0] +GoodName=Alleycat 64 by Dosin (POM '99) (PD) +CRC=306B3375 05F4E698 +Players=1 +Status=3 +Rumble=No +SaveType=None + +[2DCE0F6556C00B44367586FD1EEB40E5] +GoodName=Alleycat 64 by Dosin (POM '99) (PD) [b1] +CRC=306B3375 05F4E698 +RefMD5=9BC0E3361385713BDF50F0EEBF59FFE0 + +[58B27AE9B41B755E4F9C503656B93A97] +GoodName=Analogue Test Utility by WT_Riker (POM '99) (PD) [b1] +CRC=E4C44FDA 98532F4A + +[25099EEB13E4FB47E390087EF6A20CBC] +GoodName=Analogue Test Utility by WT_Riker (POM '99) (PD) +CRC=E4C44FDA 98532F4A +Players=1 +SaveType=None +Status=5 +Rumble=No + +[0C2CBAFEC6F184AD39EF29B2B5E0F44A] +GoodName=Armorines - Project S.W.A.R.M. (E) [!] +CRC=3CC77150 21CDB987 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +Status=5 + +[0B5F909546DE5A414F2281AD0C83D9F9] +GoodName=Armorines - Project S.W.A.R.M. (E) [f1] (NTSC) +CRC=CCDEAF02 8AFC4B28 +RefMD5=0C2CBAFEC6F184AD39EF29B2B5E0F44A + +[2BC48B3E6F61896B9BC7BEF5205CC49C] +GoodName=Armorines - Project S.W.A.R.M. (G) [!] +CRC=C0F6DB17 80E0D532 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +Status=5 + +[43C23D76E4B6B1CBFCE446DFADFB0396] +GoodName=Armorines - Project S.W.A.R.M. (G) [f1] (NTSC) +CRC=2CEEE754 31B69DBE +RefMD5=2BC48B3E6F61896B9BC7BEF5205CC49C + +[6E6E7A703C131ADADDF4175E9037A2EB] +GoodName=Armorines - Project S.W.A.R.M. (U) [!] +CRC=1FB5D932 3BA9481B +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +Status=5 + +[4C15C85280DFB003C3BE6506B217B775] +GoodName=Armorines - Project S.W.A.R.M. (U) [f1] (PAL) +CRC=EA090572 192F9673 +RefMD5=6E6E7A703C131ADADDF4175E9037A2EB + +[0FDC4ACAB1B531CBB4DFB142CD630B7A] +GoodName=Armorines - Project S.W.A.R.M. (U) [t1] +CRC=E820670A A99ED0EF +RefMD5=6E6E7A703C131ADADDF4175E9037A2EB + +[755DF7F57EDF87706D4C80FF15883312] +GoodName=Army Men - Air Combat (U) [!] +CRC=4C52BBB2 CEAB0F6B +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +Status=3 + +[53E2872612760133AB7B2CC2E22B847C] +GoodName=Army Men - Sarge's Heroes (E) (M3) [!] +CRC=B210DF19 98B58D1A +CountPerOp=1 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[B8085C2EDB1C6D23E52ED8C06D92B4F8] +GoodName=Army Men - Sarge's Heroes (U) [!] +CRC=862C0657 8DFD896D +CountPerOp=1 +SaveType=None +Mempak=Yes +Players=4 +Rumble=Yes +Status=4 + +[906D5A77188A0DC90EBF294EF8A3915E] +GoodName=Army Men - Sarge's Heroes (U) [b1] +CRC=D51CF20D 5534AF93 +RefMD5=B8085C2EDB1C6D23E52ED8C06D92B4F8 + +[F1116FAEBBA932A0159B882AF9946BE6] +GoodName=Army Men - Sarge's Heroes (U) [f1] (PAL) +CRC=94123517 300EEA90 +RefMD5=B8085C2EDB1C6D23E52ED8C06D92B4F8 + +[3D1C87BCF3F8AE8E55FC87A25BE4173C] +GoodName=Army Men - Sarge's Heroes (U) [t1] +CRC=A7507855 0D454C66 +RefMD5=B8085C2EDB1C6D23E52ED8C06D92B4F8 + +[4E39474136C94CE25061FB6C0B473E29] +GoodName=Army Men - Sarge's Heroes (U) [t2] +CRC=5E23985B E3CF7CDA +RefMD5=B8085C2EDB1C6D23E52ED8C06D92B4F8 + +[A952E495077D13C8D9587B7B8BBDE2DB] +GoodName=Army Men - Sarge's Heroes (U) [t3] +CRC=5E23985B E3CF7CDA +RefMD5=B8085C2EDB1C6D23E52ED8C06D92B4F8 + +[6EEA5C4A6256092ED8F9BA8861C689C6] +GoodName=Army Men - Sarge's Heroes 2 (U) [!] +CRC=B20F73B6 2975FC34 +CountPerOp=1 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +Status=3 + +[F818FB61331122D455692C00EDB2A2FF] +GoodName=Army Men - Sarge's Heroes 2 (U) [t1] +CRC=B24303F4 9F7D2445 +RefMD5=6EEA5C4A6256092ED8F9BA8861C689C6 + +[874C7B7B365D2C20AAA1A0C90C93F9B8] +GoodName=Asteroids Hyper 64 (U) [!] +CRC=D1F7D8AB 293B0446 +Players=4 +SaveType=None +Mempak=Yes +Status=3 +Rumble=Yes + +[94751FE93510EBA2D42D82269B224CF8] +GoodName=Asteroids Hyper 64 (U) [o1] +CRC=D1F7D8AB 293B0446 +RefMD5=874C7B7B365D2C20AAA1A0C90C93F9B8 + +[48E6A629101B200A70873589B5D2F524] +GoodName=Asteroids Hyper 64 (U) [o1][f1] (PAL) +CRC=39CE39C1 04271200 +RefMD5=874C7B7B365D2C20AAA1A0C90C93F9B8 + +[00396D6B4E66D323D4AD29833A53DF74] +GoodName=Asteroids Hyper 64 (U) [o1][t1] +CRC=5638C715 5EA6181D +RefMD5=874C7B7B365D2C20AAA1A0C90C93F9B8 + +[CF63AB6AF5FBD5DBFE500DD9A658E069] +GoodName=Attax64 by Pookae (POM '99) (PD) +CRC=26E43C40 E11F283C +Players=4 +Status=3 +Rumble=No +SaveType=None + +[553037C41F9029F544353B8446BE77D9] +GoodName=Attax64 by Pookae (POM '99) (PD) [b1] +CRC=26E43C40 E11F283C +RefMD5=CF63AB6AF5FBD5DBFE500DD9A658E069 + +[7853F02DC66A35BC8C2BC33D03B8F0CA] +GoodName=Automobili Lamborghini (E) [!] +CRC=FC7797BF 4A95E83C +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +Status=4 + +[DE4631D6419B7361DE9C4A5472964D21] +GoodName=Automobili Lamborghini (E) [o1] +CRC=FC7797BF 4A95E83C +RefMD5=7853F02DC66A35BC8C2BC33D03B8F0CA + +[EC39579F066A9714FF030D07DEC3C9D3] +GoodName=Automobili Lamborghini (U) [!] +CRC=41B25DC4 1B726786 +Players=5 +SaveType=None +Mempak=Yes +Rumble=Yes +Status=4 + +[E86A022815D0B7E65FD5557F0B3451D4] +GoodName=Automobili Lamborghini (U) [T+Ita_cattivik66][b3] +CRC=41B25DC4 1B726786 +RefMD5=EC39579F066A9714FF030D07DEC3C9D3 + +[B293E449967B246451564B25A4A36BEC] +GoodName=Automobili Lamborghini (U) [T+Ita_cattivik66][b4] +CRC=41B25DC4 1B726786 +RefMD5=EC39579F066A9714FF030D07DEC3C9D3 + +[1F324E92AF23CDC5499BBC35F3840205] +GoodName=Automobili Lamborghini (U) [b1] +CRC=4DB05DC4 28DBF801 +RefMD5=EC39579F066A9714FF030D07DEC3C9D3 + +[4086114FFB03B156DBCAA0364EB0F81B] +GoodName=Automobili Lamborghini (U) [b2] +CRC=4DB05DC4 28DBF801 +RefMD5=EC39579F066A9714FF030D07DEC3C9D3 + +[D861B752F59774A5597E66E8C58E52D9] +GoodName=Automobili Lamborghini (U) [b3] +CRC=41B25DC4 1B726786 +RefMD5=EC39579F066A9714FF030D07DEC3C9D3 + +[B708601A36054FCA51D849D6D26CEC5C] +GoodName=Automobili Lamborghini (U) [b4] +CRC=DB833E34 63548286 +RefMD5=EC39579F066A9714FF030D07DEC3C9D3 + +[0D0D6A170871ED3433A52D110B01357E] +GoodName=Automobili Lamborghini (U) [b5] +CRC=41B25DC4 1B726786 +RefMD5=EC39579F066A9714FF030D07DEC3C9D3 + +[69431C0E9152A9C5B62131C034250A25] +GoodName=Automobili Lamborghini (U) [b6] +CRC=41B25DC4 1B726786 +RefMD5=EC39579F066A9714FF030D07DEC3C9D3 + +[D441BB80EFD86B8FD65CE855FEC21631] +GoodName=Automobili Lamborghini (U) [f1] +CRC=4DB05DC4 28DBF801 +RefMD5=EC39579F066A9714FF030D07DEC3C9D3 + +[4CEF5CDD83360127B0445E7A9EA0BC8F] +GoodName=Automobili Lamborghini (U) [h1C] +CRC=41B25DC4 1B726786 +RefMD5=EC39579F066A9714FF030D07DEC3C9D3 + +[DAC77D638FF03E77F569119116D4B668] +GoodName=Automobili Lamborghini (U) [h2C] +CRC=41B25DC4 1B726786 +RefMD5=EC39579F066A9714FF030D07DEC3C9D3 + +[17951444830696AAFC07F311AB128099] +GoodName=Automobili Lamborghini (U) [o1] +CRC=41B25DC4 1B726786 +RefMD5=EC39579F066A9714FF030D07DEC3C9D3 + +[8FF8B861A0D095B910DD97EB1ECC02FF] +GoodName=Automobili Lamborghini (U) [o1][T+Ita_cattivik66] +CRC=41B25DC4 1B726786 +RefMD5=EC39579F066A9714FF030D07DEC3C9D3 + +[87D7EEBD0E6B403A2022BBD84BC12868] +GoodName=Automobili Lamborghini (U) [o2] +CRC=41B25DC4 1B726786 +RefMD5=EC39579F066A9714FF030D07DEC3C9D3 + +[805F74AEF610BA2C1F6FCEF723CD1970] +GoodName=Automobili Lamborghini (U) [o3] +CRC=4DB05DC4 28DBF801 +RefMD5=EC39579F066A9714FF030D07DEC3C9D3 + +[EC9B393B3F52B76C02E3BF2AA20145A5] +GoodName=Automobili Lamborghini (U) [o4] +CRC=41B25DC4 1B726786 +RefMD5=EC39579F066A9714FF030D07DEC3C9D3 + +[4E730D045AC33A64BA97D5672589C6C7] +GoodName=Automobili Lamborghini (U) [o5] +CRC=41B25DC4 1B726786 +RefMD5=EC39579F066A9714FF030D07DEC3C9D3 + +[8E2F186FC1B86ABC1CC04FFE1845C6AC] +GoodName=Automobili Lamborghini (U) [o6] +CRC=DB833E34 63548286 +RefMD5=EC39579F066A9714FF030D07DEC3C9D3 + +[835E98C0B8A16401BDC6653E8855F0D6] +GoodName=Automobili Lamborghini (U) [o7] +CRC=41B25DC4 1B726786 +RefMD5=EC39579F066A9714FF030D07DEC3C9D3 + +[0AD7111C5DB3CA075DCD5AC9838C3B24] +GoodName=Automobili Lamborghini (U) [o7][T+Ita_cattivik66] +CRC=41B25DC4 1B726786 +RefMD5=EC39579F066A9714FF030D07DEC3C9D3 + +[A6836524B4E71E5AD14DD8C3651665AD] +GoodName=Automobili Lamborghini (U) [t1] +CRC=DB833E34 63548286 +RefMD5=EC39579F066A9714FF030D07DEC3C9D3 + +[3B4330445D9AAE1EF9C56B1393E281E3] +GoodName=BB SRAM Manager (PD) +CRC=4E5507F2 E7D3B413 + +[8222D1129394AB4F382476D8231EF9F6] +GoodName=BMP View by Count0 (PD) +CRC=273433C0 02B1F61B + +[8183688A4B7D0A390496B5655BCD252E] +GoodName=Baku Bomberman (J) [!] +CRC=E340A49C 74318D41 +SaveType=Eeprom 4KB +Players=4 +Mempak=Yes + +[70415D917D5B7BEEFEDAFDB65CD64D43] +GoodName=Baku Bomberman (J) [b1] +CRC=E340A49C 74318D41 +RefMD5=8183688A4B7D0A390496B5655BCD252E + +[5259F6331389F6AF55B867F60AA373C8] +GoodName=Baku Bomberman (J) [h1C] +CRC=E340A49C 74318D41 +RefMD5=8183688A4B7D0A390496B5655BCD252E + +[70632EE119E54F76A344A7B04340A6F9] +GoodName=Baku Bomberman (J) [t1] +CRC=3A595B0E F8788AA6 +RefMD5=8183688A4B7D0A390496B5655BCD252E + +[CA956015B6820DCFF1C814F3532E18B1] +GoodName=Baku Bomberman 2 (J) [!] +CRC=E73C7C4F AF93B838 +SaveType=Eeprom 4KB +Players=4 +Mempak=Yes +Rumble=Yes + +[8107825AC2A522057422463ED81E276B] +GoodName=Bakuretsu Muteki Bangai-O (J) [!] +CRC=DF98B95D 58840978 +Players=1 +Rumble=Yes + +[A78517540876AE94C2027FE260633CA8] +GoodName=Bakuretsu Muteki Bangai-O (J) [f1] (PAL) +CRC=0866BEDD AE31C2EE +RefMD5=8107825AC2A522057422463ED81E276B + +[040538EA3C225D1E7F2497ACEFDE8CD0] +GoodName=Bakuretsu Muteki Bangai-O (J) [h1C] +CRC=DF98B95D 58840978 +RefMD5=8107825AC2A522057422463ED81E276B + +[09FD63AFA1156405E618752FC583DF93] +GoodName=Bakushou Jinsei 64 - Mezase! Resort Ou (J) [!] +CRC=88CF980A 8ED52EB5 +Players=4 +Mempak=Yes + +[E16CFE9268E472A7814C58783AE7D3A2] +GoodName=Bakushou Jinsei 64 - Mezase! Resort Ou (J) [h1C] +CRC=88CF980A 8ED52EB5 +RefMD5=09FD63AFA1156405E618752FC583DF93 + +[3D3855A86FD5A1B4D30BEB0F5A4A85AF] +GoodName=Banjo to Kazooie no Daibouken (J) [!] +CRC=5168D520 CA5FCD0D +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[7FDAFD3252C0F59FFBA59CD42729D959] +GoodName=Banjo to Kazooie no Daibouken (J) [f1] +CRC=18439105 60424C9E +RefMD5=3D3855A86FD5A1B4D30BEB0F5A4A85AF + +[89BBBB739E54721F77F1A6441C00C093] +GoodName=Banjo to Kazooie no Daibouken (J) [f2] +CRC=18439105 60424C9E +RefMD5=3D3855A86FD5A1B4D30BEB0F5A4A85AF + +[B49EC888940FAB43651E48F760BF7BBD] +GoodName=Banjo to Kazooie no Daibouken (J) [f3] +CRC=18439105 60424C9E +RefMD5=3D3855A86FD5A1B4D30BEB0F5A4A85AF + +[715A8816F30FA24B8D174DC5CB6F25A9] +GoodName=Banjo to Kazooie no Daibouken 2 (J) [!] +CRC=514B6900 B4B19881 +SaveType=Eeprom 16KB +Players=4 +Rumble=Yes + +[06A43BACF5C0687F596DF9B018CA6D7F] +GoodName=Banjo-Kazooie (E) (M3) [!] +CRC=733FCCB1 444892F9 +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[5FC8116DAFDEC73DE9C5CCC2D8E14B4F] +GoodName=Banjo-Kazooie (E) (M3) [f1] +CRC=192C1422 5B8CFF48 +RefMD5=06A43BACF5C0687F596DF9B018CA6D7F + +[F81C314B04CEE9DC92FD4D50811F6FBB] +GoodName=Banjo-Kazooie (E) (M3) [f2] +CRC=192C15DA 74BD6300 +RefMD5=06A43BACF5C0687F596DF9B018CA6D7F + +[B29599651A13F681C9923D69354BF4A3] +GoodName=Banjo-Kazooie (U) (V1.0) [!] +CRC=A4BF9306 BF0CDFD1 +SaveType=Eeprom 4KB +Players=1 +Rumble=Yes + +[8E870036E7A40BA42803C333A412EFE7] +GoodName=Banjo-Kazooie (U) (V1.0) [b1] +CRC=A4BF9306 BF0CDFD1 +RefMD5=B29599651A13F681C9923D69354BF4A3 + +[63609225DA40E2BAEC425F4AEB365330] +GoodName=Banjo-Kazooie (U) (V1.0) [b2] +CRC=A4BF9306 BF0CDFD1 +RefMD5=B29599651A13F681C9923D69354BF4A3 + +[880BB39F8B31C087D66F7193D3528EFE] +GoodName=Banjo-Kazooie (U) (V1.0) [b3] +CRC=A4BF9306 BF0CDFD1 +RefMD5=B29599651A13F681C9923D69354BF4A3 + +[6E3FBAF95C79A3668B6A9211F1372216] +GoodName=Banjo-Kazooie (U) (V1.0) [b4] +CRC=16EDC447 B291F183 +RefMD5=B29599651A13F681C9923D69354BF4A3 + +[508B2D76887E3FE169B60B6CF70E6DBA] +GoodName=Banjo-Kazooie (U) (V1.0) [b5] +CRC=A4BF9306 BF0CDFD1 +RefMD5=B29599651A13F681C9923D69354BF4A3 + +[4782CA6F893AA03F701D6EDA7552711B] +GoodName=Banjo-Kazooie (U) (V1.0) [b6] +CRC=FEF9D364 FBD6D06E +RefMD5=B29599651A13F681C9923D69354BF4A3 + +[B6BC123E51AE5C3190BCA41CFC1D637F] +GoodName=Banjo-Kazooie (U) (V1.0) [b7] +CRC=A4BF9306 BF0CDFD1 +RefMD5=B29599651A13F681C9923D69354BF4A3 + +[F9E8FEF0005E26720EB0D0FDFAB7A859] +GoodName=Banjo-Kazooie (U) (V1.0) [f1] +CRC=16EDC447 B291F183 +RefMD5=B29599651A13F681C9923D69354BF4A3 + +[7173250DC66CA58024C1C4D27B0F8720] +GoodName=Banjo-Kazooie (U) (V1.0) [t1] +CRC=16EDC447 B291F183 +RefMD5=B29599651A13F681C9923D69354BF4A3 + +[B11F476D4BC8E039355241E871DC08CF] +GoodName=Banjo-Kazooie (U) (V1.1) [!] +CRC=CD7559AC B26CF5AE +RefMD5=B29599651A13F681C9923D69354BF4A3 + +[61B5C5C3E5E1A81E5D37072C01B39B76] +GoodName=Banjo-Tooie (A) [!] +CRC=155B7CDF F0DA7325 +SaveType=Eeprom 16KB +Players=4 +Rumble=Yes + +[8B2E56F18421A67BCA861427453A1E19] +GoodName=Banjo-Tooie (E) (M4) [!] +CRC=C9176D39 EA4779D1 +SaveType=Eeprom 16KB +Players=4 +Rumble=Yes + +[40E98FAA24AC3EBE1D25CB5E5DDF49E4] +GoodName=Banjo-Tooie (U) [!] +CRC=C2E9AA9A 475D70AA +SaveType=Eeprom 16KB +Players=4 +Rumble=Yes + +[BF3E84CDD01CAC05987FD8DA5191534B] +GoodName=Bass Hunter 64 (E) [!] +CRC=B088FBB4 441E4B1D +Players=1 +SaveType=Eeprom 4KB +CountPerOp=1 +Rumble=Yes + +[2C618F6C69C3B4803F08762A03835139] +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] +CRC=D76333AC 0CB6219D +RefMD5=2C618F6C69C3B4803F08762A03835139 + +[1F997B26062B7D59F23193F448157EE3] +GoodName=Bass Rush - ECOGEAR PowerWorm Championship (J) [b2] +CRC=D76333AC 0CB6219D +RefMD5=2C618F6C69C3B4803F08762A03835139 + +[930C7F6E5863471DDE1816D28A10EB88] +GoodName=Bassmasters 2000 (U) [!] +CRC=BCFACCAA B814D8EF +Players=4 +SaveType=None +Mempak=Yes +CountPerOp=1 +Rumble=Yes + +[D8903586B5E479E6C4937879650D0D2D] +GoodName=Bassmasters 2000 (U) [b1] +CRC=BCFACCAA B814D8EF +RefMD5=930C7F6E5863471DDE1816D28A10EB88 + +[342476D20D7A7BF4C5484D2DEFCC79E7] +GoodName=Bassmasters 2000 (U) [f1] (PAL) +CRC=DC41E81E AC36CAD1 +RefMD5=930C7F6E5863471DDE1816D28A10EB88 + +[A08676124B326B1035B202C83A97468F] +GoodName=Batman Beyond - Return of the Joker (U) [!] +CRC=204489C1 1286CF2B +Players=1 +SaveType=None +Rumble=Yes + +[E4498D8FE11A6E0CC0737D89361DE097] +GoodName=Batman Beyond - Return of the Joker (U) [o1] +CRC=204489C1 1286CF2B +Players=1 +SaveType=None +Rumble=Yes + +[1C7FA31271E5588C968675E932C08991] +GoodName=Batman Beyond - Return of the Joker (U) [o1][t1] +CRC=D8928E46 965CE432 +RefMD5=E4498D8FE11A6E0CC0737D89361DE097 + +[A5EE8A6C34863E3D0EB8C06AE8668B30] +GoodName=Batman of the Future - Return of the Joker (E) (M3) [!] +CRC=259F7F84 7C9EED26 +Players=1 +SaveType=None +Rumble=Yes + +[F5C9B6E4DB938258EA277670B6D37F16] +GoodName=Batman of the Future - Return of the Joker (E) (M3) [b1] +CRC=259F7F84 7C9EED26 +RefMD5=A5EE8A6C34863E3D0EB8C06AE8668B30 + +[8743BDDE07A2E9E0E5A0792D7D8678CB] +GoodName=Batman of the Future - Return of the Joker (E) (M3) [o1] +CRC=259F7F84 7C9EED26 +RefMD5=A5EE8A6C34863E3D0EB8C06AE8668B30 + +[3406A505C22BAC2F40D9BFC6FF08CF86] +GoodName=BattleTanx (U) [!] +CRC=6AA4DDE7 E3E2F4E7 +CountPerOp=3 +SaveType=None +Mempak=Yes +Players=4 +Rumble=Yes + +[94A7605A28861C43F636AE0FF7F25F2E] +GoodName=BattleTanx (U) [b1] +CRC=6AA4DDE7 E3E2F4E7 +RefMD5=3406A505C22BAC2F40D9BFC6FF08CF86 + +[722D55C70368323D79AB1B63696A45E4] +GoodName=BattleTanx (U) [b1][t1] +CRC=3D615CF5 6984930A +RefMD5=3406A505C22BAC2F40D9BFC6FF08CF86 + +[EDD7187C79CEBDB0D1FABC040502E940] +GoodName=BattleTanx (U) [f1] (PAL) +CRC=9A75C9C2 A4488353 +RefMD5=3406A505C22BAC2F40D9BFC6FF08CF86 + +[220B85771E64C554514163120C2F82F4] +GoodName=BattleTanx (U) [t1] +CRC=3D615CF5 6984930A +RefMD5=3406A505C22BAC2F40D9BFC6FF08CF86 + +[D6E667FE10AFE8F7116888EFDE98AE0E] +GoodName=BattleTanx - Global Assault (E) (M3) [!] +CRC=0CAD17E6 71A5B797 +CountPerOp=1 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[654557C316F901A2CA6F7F4B43343147] +GoodName=BattleTanx - Global Assault (U) [!] +CRC=75A4E247 6008963D +CountPerOp=3 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[DC5AAE1CADF43DF43184D2935C32C26C] +GoodName=BattleTanx - Global Assault (U) [f1] (Country Check) +CRC=8A2E80DC 00F61BE4 +RefMD5=D6E667FE10AFE8F7116888EFDE98AE0E + +[D6D30577E6E8341495B7D8066035C21D] +GoodName=BattleTanx - Global Assault (U) [f2] (PAL) +CRC=90111D7E E4B49428 +RefMD5=D6E667FE10AFE8F7116888EFDE98AE0E + +[266C0989ED0929DF499389954779EA97] +GoodName=Battlezone - Rise of the Black Dogs (U) [!] +CRC=55D4C4CE 7753C78A +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[A94135D163E6091C960ADC918C1FB8A7] +GoodName=Beetle Adventure Racing! (E) (M3) [!] +CRC=A1B64A61 D014940B +Players=4 +SaveType=None +Mempak=Yes +CountPerOp=3 +Rumble=Yes + +[9D5A1B779F8B43E63E8CE8427675A7EF] +GoodName=Beetle Adventure Racing! (E) (M3) [h1C] +CRC=A1B64A61 D014940B +RefMD5=A94135D163E6091C960ADC918C1FB8A7 + +[6B4398CE56A9C4786F2087F681FFFAF3] +GoodName=Beetle Adventure Racing! (E) (M3) [t1] +CRC=59445C71 1F1FE699 +RefMD5=A94135D163E6091C960ADC918C1FB8A7 + +[5FFD43089B7334072B2B74421618D973] +GoodName=Beetle Adventure Racing! (J) [!] +CRC=9C7318D2 24AE0DC1 +Players=4 +SaveType=None +Mempak=Yes +CountPerOp=3 +Rumble=Yes + +[E126B84FA242916289D04D68C0E20BFE] +GoodName=Beetle Adventure Racing! (J) [b1] +CRC=9C7318D2 24AE0DC1 +RefMD5=5FFD43089B7334072B2B74421618D973 + +[CF97C336479DDBF1217E4DDE89D9D2D3] +GoodName=Beetle Adventure Racing! (U) (M3) [!] +CRC=EDF419A8 BF1904CC +SaveType=None +Mempak=Yes +Players=4 +CountPerOp=3 +Rumble=Yes + +[D11BC38F26EA2835FBF017FE9BD404FE] +GoodName=Beetle Adventure Racing! (U) (M3) [b1] +CRC=EDF419A8 BF1904CC +RefMD5=CF97C336479DDBF1217E4DDE89D9D2D3 + +[40CBC5A23B7D8C1FDD47D78CACA29248] +GoodName=Beetle Adventure Racing! (U) (M3) [b2] +CRC=EDF419A8 BF1904CC +RefMD5=CF97C336479DDBF1217E4DDE89D9D2D3 + +[CC9F8A2181C6C9C5ED49B77FF632395A] +GoodName=Beetle Adventure Racing! (U) (M3) [f1] (PAL) +CRC=1E17A377 9D8C5E86 +RefMD5=CF97C336479DDBF1217E4DDE89D9D2D3 + +[EFFB7B42C6D7C29540C93006E6142F99] +GoodName=Beetle Adventure Racing! (U) (M3) [t1] +CRC=559A0FD3 897F777C +RefMD5=CF97C336479DDBF1217E4DDE89D9D2D3 + +[C246BD299AA756459193F406A261D1D1] +GoodName=Beetle Adventure Racing! (U) (M3) [t2] +CRC=522409D3 9340EBFF +RefMD5=CF97C336479DDBF1217E4DDE89D9D2D3 + +[AD7C7B994994CF56481E4450E958049F] +GoodName=Berney Must Die! by Nop_ (POM '99) (PD) +CRC=3A089BBC 54AB2C06 +Status=0 +SaveType=None +Mempak=Yes + +[108A605E3D57A5E5C52398B675861EF4] +GoodName=Berney Must Die! by Nop_ (POM '99) (PD) [t1] +CRC=861F9BDC C3353C85 +RefMD5=AD7C7B994994CF56481E4450E958049F + +[BF6780E2982C16D4A4FDB553BE8F9226] +GoodName=Big Mountain 2000 (U) [!] +CRC=08FFA4B7 01F453B6 +SaveType=Eeprom 4KB +Players=2 +Rumble=Yes +Mempak=Yes + +[CFE3E75B8B4C75F231CBBD9C99804EC3] +GoodName=Big Mountain 2000 (U) [t1] +CRC=B0119B37 B9774FD5 +RefMD5=BF6780E2982C16D4A4FDB553BE8F9226 + +[0059B65E1C813BC8BD1A61A1FE009CCD] +GoodName=Bike Race '98 V1.0 by NAN (PD) +CRC=713FDDD3 72D6A0EF +Players=1 +Status=2 +SaveType=None +Rumble=No + +[A1025E61229D5D855D232210B39F5E66] +GoodName=Bike Race '98 V1.0 by NAN (PD) [b1] +CRC=713FDDD3 72D6A0EF +RefMD5=0059B65E1C813BC8BD1A61A1FE009CCD + +[1CCD7DB5B3F57944CAF7DA86EF1763E3] +GoodName=Bike Race '98 V1.2 by NAN (PD) +CRC=F4B64159 46FC16CF +Players=1 +Status=2 +SaveType=None +Rumble=No + +[58B2716389BA3C5575B5A287E59F49AF] +GoodName=Bike Race '98 V1.2 by NAN (PD) [b1] +CRC=F4B64159 46FC16CF +RefMD5=1CCD7DB5B3F57944CAF7DA86EF1763E3 + +[133B6615CD0936AC705DFC81E4389CBB] +GoodName=Bike Race '98 V1.2 by NAN (PD) [b2] +CRC=F4B64159 46FC16CF +RefMD5=1CCD7DB5B3F57944CAF7DA86EF1763E3 + +[42672BA5E98CD21D7F3E3745E69038DD] +GoodName=Bio F.R.E.A.K.S. (E) [!] +CRC=AB7C101D EC58C8B0 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[0F412C4CDE69AE41B89D390731D34F71] +GoodName=Bio F.R.E.A.K.S. (E) [b1] +CRC=AB7C101D EC58C8B0 +RefMD5=42672BA5E98CD21D7F3E3745E69038DD + +[B90AB8F7605D971CC7A6D9BA5E67D1AF] +GoodName=Bio F.R.E.A.K.S. (U) [!] +CRC=08123595 0510F1DE +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[801ECC49DAF04FBA099C6F75A06F0454] +GoodName=Bio F.R.E.A.K.S. (U) [b1] +CRC=08123595 0510F1DE +RefMD5=B90AB8F7605D971CC7A6D9BA5E67D1AF + +[F64B263F67ACA5DE1957299FD92FB35A] +GoodName=Bio F.R.E.A.K.S. (U) [b2] +CRC=08123595 0510F1DE +RefMD5=B90AB8F7605D971CC7A6D9BA5E67D1AF + +[3F2802F12058B4511A0778A891050297] +GoodName=Bio F.R.E.A.K.S. (U) [b3] +CRC=B6223A7B 2139CEA6 +RefMD5=B90AB8F7605D971CC7A6D9BA5E67D1AF + +[E02AEF75AC059FC2446BFFDD06EE64A9] +GoodName=Bio F.R.E.A.K.S. (U) [h1C] +CRC=08123595 0510F1DE +RefMD5=B90AB8F7605D971CC7A6D9BA5E67D1AF + +[879A085B07B7E6D52DFE2CE636D7A239] +GoodName=Bio F.R.E.A.K.S. (U) [t1] +CRC=B6223A7B 2139CEA6 +RefMD5=B90AB8F7605D971CC7A6D9BA5E67D1AF + +[F77D70959222276491222F31EBFF3BF1] +GoodName=Biohazard 2 (J) [!] +CRC=7EAE2488 9D40A35A +SaveType=SRAM +Players=1 +CountPerOp=1 +Rumble=Yes + +[13D7834291A311077B84B9A2816AF6FC] +GoodName=Birthday Demo for Steve by Nep (PD) [b1] +CRC=C2B35C2F 5CD995A2 + +[4443B11C457348B0B6B64650909F0143] +GoodName=Birthday Demo for Steve by Nep (PD) +CRC=C2B35C2F 5CD995A2 + +[889D4D337AD11CE94357511C725EAB6A] +GoodName=Blast Corps (E) (M2) [!] +CRC=7C64E6DB 55B924DB +Players=1 +SaveType=Eeprom 4KB +Mempak=Yes + +[7C9C000B61BF0BCF81AFD4E583EC9B2A] +GoodName=Blast Corps (E) (M2) [b1] +CRC=7C64E6DB 55B924DB +RefMD5=889D4D337AD11CE94357511C725EAB6A + +[36C97C12DDABB02D7D2D3F6B33B3D83F] +GoodName=Blast Corps (E) (M2) [b2] +CRC=7C64E6DB 55B924DB +RefMD5=889D4D337AD11CE94357511C725EAB6A + +[A8DFDFF49144627492DA9B0B65B91845] +GoodName=Blast Corps (U) (V1.0) [!] +CRC=7C647C25 D9D901E6 +Players=1 +SaveType=Eeprom 4KB +Mempak=Yes + +[000E40366ECE225565D3EC83BE7D97A4] +GoodName=Blast Corps (U) (V1.0) [b1] +CRC=7C647C25 D9D901E6 +RefMD5=A8DFDFF49144627492DA9B0B65B91845 + +[4BFB72FC9A787543323ADEFC8EC2A042] +GoodName=Blast Corps (U) (V1.0) [b2] +CRC=7C647C25 D9D901E6 +RefMD5=A8DFDFF49144627492DA9B0B65B91845 + +[5875FC73069077C93E214233B60F0BDC] +GoodName=Blast Corps (U) (V1.1) [!] +CRC=7C647E65 1948D305 +Players=1 +SaveType=Eeprom 4KB +Mempak=Yes + +[16B82D53D7F038A8FE67A78027720516] +GoodName=Blast Dozer (J) [!] +CRC=65234451 EBD3346F +Players=1 +SaveType=Eeprom 4KB +Mempak=Yes + +[FA3A5597012B710C844682DA586A62C9] +GoodName=Blast Dozer (J) [b1] +CRC=65234451 EBD3346F +RefMD5=16B82D53D7F038A8FE67A78027720516 + +[31B4A8ED52B48E756B344C9F22736E50] +GoodName=Blues Brothers 2000 (E) (M6) [!] +CRC=D571C883 822D3FCF +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[997FD8F79CD6F3CD1C1C1FD21E358717] +GoodName=Blues Brothers 2000 (U) [!] +CRC=7CD08B12 1153FF89 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[96D5910A6FFD3EE53638251ACE86E0CB] +GoodName=Blues Brothers 2000 (U) [f1] (PAL-NTSC) +CRC=A9A17EF3 AB1F8703 +RefMD5=997FD8F79CD6F3CD1C1C1FD21E358717 + +[A6E03FA194A2932D36E0A67F9F64D92E] +GoodName=Blues Brothers 2000 (U) [t1] +CRC=A0976BE9 FF41562B +RefMD5=997FD8F79CD6F3CD1C1C1FD21E358717 + +[A8D31D9715BB5645EFC3245A6497F542] +GoodName=Blues Brothers 2000 (U) [t1][f1] (PAL-NTSC) +CRC=ABB57137 960F561D +RefMD5=997FD8F79CD6F3CD1C1C1FD21E358717 + +[B27FA5E9AD0CB47BB3A74FFAC7BC8EDF] +GoodName=Body Harvest (E) (M3) [!] +CRC=0B58B8CD B7B291D2 +SaveType=Eeprom 4KB +Players=1 +CountPerOp=1 +Rumble=Yes + +[0EF2448C243F86C4C9F194F49CFD8352] +GoodName=Body Harvest (E) (M3) [f1] (NTSC) +CRC=6F66B92D 80B9E520 +RefMD5=B27FA5E9AD0CB47BB3A74FFAC7BC8EDF + +[3B8585ED03E8DDB89D7DE456317545E7] +GoodName=Body Harvest (U) [!] +CRC=5326696F FE9A99C3 +Players=1 +SaveType=Eeprom 4KB +CountPerOp=1 +Rumble=Yes + +[77554810629D4EF4D93519745FA6066B] +GoodName=Body Harvest (U) [b1] +CRC=5326696F FE9A99C3 +RefMD5=3B8585ED03E8DDB89D7DE456317545E7 + +[D266B288829193BD8205DDDCDFA5CF30] +GoodName=Body Harvest (U) [b1][t1] +CRC=C535091F D60CCF6C +RefMD5=3B8585ED03E8DDB89D7DE456317545E7 + +[13532519CBC43BFA638FD5A7754EE281] +GoodName=Body Harvest (U) [b2] +CRC=00A46EE3 554158C6 +RefMD5=3B8585ED03E8DDB89D7DE456317545E7 + +[D8BD69AEE8246A3127A58E202D447BA1] +GoodName=Body Harvest (U) [t1] +CRC=C535091F D60CCF6C +RefMD5=3B8585ED03E8DDB89D7DE456317545E7 + +[1CF31E7F6E0DEB2C18C39DDD4EED9E51] +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] +CRC=B3D451C6 E1CB58E2 +RefMD5=1CF31E7F6E0DEB2C18C39DDD4EED9E51 + +[E627B898A7692C08B595A8D2178E34A0] +GoodName=Bokujou Monogatari 2 (J) (V1.1) [!] +CRC=7365D8F8 9ED9326F +RefMD5=1CF31E7F6E0DEB2C18C39DDD4EED9E51 + +[24E3EE6A54278DB65C463804F2BB6223] +GoodName=Bokujou Monogatari 2 (J) (V1.2) [!] +CRC=736657F6 3C88A702 +RefMD5=1CF31E7F6E0DEB2C18C39DDD4EED9E51 + +[B68F49AA8F6F7499184AC6B7B8570F2B] +GoodName=Bomberman 64 (E) [!] +CRC=5A160336 BC7B37B0 +Players=4 +SaveType=Eeprom 4KB +Mempak=Yes + +[B9E6A38B28108E4D6E6A0A47BF981747] +GoodName=Bomberman 64 (E) [b1] +CRC=5A160336 BC7B37B0 +RefMD5=B68F49AA8F6F7499184AC6B7B8570F2B + +[4D5C42B239DFD67E40D4E9476A208A1E] +GoodName=Bomberman 64 (E) [b2] +CRC=5A160336 BC7B37B0 +RefMD5=B68F49AA8F6F7499184AC6B7B8570F2B + +[0283CC125AEA29EF72A03BEE7D759C5D] +GoodName=Bomberman 64 (E) [h1C] +CRC=5A160336 BC7B37B0 +RefMD5=B68F49AA8F6F7499184AC6B7B8570F2B + +[9976833301116D0CB9E278E857921BF6] +GoodName=Bomberman 64 (E) [t1] +CRC=938CA401 43339F1B +RefMD5=B68F49AA8F6F7499184AC6B7B8570F2B + +[093058ECE14C8CC1A887B2087EB5CFE9] +GoodName=Bomberman 64 (U) [!] +CRC=F568D51E 7E49BA1E +Players=4 +SaveType=Eeprom 4KB +Mempak=Yes + +[BB4C5769EED69362F1A90A2BE19998D6] +GoodName=Bomberman 64 (U) [b1] +CRC=F568D51E 7E49BA1E +RefMD5=093058ECE14C8CC1A887B2087EB5CFE9 + +[FA4347AC05BC0C0BBC8CABE3ED90B8A4] +GoodName=Bomberman 64 (U) [o1] +CRC=F568D51E 7E49BA1E +RefMD5=093058ECE14C8CC1A887B2087EB5CFE9 + +[567B8914E0642721408D46627E36003B] +GoodName=Bomberman 64 - Arcade Edition (J) [f1] (PAL) +CRC=DF6FF0F4 29D14238 +RefMD5=08E491F87445C6E5C168D982FC665D5F + +[852E8651D6C610CE593C35CEA678C9F1] +GoodName=Bomberman 64 - Arcade Edition (J) [f2] (PAL-CRC) +CRC=E87F1ACE 809F204B +RefMD5=08E491F87445C6E5C168D982FC665D5F + +[08E491F87445C6E5C168D982FC665D5F] +GoodName=Bomberman 64 - Arcade Edition (J) [!] +CRC=DF6FF0F4 29D14238 +Players=4 + +[AEC1FDB0F1CAAD86C9F457989A4CE482] +GoodName=Bomberman 64 - The Second Attack! (U) [!] +CRC=237E73B4 D63B6B37 +Players=4 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[9058970DDF26431A4DAF353C2EEA86AB] +GoodName=Bomberman 64 - The Second Attack! (U) [t1][f1] (PAL-NTSC) +CRC=9BA3E5CC EB222304 +RefMD5=AEC1FDB0F1CAAD86C9F457989A4CE482 + +[F79EF0813157880FFBAD6199E07579BE] +GoodName=Bomberman Hero (E) [!] +CRC=D85C4E29 88E276AF +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[EA6D0EBD673A66C395569A2A230AEA6F] +GoodName=Bomberman Hero (E) [b1] +CRC=D85C4E29 88E276AF +RefMD5=F79EF0813157880FFBAD6199E07579BE + +[141430D034C16FC4B4BA20D53EAB61C1] +GoodName=Bomberman Hero (E) [b2] +CRC=D85C4E29 88E276AF +RefMD5=F79EF0813157880FFBAD6199E07579BE + +[8A8E73D70CBC902CD99C7A4E2B982778] +GoodName=Bomberman Hero (E) [b3] +CRC=D85C4E29 88E276AF +RefMD5=F79EF0813157880FFBAD6199E07579BE + +[008710F628C29D69BD939066A44AB877] +GoodName=Bomberman Hero (E) [f1] (NTSC) +CRC=D85C4E29 88E276AF +RefMD5=F79EF0813157880FFBAD6199E07579BE + +[EF2453BFF7AD0C4BFA9AB0BD6324EBF3] +GoodName=Bomberman Hero (U) [!] +CRC=4446FDD6 E3788208 +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[5642E51D746F603DFE5A71C5CBDB5C73] +GoodName=Bomberman Hero (U) [b1] +CRC=4446FDD6 E3788208 +RefMD5=EF2453BFF7AD0C4BFA9AB0BD6324EBF3 + +[1143B49D788BA477DAE98C05D6623344] +GoodName=Bomberman Hero (U) [b2] +CRC=DA573DB9 9442D273 +RefMD5=EF2453BFF7AD0C4BFA9AB0BD6324EBF3 + +[1BCED1BA1BF5A0E2FF5768C714EE4627] +GoodName=Bomberman Hero (U) [b3] +CRC=DA573DB9 9442D273 +RefMD5=EF2453BFF7AD0C4BFA9AB0BD6324EBF3 + +[8A0479714259954BAE41D5275AC926F4] +GoodName=Bomberman Hero (U) [t1] +CRC=DA573DB9 9442D273 +RefMD5=EF2453BFF7AD0C4BFA9AB0BD6324EBF3 + +[EE273763C7391458865FF26C7EA0C3F1] +GoodName=Bomberman Hero - Mirian Oujo wo Sukue! (J) [!] +CRC=67FF12CC 76BF0212 +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[E7D3A4A73D373DA534A025E99B4D0EEF] +GoodName=Bomberman Hero - Mirian Oujo wo Sukue! (J) [b1] +CRC=67FF12CC 76BF0212 +RefMD5=EE273763C7391458865FF26C7EA0C3F1 + +[8FA5E55E5597E2615F81CD236DCA4721] +GoodName=Bomberman Hero - Mirian Oujo wo Sukue! (J) [b2] +CRC=DDEF1333 E7209D07 +RefMD5=EE273763C7391458865FF26C7EA0C3F1 + +[F39476591E147906291BA48145F304B0] +GoodName=Bomberman Hero - Mirian Oujo wo Sukue! (J) [b3] +CRC=DDEF1333 E7209D07 +RefMD5=EE273763C7391458865FF26C7EA0C3F1 + +[49E9C7AACF839E46EA2D255A99FB2613] +GoodName=Bomberman Hero - Mirian Oujo wo Sukue! (J) [b4] +CRC=67FF12CC 76BF0212 +RefMD5=EE273763C7391458865FF26C7EA0C3F1 + +[D4806CD9D9DFC7E52D6F825B5D5CC7C2] +GoodName=Bomberman Hero - Mirian Oujo wo Sukue! (J) [b5] +CRC=DDEF1333 E7209D07 +RefMD5=EE273763C7391458865FF26C7EA0C3F1 + +[30194320B54FF67CB0CDA5DDB061D933] +GoodName=Bomberman Hero - Mirian Oujo wo Sukue! (J) [b6] +CRC=DDEF1333 E7209D07 +RefMD5=EE273763C7391458865FF26C7EA0C3F1 + +[2C68A2D12C1EBFA2AD8F0BE1A09AEEE7] +GoodName=Bomberman Hero - Mirian Oujo wo Sukue! (J) [b7] +CRC=67FF12CC 76BF0212 +RefMD5=EE273763C7391458865FF26C7EA0C3F1 + +[4022B2A0F22218870764CDAE73580762] +GoodName=Bomberman Hero - Mirian Oujo wo Sukue! (J) [b8] +CRC=DDEF1333 E7209D07 +RefMD5=EE273763C7391458865FF26C7EA0C3F1 + +[A12B361F9D38FDFE3183C2B4C1F2F217] +GoodName=Bomberman Hero - Mirian Oujo wo Sukue! (J) [o1] +CRC=67FF12CC 76BF0212 +RefMD5=EE273763C7391458865FF26C7EA0C3F1 + +[C4543F27B4E481D0818B51036B67DFEF] +GoodName=Bomberman Hero - Mirian Oujo wo Sukue! (J) [t1] +CRC=DDEF1333 E7209D07 +RefMD5=EE273763C7391458865FF26C7EA0C3F1 + +[B5772A2827BEFC81E107AE756B36BB2A] +GoodName=Boot Emu by Jovis (PD) +CRC=2D15DC8C D3BBDB52 + +[FB19AFD5E8C49978E6E6AE3622E0498A] +GoodName=Bottom of the 9th (U) [!] +CRC=D72FD14D 1FED32C4 +SaveType=None +Mempak=Yes +Players=2 +CountPerOp=1 + +[6E207C47FAAD2A4F64AE721A3A8F6161] +GoodName=Bottom of the 9th (U) [b1] +CRC=D72FD14D 1FED32C4 +RefMD5=FB19AFD5E8C49978E6E6AE3622E0498A + +[62E92102D6FD1701A6E904DA6AB58AE8] +GoodName=Brunswick Circuit Pro Bowling (U) [!] +CRC=1E22CF2E 42AAC813 +Players=4 +SaveType=None +Mempak=Yes + +[14D070077D70C94CBB1413C7641E7272] +GoodName=Brunswick Circuit Pro Bowling (U) [b1] +CRC=91644B9F 8CDD0DA5 +RefMD5=62E92102D6FD1701A6E904DA6AB58AE8 + +[2D30FBE45C2858957F9EFDB5E9000033] +GoodName=Brunswick Circuit Pro Bowling (U) [o1] +CRC=1E22CF2E 42AAC813 +RefMD5=62E92102D6FD1701A6E904DA6AB58AE8 + +[C3A55D506E5BD011EC20F601EA2B33BB] +GoodName=Brunswick Circuit Pro Bowling (U) [o1][f1] (PAL) +CRC=91644B9F 8CDD0DA5 +RefMD5=62E92102D6FD1701A6E904DA6AB58AE8 + +[A2E4BE02876CB0F0D1E925FF95090C96] +GoodName=Buck Bumble (E) (M5) [!] +CRC=D5B2339C CABCCAED +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[AEE981977D8F069003574CD10A268D47] +GoodName=Buck Bumble (J) [!] +CRC=D7C762B6 F83D9642 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[41417FCE2B37EAAE787C5A845A0015C4] +GoodName=Buck Bumble (U) [!] +CRC=85AE781A C756F05D +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[01933A0CBBDE1D4EB4C58CC6C6C27633] +GoodName=Buck Bumble (U) [b1][t1] +CRC=3C2B07FC 8C6AC97B +RefMD5=41417FCE2B37EAAE787C5A845A0015C4 + +[CD19788AE04DAD7AF27FD0C591983CCE] +GoodName=Buck Bumble (U) [b2] +CRC=E8522F04 43FA513A +RefMD5=41417FCE2B37EAAE787C5A845A0015C4 + +[C129EE8DA7FE1B976D71932733385438] +GoodName=Buck Bumble (U) [f1] (PAL) +CRC=3C2AC7FA 72BC3A5F +RefMD5=41417FCE2B37EAAE787C5A845A0015C4 + +[28F8F7D8423B291E3056047C62E2937A] +GoodName=Buck Bumble (U) [t1] +CRC=3C2B07FC 8C6AC97B +RefMD5=41417FCE2B37EAAE787C5A845A0015C4 + +[ED3E962653A1CD56AAB175DEEE6EE52A] +GoodName=Bug's Life, A (E) [!] +CRC=8F12C096 45DC17E1 +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[5BF0F2351AEE577A8345D6E13D197E06] +GoodName=Bug's Life, A (E) [f1] (NTSC) +CRC=09035DC5 870C1041 +RefMD5=ED3E962653A1CD56AAB175DEEE6EE52A + +[D2860D4FBD0EC4B2711A6EF8D78F9866] +GoodName=Bug's Life, A (F) [!] +CRC=2B38AEC0 6350B810 +SaveType=None +Mempak=Yes +Rumble=Yes +Players=1 +CountPerOp=1 + +[504C92A5978B7EAE7A3FD30645E06D39] +GoodName=Bug's Life, A (F) [f1] (NTSC) +CRC=BD58346E 67E74459 +RefMD5=D2860D4FBD0EC4B2711A6EF8D78F9866 + +[CBEF54768670F4B5602CCBC90150007A] +GoodName=Bug's Life, A (G) [!] +CRC=DFF227D9 0D4D8169 +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[919E5D60A7F9A79D89AC179123D47EEE] +GoodName=Bug's Life, A (G) [f1] (NTSC) +CRC=31E33A96 2744267B +RefMD5=CBEF54768670F4B5602CCBC90150007A + +[E3609FD12369C464E832C6D2A4D20790] +GoodName=Bug's Life, A (I) [!] +CRC=F63B89CE 4582D57D +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[7FD6BFFB80F920E01EF869829D485EA3] +GoodName=Bug's Life, A (U) [!] +CRC=82DC04FD CF2D82F4 +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[14ACC20454B0C2789C9F7EF7A556231A] +GoodName=Bug's Life, A (U) [b1] +CRC=82DC04FD CF2D82F4 +RefMD5=7FD6BFFB80F920E01EF869829D485EA3 + +[6472BD444D2025B1D883FFAE35D94FD4] +GoodName=Bug's Life, A (U) [b1][f1] (PAL) +CRC=2FE62885 F6853DAF +RefMD5=7FD6BFFB80F920E01EF869829D485EA3 + +[08E3F4EEEA56C873A84EA076AA362EDD] +GoodName=Bug's Life, A (U) [f1] (PAL) +CRC=2FE62885 F6853DAF +RefMD5=7FD6BFFB80F920E01EF869829D485EA3 + +[B8B760613CAA702E33F271741170632A] +GoodName=Bug's Life, A (U) [t1] +CRC=3F4AFB7B 2D24C8F8 +RefMD5=7FD6BFFB80F920E01EF869829D485EA3 + +[30AAE8A534C72FFC89343E8EF0F1C5A1] +GoodName=Bug's Life, A (U) [t2] +CRC=3F4AFB7B 2D24C8F8 +RefMD5=7FD6BFFB80F920E01EF869829D485EA3 + +[8567382D3CD5BC0406B7B4C780F621DC] +GoodName=Bust-A-Move '99 (U) [!] +CRC=4222D89F AFE0B637 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[B292B14BBC7FFCC2A741FE87A80B8D4D] +GoodName=Bust-A-Move '99 (U) [b1] +CRC=8AFB2D9A 9F186C02 +RefMD5=8567382D3CD5BC0406B7B4C780F621DC + +[4EA8627701C3D6AF50DDAA607AA3B7F9] +GoodName=Bust-A-Move '99 (U) [f1] (PAL) +CRC=F23CA406 EC2ACE78 +RefMD5=8567382D3CD5BC0406B7B4C780F621DC + +[094F639A9BA63B2136D2887C8D72BCA0] +GoodName=Bust-A-Move 2 - Arcade Edition (E) [!] +CRC=CEDCDE1E 513A0502 +Players=2 +SaveType=None +Mempak=Yes + +[AE0693C8D73E5A1407A2EDF41F1164A9] +GoodName=Bust-A-Move 2 - Arcade Edition (E) [b1] +CRC=B121ED86 883423F1 +RefMD5=094F639A9BA63B2136D2887C8D72BCA0 + +[8897A39E34AEE4D3F807AF255C6617D6] +GoodName=Bust-A-Move 2 - Arcade Edition (U) [!] +CRC=8A86F073 CD45E54B +Players=2 +SaveType=None +Mempak=Yes + +[84DD20F80DB23CB49BFE98639BE6CD71] +GoodName=Bust-A-Move 2 - Arcade Edition (U) [b1] +CRC=8A86F073 CD45E54B +RefMD5=8897A39E34AEE4D3F807AF255C6617D6 + +[5065D7A833FC73CB75DED8D639AAADA5] +GoodName=Bust-A-Move 2 - Arcade Edition (U) [b2] +CRC=2D03FD5B D5C096D5 +RefMD5=8897A39E34AEE4D3F807AF255C6617D6 + +[EF3D1E9059723766941FF4E0E913C941] +GoodName=Bust-A-Move 2 - Arcade Edition (U) [b3] +CRC=322EF540 38D316EB +RefMD5=8897A39E34AEE4D3F807AF255C6617D6 + +[8EEF2BB9543B78197CEDDA6DA860DA97] +GoodName=Bust-A-Move 2 - Arcade Edition (U) [b4] +CRC=8A86F073 CD45E54B +RefMD5=8897A39E34AEE4D3F807AF255C6617D6 + +[3EA21256DDC4157C3231AE5CC9C4652A] +GoodName=Bust-A-Move 3 DX (E) [!] +CRC=E328B4FA 004A28E1 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[16D7676C2394E422076F7CB855DE901B] +GoodName=Bust-A-Move 3 DX (E) [b1] +CRC=364C4ADC D3050993 +RefMD5=3EA21256DDC4157C3231AE5CC9C4652A + +[0BD4AEB12E502C39140E4DA52F77642E] +GoodName=Bust-A-Move 3 DX (E) [b2] +CRC=E328B4FA 004A28E1 +RefMD5=3EA21256DDC4157C3231AE5CC9C4652A + +[089D12EE45BFACD4A9FC93185AF5C42B] +GoodName=Bust-A-Move 3 DX (E) [b3] +CRC=E328B4FA 004A28E1 +RefMD5=3EA21256DDC4157C3231AE5CC9C4652A + +[1BDC2BFDD0B6CA9D8FD354AEAF1A3CF6] +GoodName=Bust-A-Move 3 DX (E) [f1] (NTSC100%) +CRC=364C4ADC D3050993 +RefMD5=3EA21256DDC4157C3231AE5CC9C4652A + +[F7CA97BE225630B7690A862FCA97E442] +GoodName=Bust-A-Move 3 DX (E) [f2] (NTSC-Z64) +CRC=D5BDCD1D 393AFE43 +RefMD5=3EA21256DDC4157C3231AE5CC9C4652A + +[3CA46AD43F9B62DF409759D56468F18E] +GoodName=Bust-A-Move 3 DX (E) [f3] (NTSC) +CRC=D5BDCD1D 393AFE43 +RefMD5=3EA21256DDC4157C3231AE5CC9C4652A + +[6A78DA715440C0C6872B5D78D31BFD3B] +GoodName=CD64 BIOS Direct-Upgrade V1.08 +CRC=549EA1B0 F666F794 + +[176D518AD6E1D89BC0FEF0672A4C1882] +GoodName=CD64 BIOS Direct-Upgrade V1.09 +CRC=8E3D8D2E 9850573F + +[0B7C2A6D2B3DE3D7D0FF7AAFAB6F8DA7] +GoodName=CD64 BIOS Direct-Upgrade V1.10 +CRC=3E93A24F AC2D58E1 + +[30D7D730E8C131C77EC6F6390B9EB8B3] +GoodName=CD64 BIOS Direct-Upgrade V1.11 +CRC=FAB972E4 1CB0882B + +[CF1E4E42B93ECBB080C05B73BB4AF808] +GoodName=CD64 BIOS Direct-Upgrade V1.13 +CRC=960621E3 7D4D5BB0 + +[B03E6FAFEA6A314285D0181D5D2ABBAB] +GoodName=CD64 BIOS Direct-Upgrade V1.20 +CRC=D32264A1 989987EA + +[A911F13E7D4CF157C79330E908BAE9A7] +GoodName=CD64 BIOS Direct-Upgrade V1.21 +CRC=4F354F88 A75E40E0 + +[6711B9D80D4D22AD0DC4AF20C9088763] +GoodName=CD64 BIOS Direct-Upgrade V1.23 +CRC=AAD9FC15 B2C9DA6F + +[354E8A1BC64683F01FE598F51D5AB4BE] +GoodName=CD64 BIOS Direct-Upgrade V1.30 +CRC=6BF11774 D330D7ED + +[F70A06305D5C545980D9D2D16EF122B2] +GoodName=CD64 BIOS EEPROM-Burner V1.08 [a1] +CRC=626C7AA3 C1480B86 + +[4EA4119D7D07FD965BB09A974341E0F3] +GoodName=CD64 BIOS EEPROM-Burner V1.08 +CRC=57D1CEA5 E2CCC89F + +[D47EC4844C8C3946A3222FB22E103F04] +GoodName=CD64 BIOS EEPROM-Burner V1.09 +CRC=CADEA283 46EAF060 + +[E7C8D1090FA90E9B8C29B48734CF3A78] +GoodName=CD64 BIOS EEPROM-Burner V1.10 +CRC=BE4AF7A0 14E3D32C + +[E730EDA716AE40BDBC404F7601491D77] +GoodName=CD64 BIOS EEPROM-Burner V1.11 (Even Bytes) +CRC=43362020 20202020 + +[706DB19D4AA4EAF902C8B48544884CEF] +GoodName=CD64 BIOS EEPROM-Burner V1.11 (Odd Bytes) +CRC=44342020 20202056 + +[CBEA298BFE9B59BBDBC379ABFD2CD208] +GoodName=CD64 BIOS EEPROM-Burner V1.11 +CRC=4A0CD2F4 F1F22FE3 + +[8191F6945DAB90A17E752AA3C94B0402] +GoodName=CD64 BIOS EEPROM-Burner V1.21 (Even Bytes) +CRC=43362020 20202020 + +[1DF4F3503FEFFBA6214092E0ABBA33B2] +GoodName=CD64 BIOS EEPROM-Burner V1.21 (Odd Bytes) +CRC=44342020 20202056 + +[16E77C21E1EA47FDD8C5635CFFF94BFD] +GoodName=CD64 BIOS EEPROM-Burner V1.21 +CRC=E74607D1 751139B4 + +[AAAA0551DB73728D79EBC1D1EDD127F6] +GoodName=CD64 BIOS EEPROM-Burner V1.23 (Even Bytes) +CRC=43362020 20202020 + +[168872484F1E933FF351D1C3DC1FC601] +GoodName=CD64 BIOS EEPROM-Burner V1.23 (Odd Bytes) +CRC=44342020 20202056 + +[DA027DB6DCB643B0BFCE71720A1F7500] +GoodName=CD64 BIOS EEPROM-Burner V1.23 +CRC=FE169919 46F54C2D + +[781AE174BEDA8641E3F0E1EFAD761050] +GoodName=CD64 BIOS EEPROM-Burner V1.30 (Even Bytes) +CRC=43362020 20202020 + +[3965F14D450F019BEB8591AA10AFC2BF] +GoodName=CD64 BIOS EEPROM-Burner V1.30 (Odd Bytes) +CRC=44342020 20202056 + +[51313E88D86DFF531E386529BBE45DD5] +GoodName=CD64 BIOS EEPROM-Burner V1.30 +CRC=C7F15051 EE3DEE75 + +[A99D3F4334F2F59B247FD5CB3DC85A77] +GoodName=CD64 Memory Test (PD) +CRC=95081A8B 49DFE4FA + +[226127FDBA21FC9019397ED2C5E5B19F] +GoodName=CZN Module Player (PD) +CRC=5B9D65DF A18AB4AE + +[29B79BF5812E5F9E5ECEF073D59F8915] +GoodName=California Speed (E) (Prototype) +CRC=CA2A7444 71DAB71C +SaveType=None +Mempak=Yes +Players=2 +CountPerOp=1 +Rumble=Yes + +[965AD2FA317F0644E49A89A3219719CB] +GoodName=California Speed (U) [!] +CRC=AC16400E CF5D071A +SaveType=None +Mempak=Yes +Players=2 +CountPerOp=1 +Rumble=Yes + +[C95353C14C4AE3DC95D1D91D6566EF92] +GoodName=California Speed (U) [f1] (Country Check) +CRC=AC16460E 46F60594 +RefMD5=965AD2FA317F0644E49A89A3219719CB + +[7658075D52C403783640DFAC2F8B6A9E] +GoodName=California Speed (U) [f2] (PAL) +CRC=41D44009 5E94483F +RefMD5=965AD2FA317F0644E49A89A3219719CB + +[EEEAD69D62EB43F093D9D46C38A82AC5] +GoodName=California Speed (U) [t1] +CRC=150DDE31 969D3994 +RefMD5=965AD2FA317F0644E49A89A3219719CB + +[CA21467BDE6B355E7A15B8F1ADA7B24D] +GoodName=Carmageddon 64 (E) (M4) (Eng-Spa-Fre-Ger) [!] +CRC=580162EC E3108BF1 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[A5DB496C328C36682EB770CEFE6C2064] +GoodName=Carmageddon 64 (E) (M4) (Eng-Spa-Fre-Ger) [f1] (NTSC) +CRC=BCC83145 6B7F5DA6 +RefMD5=CA21467BDE6B355E7A15B8F1ADA7B24D + +[59EB5646FA079BCBD7A340D7A10196DD] +GoodName=Carmageddon 64 (E) (M4) (Eng-Spa-Fre-Ita) [!] +CRC=E48E01F5 E6E51F9B +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[D5271DB3CBE6B24099DCC6878C137FF7] +GoodName=Carmageddon 64 (E) (M4) (Eng-Spa-Fre-Ita) [b1] +CRC=E48E01F5 E6E51F9B +RefMD5=59EB5646FA079BCBD7A340D7A10196DD + +[BCD2A45C39128B7D7E29E351788E860E] +GoodName=Carmageddon 64 (E) (M4) (Eng-Spa-Fre-Ita) [f1] (NTSC) +CRC=A1CC026F E09D1766 +RefMD5=59EB5646FA079BCBD7A340D7A10196DD + +[3559BE56B70BAFB77C900516B909BFEF] +GoodName=Carmageddon 64 (E) (M4) (Eng-Spa-Fre-Ita) [f2] (NTSC) +CRC=5D0283F5 2CDEEA76 +RefMD5=59EB5646FA079BCBD7A340D7A10196DD + +[31BB57C1FAD0D47DC2353C1950B11886] +GoodName=Carmageddon 64 (U) [!] +CRC=F00F2D4E 340FAAF4 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[57146B6CD8EE7D96B01A811F98A1AC61] +GoodName=Castlevania (E) (M3) [!] +CRC=64F1B7CA 71A23755 +Players=1 +SaveType=None +Mempak=Yes + +[DE30F7C3D077778380E2B3D507EFE2D3] +GoodName=Castlevania (E) (M3) [b1] +CRC=64F1B7CA 71A23755 +RefMD5=57146B6CD8EE7D96B01A811F98A1AC61 + +[96C8DA6D1567F43570CCB362811114DE] +GoodName=Castlevania (E) (M3) [t1] +CRC=DA0E5024 969ED261 +RefMD5=57146B6CD8EE7D96B01A811F98A1AC61 + +[1CC5CF3B4D29D8C3ADE957648B529DC1] +GoodName=Castlevania (U) (V1.0) [!] +CRC=F35D5F95 8AFE3D69 +Players=1 +SaveType=None +Mempak=Yes + +[C19E5A3FCDF52C7292097F215DDC428A] +GoodName=Castlevania (U) (V1.0) [b1] +CRC=F35D5F95 8AFE3D69 +RefMD5=1CC5CF3B4D29D8C3ADE957648B529DC1 + +[1A9EBA4D8CB647FD03AAEB022D04344F] +GoodName=Castlevania (U) (V1.0) [b2] +CRC=F35D5F95 8AFE3D69 +RefMD5=1CC5CF3B4D29D8C3ADE957648B529DC1 + +[A4DB62BABE8583E5F5674FFCFF8B8DFC] +GoodName=Castlevania (U) (V1.0) [b3] +CRC=F35D5F95 8AFE3D69 +RefMD5=1CC5CF3B4D29D8C3ADE957648B529DC1 + +[3E972E3340BED6E47D3C515DD10EAEDA] +GoodName=Castlevania (U) (V1.0) [b4] +CRC=F35D5F95 8AFE3D69 +RefMD5=1CC5CF3B4D29D8C3ADE957648B529DC1 + +[1FEC5A43F756C4AAE958CD286F6451C5] +GoodName=Castlevania (U) (V1.0) [t1] +CRC=0B28EBA3 5E062616 +RefMD5=1CC5CF3B4D29D8C3ADE957648B529DC1 + +[EBDC9053485AAEE05378A9D95D991104] +GoodName=Castlevania (U) (V1.0) [t2] +CRC=036CBFE5 9E626365 +RefMD5=1CC5CF3B4D29D8C3ADE957648B529DC1 + +[8F94C0A43D697D8DEAE9DE660865A966] +GoodName=Castlevania (U) (V1.0) [t3] +CRC=0B28EBA3 5E062616 +RefMD5=1CC5CF3B4D29D8C3ADE957648B529DC1 + +[8ADA90FBD3313D5080007905D183CBD4] +GoodName=Castlevania (U) (V1.0) [t4] +CRC=0B28EBA3 5E062616 +RefMD5=1CC5CF3B4D29D8C3ADE957648B529DC1 + +[CE71D1CE0A2B6D597F72CB4FC08F5844] +GoodName=Castlevania (U) (V1.1) [!] +CRC=F35D5335 B7667CB7 +Players=1 +SaveType=None +Mempak=Yes + +[06B58673F7D31C56F8FE8186E86F6BD6] +GoodName=Castlevania (U) (V1.2) [!] +CRC=4BCDFF47 AAA3AF8F +Players=1 +SaveType=None +Mempak=Yes + +[78D5F8A98A5ED21D0817856BCD2AD750] +GoodName=Castlevania - Legacy of Darkness (E) (M3) [!] +CRC=A2C54BE7 6719CBB2 +Players=1 +SaveType=None +Mempak=Yes + +[3152B82C03FC7B928D3D5C43F95AEF51] +GoodName=Castlevania - Legacy of Darkness (E) (M3) [h1C] +CRC=A2C54BE7 6719CBB2 +RefMD5=78D5F8A98A5ED21D0817856BCD2AD750 + +[45EF2794A1AC6AD737288A6577D55194] +GoodName=Castlevania - Legacy of Darkness (E) (M3) [o1] +CRC=A2C54BE7 6719CBB2 +RefMD5=78D5F8A98A5ED21D0817856BCD2AD750 + +[25258460F98F567497B24844ABE3A05B] +GoodName=Castlevania - Legacy of Darkness (U) [!] +CRC=1CC06338 87388926 +Players=1 +SaveType=None +Mempak=Yes + +[5F73634C622ABEDF6204CB801872C79C] +GoodName=Castlevania - Legacy of Darkness (U) [b1] +CRC=1CC06338 87388926 +RefMD5=25258460F98F567497B24844ABE3A05B + +[2D6ABF559A9AAE65BBEB0E60B3F82D1B] +GoodName=Castlevania - Legacy of Darkness (U) [f1] (PAL) +CRC=0CE3D2E6 6C6E443D +RefMD5=25258460F98F567497B24844ABE3A05B + +[DE4CA7C5F9DD9216771451A5AFF9F634] +GoodName=Castlevania - Legacy of Darkness (U) [f2] (PAL) +CRC=7FD0761E 2190A9ED +RefMD5=25258460F98F567497B24844ABE3A05B + +[956FCD46E850E9D10E623C6749D5524E] +GoodName=Castlevania - Legacy of Darkness (U) [t1] +CRC=64B62D16 43A2A592 +RefMD5=25258460F98F567497B24844ABE3A05B + +[31FB88048076ACE4BD4205C5F40414AB] +GoodName=Centre Court Tennis (E) [!] +CRC=DCCF2134 9DD63578 +Players=4 +Mempak=Yes + +[F52661EF93B9FD4DF16F1F113082AEAA] +GoodName=Centre Court Tennis (E) [f1] (NTSC) +CRC=B6C4F400 92A39D47 +RefMD5=31FB88048076ACE4BD4205C5F40414AB + +[53EE0172E29CDCBBFA5957A442863E5A] +GoodName=Centre Court Tennis (E) [h1C] +CRC=DCCF2134 9DD63578 +RefMD5=31FB88048076ACE4BD4205C5F40414AB + +[1CD90B13B7FD6AFDCB838F801D807826] +GoodName=Chameleon Twist (E) [!] +CRC=B9AF8CC6 DEC9F19F +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes + +[AB7D5366FEDCF8EC2D414B6001BEB399] +GoodName=Chameleon Twist (E) [b1] +CRC=B9AF8CC6 DEC9F19F +RefMD5=1CD90B13B7FD6AFDCB838F801D807826 + +[7C74D08A04B6B1B670D90CDB153F083C] +GoodName=Chameleon Twist (E) [b2] +CRC=B9AF8CC6 DEC9F19F +RefMD5=1CD90B13B7FD6AFDCB838F801D807826 + +[2151AB8629DACD8936439FC90F0AFD10] +GoodName=Chameleon Twist (E) [b3] +CRC=B9AF8CC6 DEC9F19F +RefMD5=1CD90B13B7FD6AFDCB838F801D807826 + +[3682AEBA1DA191A1CB2C513B1F834F70] +GoodName=Chameleon Twist (E) [f1] (NTSC) +CRC=4191BA80 41C5E21A +RefMD5=1CD90B13B7FD6AFDCB838F801D807826 + +[C71750C4B84081F3331D957D3FE932AD] +GoodName=Chameleon Twist (E) [o1] +CRC=B9AF8CC6 DEC9F19F +RefMD5=1CD90B13B7FD6AFDCB838F801D807826 + +[3728BE19FDCFC3ECEBD8C7504C13D1F5] +GoodName=Chameleon Twist (E) [o2] +CRC=B9AF8CC6 DEC9F19F +RefMD5=1CD90B13B7FD6AFDCB838F801D807826 + +[C0EB519122D63A944A122437EC1B98EE] +GoodName=Chameleon Twist (J) [!] +CRC=A4F2F521 F0EB168E +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes + +[397BE52D4FB7DF1E26C6275E05425571] +GoodName=Chameleon Twist (U) (V1.0) [!] +CRC=6420535A 50028062 +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes + +[AB299B3943161B9C2ABF03F5A9824E9F] +GoodName=Chameleon Twist (U) (V1.0) [b1] +CRC=6420535A 50028062 +RefMD5=397BE52D4FB7DF1E26C6275E05425571 + +[959E64F082449BDBD0E5164C32491470] +GoodName=Chameleon Twist (U) (V1.0) [b2] +CRC=6420535A 50028062 +RefMD5=397BE52D4FB7DF1E26C6275E05425571 + +[277D852DF9C71BE8DCBA01BA8C862482] +GoodName=Chameleon Twist (U) (V1.0) [b3] +CRC=6420535A 50028062 +RefMD5=397BE52D4FB7DF1E26C6275E05425571 + +[0A04F5F5938218B510A573B86967B199] +GoodName=Chameleon Twist (U) (V1.0) [t1] +CRC=1CD50DF2 345593AF +RefMD5=397BE52D4FB7DF1E26C6275E05425571 + +[D8A88ACFCD89DF7A59D9A1B050FDA740] +GoodName=Chameleon Twist (U) (V1.1) [!] +CRC=D81963C7 4271A3AA +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes + +[45D1D039AB7926ADC748DE640AFD986A] +GoodName=Chameleon Twist 2 (E) [!] +CRC=07A69D01 9A7D41A1 +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes + +[3A5EDF7256EA5E7AF4B451E07CC54003] +GoodName=Chameleon Twist 2 (E) [b1] +CRC=07A69D01 9A7D41A1 +RefMD5=45D1D039AB7926ADC748DE640AFD986A + +[740AD4DB03952BBE997DB09947A41E62] +GoodName=Chameleon Twist 2 (J) [!] +CRC=0549765A 93B9D042 +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes + +[7A638431CE966DDA97B282FF04B1D9D7] +GoodName=Chameleon Twist 2 (J) [b1] +CRC=0549765A 93B9D042 +RefMD5=740AD4DB03952BBE997DB09947A41E62 + +[24658C0D8AC2C4FD58A74F13BCA1D16A] +GoodName=Chameleon Twist 2 (J) [b2] +CRC=7D5772F8 3A6785EF +RefMD5=740AD4DB03952BBE997DB09947A41E62 + +[99605763AD74D40D5B2D24CF3F0A3CD5] +GoodName=Chameleon Twist 2 (J) [b3] +CRC=0549765A 93B9D042 +RefMD5=740AD4DB03952BBE997DB09947A41E62 + +[33B9DDDD6D7039CE1C9E6773056A65C8] +GoodName=Chameleon Twist 2 (J) [b4] +CRC=0549765A 93B9D042 +RefMD5=740AD4DB03952BBE997DB09947A41E62 + +[A55AF433E65E3690E2DC2B16018E9A0F] +GoodName=Chameleon Twist 2 (J) [b5] +CRC=0549765A 93B9D042 +RefMD5=740AD4DB03952BBE997DB09947A41E62 + +[4C5F3C38743EBB2D12154A83C026DA46] +GoodName=Chameleon Twist 2 (J) [o2] +CRC=0549765A 93B9D042 +RefMD5=740AD4DB03952BBE997DB09947A41E62 + +[D85C29FD57FE481A34AFBCDB9774395A] +GoodName=Chameleon Twist 2 (J) [t1] +CRC=7D5772F8 3A6785EF +RefMD5=740AD4DB03952BBE997DB09947A41E62 + +[00327E0B5DF6DCE6DECC31353F33A3D3] +GoodName=Chameleon Twist 2 (U) [!] +CRC=CD538CE4 618AFCF9 +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes + +[80F4CD56317218264E35894BA22CAD35] +GoodName=Chameleon Twist 2 (U) [t1] +CRC=752E1BF8 E81DF66D +RefMD5=00327E0B5DF6DCE6DECC31353F33A3D3 + +[4A3263EAB67FAB2D1171A23765D73AC6] +GoodName=Chaos 89 Demo (PD) +CRC=EDA1A0C7 58EE0464 + +[DD53E1F83E8789D23DF6AF942FFEF236] +GoodName=Charlie Blast's Territory (E) [!] +CRC=FB3C48D0 8D28F69F +SaveType=None +Players=4 +CountPerOp=1 +Rumble=Yes + +[A7C15E0C1E7D898C1B20276DF7A62660] +GoodName=Charlie Blast's Territory (E) [o1] +CRC=FB3C48D0 8D28F69F +RefMD5=DD53E1F83E8789D23DF6AF942FFEF236 + +[59FA8C6D533D36C0FFC2AAFAB7166E6F] +GoodName=Charlie Blast's Territory (U) [!] +CRC=1E0E96E8 4E28826B +SaveType=None +Players=4 +CountPerOp=1 +Rumble=Yes + +[7FFD84FC7D112EAB4EEF15CB10189A38] +GoodName=Charlie Blast's Territory (U) [hIR] +CRC=1E0E96E8 4E28826B +RefMD5=59FA8C6D533D36C0FFC2AAFAB7166E6F + +[7CBB43473597F48AA9A8E0B0D38CE685] +GoodName=Charlie Blast's Territory (U) [hI] +CRC=A6FD0808 6E6B3ECA +RefMD5=59FA8C6D533D36C0FFC2AAFAB7166E6F + +[8F6BED633BE214CF039DBDAC356231CE] +GoodName=Chopper Attack (E) [!] +CRC=2E359339 3FA5EDA6 +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[AC129AB2688C02419FC190A87F2A2E93] +GoodName=Chopper Attack (E) [b1] +CRC=2E359339 3FA5EDA6 +RefMD5=8F6BED633BE214CF039DBDAC356231CE + +[0A3955C704210225D95937DCAB86C9E3] +GoodName=Chopper Attack (E) [t1] +CRC=D852E238 0E52A960 +RefMD5=8F6BED633BE214CF039DBDAC356231CE + +[C37E8AFB4F3ECC86D01CE7388CA59347] +GoodName=Chopper Attack (U) [!] +CRC=214CAD94 BE1A3B24 +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[14AEB927F3620EFE48AF7FC748C1931F] +GoodName=Chopper Attack (U) [b1] +CRC=ACBF6069 EABEE162 +RefMD5=C37E8AFB4F3ECC86D01CE7388CA59347 + +[B8BEA2194D7D75A1711C024F5069D18E] +GoodName=Chopper Attack (U) [b2] +CRC=214CAD94 BE1A3B24 +RefMD5=C37E8AFB4F3ECC86D01CE7388CA59347 + +[34957B173CD33C999B954E7034FC01EA] +GoodName=Chopper Attack (U) [b3] +CRC=214CAD94 BE1A3B24 +RefMD5=C37E8AFB4F3ECC86D01CE7388CA59347 + +[B34CBCA3EEE5C010FF3E504AF2064069] +GoodName=Chopper Attack (U) [b4] +CRC=BF5D6D65 3F4A9C03 +RefMD5=C37E8AFB4F3ECC86D01CE7388CA59347 + +[5FA39EF0EBE18DA55C260A3A89F935B6] +GoodName=Chopper Attack (U) [b5] +CRC=214CAD94 BE1A3B24 +RefMD5=C37E8AFB4F3ECC86D01CE7388CA59347 + +[64C75E19890ACDE25842A815A21D55C9] +GoodName=Chopper Attack (U) [b6] +CRC=214CAD94 BE1A3B24 +RefMD5=C37E8AFB4F3ECC86D01CE7388CA59347 + +[F10D601D64786C52CAC1FD0AB5511C82] +GoodName=Chopper Attack (U) [t1] +CRC=BF5D6D65 3F4A9C03 +RefMD5=C37E8AFB4F3ECC86D01CE7388CA59347 + +[8287A908E36E79B2D3AF0BD22C43ECD9] +GoodName=Choro Q 64 (J) [!] +CRC=2BCCF9C4 403D9F6F +Players=4 +SaveType=Eeprom 4KB +Mempak=Yes + +[2C944319017A21652566CC4196C714CC] +GoodName=Choro Q 64 (J) [b1] +CRC=2BCCF9C4 403D9F6F +RefMD5=8287A908E36E79B2D3AF0BD22C43ECD9 + +[470E1635A9693102B426A840DBD691E5] +GoodName=Choro Q 64 (J) [b2] +CRC=2BCCF9C4 403D9F6F +RefMD5=8287A908E36E79B2D3AF0BD22C43ECD9 + +[04A2C1A6EFAE28E07A4AD77603081F86] +GoodName=Choro Q 64 (J) [b3] +CRC=2BCCF9C4 403D9F6F +RefMD5=8287A908E36E79B2D3AF0BD22C43ECD9 + +[5F4D852BD3B707C1B4FE29F2FE19C687] +GoodName=Choro Q 64 (J) [b4] +CRC=2BCCF9C4 403D9F6F +RefMD5=8287A908E36E79B2D3AF0BD22C43ECD9 + +[7151AE130BA8DC97A205B62FF0EE0FB6] +GoodName=Choro Q 64 (J) [h1C] +CRC=2BCCF9C4 403D9F6F +RefMD5=8287A908E36E79B2D3AF0BD22C43ECD9 + +[9081370141079031EBBDBCA56FC8C7D8] +GoodName=Choro Q 64 II - Hacha Mecha Grand Prix Race (J) [!] +CRC=26CD0F54 53EBEFE0 +Players=4 +Mempak=Yes +Rumble=Yes +Transferpak=Yes + +[78838C202C4FF5A460586451EE9182AA] +GoodName=Chou Kuukan Night Pro Yakyuu King (J) [!] +CRC=8ACE6683 3FBA426E +Players=4 +Mempak=Yes + +[5224CCBE260A4B7713D662D9BC269063] +GoodName=Chou Kuukan Night Pro Yakyuu King (J) [b1] +CRC=8ACE6683 3FBA426E +RefMD5=78838C202C4FF5A460586451EE9182AA + +[9C39391D103E6DB39CEC6C774EDB082A] +GoodName=Chou Kuukan Night Pro Yakyuu King (J) [h1C] +CRC=8ACE6683 3FBA426E +RefMD5=78838C202C4FF5A460586451EE9182AA + +[97EAB4DC83DA0AD2890DE2AAAA5D109A] +GoodName=Chou Kuukan Night Pro Yakyuu King 2 (J) [!] +CRC=3A180FF4 5C8E8AF7 +Players=4 +Mempak=Yes +Rumble=Yes + +[9466618F4497DA6C9091E05CC9666786] +GoodName=Chou Snobow Kids (J) [!] +CRC=A7941528 61F1199D +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes + +[74341014043CC42D8804DADBF252B344] +GoodName=Chou Snobow Kids (J) [f1] (PAL) +CRC=2FEB152B 9C205EA5 +RefMD5=9466618F4497DA6C9091E05CC9666786 + +[BA145D51B681EF4432DB59C1DA703047] +GoodName=Christmas Flame Demo by Halley's Comet Software (PD) +CRC=B484EB31 D44B1928 + +[2A0BF5A9A136D57AF01D199B16899634] +GoodName=City-Tour GP - Zennihon GT Senshuken (J) [!] +CRC=F8009DB0 6B291823 +Players=2 +SaveType=Eeprom 16KB +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[4808E8129B22AC8B3185B37243113005] +GoodName=City-Tour GP - Zennihon GT Senshuken (J) [b1] +CRC=F8009DB0 6B291823 +RefMD5=2A0BF5A9A136D57AF01D199B16899634 + +[2BD614A2A1A317ECBEEB4193954C5FA5] +GoodName=City-Tour GP - Zennihon GT Senshuken (J) [b2] +CRC=F8009DB0 6B291823 +RefMD5=2A0BF5A9A136D57AF01D199B16899634 + +[E226801C0B57FD2F2D2E303986DB5E5C] +GoodName=City-Tour GP - Zennihon GT Senshuken (J) [b3] +CRC=F8009DB0 6B291823 +RefMD5=2A0BF5A9A136D57AF01D199B16899634 + +[30E7E083B978408D5B7760D0CE4DC61D] +GoodName=Clay Fighter - Sculptor's Cut (U) [!] +CRC=FA5A3DFF B4C9CDB9 +SaveType=None +Players=4 + +[052BB2C8C4174633A0D38DEB4D31C719] +GoodName=Clay Fighter - Sculptor's Cut (U) [b1] +CRC=FA5A3DFF B4C9CDB9 +RefMD5=30E7E083B978408D5B7760D0CE4DC61D + +[D47AB8CA78D9686A7021EBBBA00B0AA0] +GoodName=Clay Fighter - Sculptor's Cut (U) [b2] +CRC=FA5A3DFF B4C9CDB9 +RefMD5=30E7E083B978408D5B7760D0CE4DC61D + +[B8047551F6E44E367862E9BC9C2A4DDF] +GoodName=Clay Fighter - Sculptor's Cut (U) [h1C] +CRC=FA5A3DFF B4C9CDB9 +RefMD5=30E7E083B978408D5B7760D0CE4DC61D + +[CCD869C8D45C3998ADDCBF43791D6C56] +GoodName=Clay Fighter - Sculptor's Cut (U) [h2C] +CRC=FA5A3DFF B4C9CDB9 +RefMD5=30E7E083B978408D5B7760D0CE4DC61D + +[CD00C317003B03CD0BBEEC4570D2B55D] +GoodName=Clay Fighter - Sculptor's Cut (U) [t1] +CRC=6C48FE11 8E1A27EC +RefMD5=30E7E083B978408D5B7760D0CE4DC61D + +[CBBEAFF5A9074D1A5507CF46CD683D36] +GoodName=Clay Fighter 63 1-3 (Beta) [!] +CRC=2B6FA7C0 09A71225 +Players=4 +SaveType=None + +[BE41BA94878999987DC8D2FD3A5551D9] +GoodName=Clay Fighter 63 1-3 (Beta) [b1] +CRC=2B6FA7C0 09A71225 + +[41965B533F3DD95663361D9DF68B0C1F] +GoodName=Clay Fighter 63 1-3 (E) [!] +CRC=8E9692B3 4264BB2A +Players=4 +SaveType=None + +[46B95EA3EB82654439A6750443BCDE53] +GoodName=Clay Fighter 63 1-3 (E) [b1][h1C] +CRC=8E9692B3 4264BB2A +RefMD5=41965B533F3DD95663361D9DF68B0C1F + +[2084974C9098B2D01C1F58B0E56EE058] +GoodName=Clay Fighter 63 1-3 (E) [h1C] +CRC=8E9692B3 4264BB2A +RefMD5=41965B533F3DD95663361D9DF68B0C1F + +[3207BF22E305C488109B09A03706F36F] +GoodName=Clay Fighter 63 1-3 (U) [!] +CRC=F03C24CA C5237BCC +Players=4 +SaveType=None + +[7A4ACAB8997D180C045D9286C917ED1B] +GoodName=Clay Fighter 63 1-3 (U) [b1] +CRC=F03C24CA C5237BCC +RefMD5=3207BF22E305C488109B09A03706F36F + +[0EDBCB64159B7E32DDA165A7A363AB35] +GoodName=Clay Fighter 63 1-3 (U) [b2] +CRC=F03C24CA C5237BCC +RefMD5=3207BF22E305C488109B09A03706F36F + +[D41EE755C8DDF4BBD5E368670C672488] +GoodName=Clay Fighter 63 1-3 (U) [o1] +CRC=2B6FA7C0 09A71225 +RefMD5=3207BF22E305C488109B09A03706F36F + +[6746F4CC43ACEBF3F04B1677B16C1935] +GoodName=Clay Fighter 63 1-3 (U) [o2] +CRC=F03C24CA C5237BCC +RefMD5=3207BF22E305C488109B09A03706F36F + +[0E38732BC5F564D74D57EF0A0CBA8D56] +GoodName=Cliffi's Little Intro by Cliffi (POM '99) (PD) [b1] +CRC=10637557 03E93693 + +[BE2AB7CD9DBDDA8DDAE1EA288C663F15] +GoodName=Cliffi's Little Intro by Cliffi (POM '99) (PD) +CRC=4B0313E2 65657446 + +[42DA4C7D040F9E7CD046A42EC3E68027] +GoodName=Command & Conquer (E) (M2) [!] +CRC=AE5B9465 C54D6576 +Players=1 +SaveType=Flash RAM +Rumble=Yes + +[4D972AE7FAA1AA3ED26026F6F46C8A6A] +GoodName=Command & Conquer (E) (M2) [b1] +CRC=AE5B9465 C54D6576 +RefMD5=42DA4C7D040F9E7CD046A42EC3E68027 + +[C0CC62AC4B06416C9DB5B765ADE5F626] +GoodName=Command & Conquer (E) (M2) [b2] +CRC=AE5B9465 C54D6576 +RefMD5=42DA4C7D040F9E7CD046A42EC3E68027 + +[1D26E8B65CD2F1BF1EABAFFDBBFC1F26] +GoodName=Command & Conquer (E) (M2) [b3] +CRC=AE5B9465 C54D6576 +RefMD5=42DA4C7D040F9E7CD046A42EC3E68027 + +[E19F762182F4B4ADF5D8F6D998033059] +GoodName=Command & Conquer (E) (M2) [f1] (Z64) +CRC=EA630EC7 2B2F37F3 +RefMD5=42DA4C7D040F9E7CD046A42EC3E68027 + +[1A9195662C89DCBEA88BCFA99B096CDE] +GoodName=Command & Conquer (G) [!] +CRC=B5025BAD D32675FD +Players=1 +SaveType=Flash RAM +Rumble=Yes + +[19A646E0148EA6695E797C1990919B8A] +GoodName=Command & Conquer (G) [f1] (Z64) +CRC=705AC38A A8D714E8 +RefMD5=1A9195662C89DCBEA88BCFA99B096CDE + +[B436F4717AC585B0D847756468FD6393] +GoodName=Command & Conquer (U) [!] +CRC=95286EB4 B76AD58F +Players=1 +SaveType=Flash RAM +Rumble=Yes + +[57044E8F223D117F55B22E7FD2EDF71E] +GoodName=Command & Conquer (U) [b1] +CRC=F921961E E09D8B11 +RefMD5=B436F4717AC585B0D847756468FD6393 + +[715D537C6D78440C085DDD22E827C260] +GoodName=Command & Conquer (U) [f1] (Z64) +CRC=22AD2E8E 73CC712C +RefMD5=B436F4717AC585B0D847756468FD6393 + +[B206F917C1B4FD41CDADC4064C48B07B] +GoodName=Congratulations Demo for SPLiT by Widget and Immortal (PD) [b1] +CRC=D2B908C8 E0E73A1D + +[2616B2901F794EADFD26D5FA2BF5564D] +GoodName=Congratulations Demo for SPLiT by Widget and Immortal (PD) +CRC=D2B908C8 E0E73A1D + +[05194D49C14E52055DF72A54D40791E1] +GoodName=Conker's Bad Fur Day (E) [!] +CRC=373F5889 9A6CA80A +SaveType=Eeprom 16KB +Players=4 +Rumble=Yes + +[70E9EB9BF2F7BC76CA38CE450BA01C2E] +GoodName=Conker's Bad Fur Day (U) (Debug Version) [f1] (Decrypted) +CRC=8BC3A47A 74221294 +RefMD5=00E2920665F2329B95797A7EAABC2390 + +[13ECBAEEF7111D5343D73A80E03E353A] +GoodName=Conker's Bad Fur Day (U) (Demo) (V_ECTS_Decrypted) +CRC=A08D0F77 6F82E38C +Players=4 +Rumble=Yes + +[00E2920665F2329B95797A7EAABC2390] +GoodName=Conker's Bad Fur Day (U) [!] +CRC=30C7AC50 7704072D +SaveType=Eeprom 16KB +Players=4 +Rumble=Yes + +[DB7A03B77D44DB81B8A3FCDFC4B72D8C] +GoodName=Cruis'n Exotica (U) [!] +CRC=46A3F7AF 0F7591D0 +SaveType=Eeprom 4KB +Players=2 +Rumble=Yes + +[A8266778591994EFA3A3B9E6E806F8C8] +GoodName=Cruis'n Exotica (U) [t1] +CRC=1E4C4743 FEA2C4D1 +RefMD5=DB7A03B77D44DB81B8A3FCDFC4B72D8C + +[69CD5BA6BC9310B9E37CCB1BC6BD16AD] +GoodName=Cruis'n USA (E) [!] +CRC=503EA760 E1300E96 +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes + +[00A3E885F8D899646228A21D946B2102] +GoodName=Cruis'n USA (U) (V1.0) [!] +CRC=FF2F2FB4 D161149A +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes + +[190906A8A5F1C1D4909F6374A784ECA4] +GoodName=Cruis'n USA (U) (V1.0) [T+Ita0.40] +CRC=FF2F2FB4 D161149A +RefMD5=00A3E885F8D899646228A21D946B2102 + +[635C94434922DC73C58965004E3F699D] +GoodName=Cruis'n USA (U) (V1.0) [b1] +CRC=FF2F2FB4 D161149A +RefMD5=00A3E885F8D899646228A21D946B2102 + +[D37AB17D3E27ED333704C44DCFAA28E7] +GoodName=Cruis'n USA (U) (V1.0) [b2] +CRC=FF2F2FB4 D161149A +RefMD5=00A3E885F8D899646228A21D946B2102 + +[1D4843F0C69E273A1099A4267BB9F526] +GoodName=Cruis'n USA (U) (V1.0) [b3] +CRC=FF2F2FB4 D161149A +RefMD5=00A3E885F8D899646228A21D946B2102 + +[B0679C685A1FB4D2BA96E4BB941262DE] +GoodName=Cruis'n USA (U) (V1.0) [b4] +CRC=FF2F2FB4 D161149A +RefMD5=00A3E885F8D899646228A21D946B2102 + +[A8D5B5F1902AFB1346D97A9D0D52B292] +GoodName=Cruis'n USA (U) (V1.0) [b5] +CRC=FF2F2FB4 D161149A +RefMD5=00A3E885F8D899646228A21D946B2102 + +[41CA21BD737E16BA81168982B74276F1] +GoodName=Cruis'n USA (U) (V1.0) (VC) [!] +CRC=FF2F2FB4 D161149A +RefMD5=00A3E885F8D899646228A21D946B2102 + +[45FC88E2BA6711F25F0DE988E719DF29] +GoodName=Cruis'n USA (U) (V1.1) [!] +CRC=5306CF45 CBC49250 +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes + +[2838A9018AD2BCB8B7F6161C746A1B71] +GoodName=Cruis'n USA (U) (V1.2) [!] +CRC=B3402554 7340C004 +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes + +[AF950A1B6C460D7FC3E78375D35047EF] +GoodName=Cruis'n World (E) [!] +CRC=83F3931E CB72223D +SaveType=Eeprom 16KB +Players=4 +Rumble=Yes + +[20DB5E4DDB0CD5B04C4BF09CDC95592F] +GoodName=Cruis'n World (E) (V1.1) [!] +CRC=33E61153 97A2E2C5 +SaveType=Eeprom 16KB +Players=4 +Rumble=Yes + +[626478CC0790B1452045A3D853B46C18] +GoodName=Cruis'n World (E) [b1] +CRC=312E2FC5 CB76AB4D +RefMD5=AF950A1B6C460D7FC3E78375D35047EF + +[942A09966EC752A5EE81D042AF11D4BB] +GoodName=Cruis'n World (E) [b2] +CRC=AFF44E2D 2ECB9679 +RefMD5=AF950A1B6C460D7FC3E78375D35047EF + +[B22A6E184CB0657882CB4D6A81534254] +GoodName=Cruis'n World (E) [f1] +CRC=AFF44E2D 2ECB9679 +RefMD5=AF950A1B6C460D7FC3E78375D35047EF + +[0BD71426A0240CA4D871A8F54B7761F0] +GoodName=Cruis'n World (E) [f2] +CRC=AFF44E2D 2ECB9679 +RefMD5=AF950A1B6C460D7FC3E78375D35047EF + +[12CE267F5D538C2959BDEBA5E87BDE79] +GoodName=Cruis'n World (E) [f3] (NTSC) +CRC=AF3E4E2D 9C63E651 +RefMD5=AF950A1B6C460D7FC3E78375D35047EF + +[AADA4CBD938E58A447B399A1D46F03E6] +GoodName=Cruis'n World (U) [!] +CRC=DFE61153 D76118E6 +SaveType=Eeprom 16KB +Players=4 +Rumble=Yes + +[B97C963235635672CBEAB35154DFDFA2] +GoodName=Cruis'n World (U) [b1] +CRC=E2A32049 46E8F8E2 +RefMD5=AADA4CBD938E58A447B399A1D46F03E6 + +[82C6213EF921BF2805B3CA7CA4F08BFB] +GoodName=Cruis'n World (U) [b2] +CRC=E2A32049 46E8F8E2 +RefMD5=AADA4CBD938E58A447B399A1D46F03E6 + +[63DA3150AC7B603187DE3951A3270F6E] +GoodName=Cruis'n World (U) [b3] +CRC=DFE61153 D76118E6 +RefMD5=AADA4CBD938E58A447B399A1D46F03E6 + +[4BCDE237F4A390A564369696D0579760] +GoodName=Cruis'n World (U) [f1] +CRC=E2A32049 46E8F8E2 +RefMD5=AADA4CBD938E58A447B399A1D46F03E6 + +[AD4A781024E29F4A735CB4B87F2D59DB] +GoodName=Cruis'n World (U) [o1] +CRC=DFE61153 D76118E6 +RefMD5=AADA4CBD938E58A447B399A1D46F03E6 + +[8D4DAA86BF542D8A55460F56C52F7D02] +GoodName=Cube Demo (PD) +CRC=0E3ED77B 8E1C26FD + +[6F936ECE2BA8EA8C74BDBBA9BDA1407A] +GoodName=Cube Demo (PD) [b1] +CRC=0E3ED77B 8E1C26FD +RefMD5=8D4DAA86BF542D8A55460F56C52F7D02 + +[9A3014ED85F796CCB836E85E78D2618A] +GoodName=Cube Demo (PD) [b2] +CRC=0E3ED77B 8E1C26FD +RefMD5=8D4DAA86BF542D8A55460F56C52F7D02 + +[827CFFD3648116511ED2D5DA76C83FBB] +GoodName=Cube Demo by Msftug (PD) +CRC=37BDF228 92CF779C + +[33F2BC6847985F96DE8177147DCD3B85] +GoodName=Custom Robo (Ch) (iQue) [!] +Players=2 + +[A06D2E83CF2628915E8847F609474661] +GoodName=Custom Robo (J) [!] +CRC=83CB0B87 7E325457 +Players=2 + +[115118DD5E0F02D82BA1BF070A7B78F1] +GoodName=Custom Robo V2 (J) [!] +CRC=079501B9 AB0232AB +Players=4 +SaveType=Eeprom 16KB +Rumble=Yes + +[8C4A4CD472D610CDA5459B3A92F21D30] +GoodName=CyberTiger (E) [!] +CRC=D1A78A07 52A3DD3E +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[88072F30D4F9CF384B2B3A0300649218] +GoodName=CyberTiger (U) [!] +CRC=E8FC8EA1 9F738391 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[9801AAA87D650C42B021F94D5C34C7A4] +GoodName=DKONG Demo (PD) +CRC=B323E37C BBC35EC4 + +[F0D62C8FD773F55A34EAAC20D3B95F17] +GoodName=DS1 Manager V1.0 by R. Bubba Magillicutty (PD) +CRC=1194FFD2 808C6FB1 + +[4F94D90294D6E5C1FC116E073DD3F542] +GoodName=DS1 Manager V1.1 by R. Bubba Magillicutty (PD) +CRC=D7484C2A 56CFF26D + +[52037ED117D09F46F82C3F72044366E7] +GoodName=DS1 SRAM Manager V1.1 by _Sage_ (PD) +CRC=201DA461 EC0C992B + +[0B86FA9259E2B751111A1701091644B1] +GoodName=Dance Dance Revolution - Disney Dancing Museum (J) [!] +CRC=7188F445 84410A68 +Players=2 +Rumble=Yes + +[3A1488C2A8A8F2AB9368D7C056EB02A2] +GoodName=Dance Dance Revolution - Disney Dancing Museum (J) [o1] +CRC=7188F445 84410A68 +RefMD5=0B86FA9259E2B751111A1701091644B1 + +[885A29B9A52183B96E5D636F2B765231] +GoodName=Dance Dance Revolution - Disney Dancing Museum (J) [o2] +CRC=7188F445 84410A68 +RefMD5=0B86FA9259E2B751111A1701091644B1 + +[4242FDE5B74F22AAF5746459E126121F] +GoodName=Dark Rift (E) [!] +CRC=7ED67CD4 B4415E6D +Players=2 +SaveType=None + +[0DD2887AF64C5786C1C66877AFCC0B97] +GoodName=Dark Rift (E) [b1] +CRC=7ED67CD4 B4415E6D +RefMD5=4242FDE5B74F22AAF5746459E126121F + +[ECB170EBBFDA0E932C07524040BCC36C] +GoodName=Dark Rift (U) [!] +CRC=A4A52B58 23759841 +Players=2 +SaveType=None + +[CBFEAD02C508DADFB44A00E7F7ED61B8] +GoodName=Dark Rift (U) [t1] +CRC=DAA66890 ED4CCD04 +RefMD5=ECB170EBBFDA0E932C07524040BCC36C + +[A2A4A0318DAB366A595336B6F80FF3AB] +GoodName=Deadly Arts (U) [!] +CRC=F5363349 DBF9D21B +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[F403FCEB3FCD41BB5830142989FC9486] +GoodName=Deadly Arts (U) [b1] +CRC=F5363349 DBF9D21B +RefMD5=A2A4A0318DAB366A595336B6F80FF3AB + +[C644E318B33C4EBD94695C0C3E1E80FF] +GoodName=Defi au Tetris Magique (F) [!] +CRC=3F66A9D9 9BCB5B00 +SaveType=None +Players=2 +Rumble=Yes + +[772FA166E5DB51EFFC77FB8D832AC4D2] +GoodName=Densha de Go! 64 (J) [!] +CRC=17C54A61 4A83F2E7 +Players=1 +SaveType=Eeprom 16KB +Rumble=Yes +CountPerOp=1 + +[BA99C445ADC6994C97FE6463F3E0EC10] +GoodName=Densha de Go! 64 (J) [f1] (PAL) +CRC=CF138879 2A6144CB +RefMD5=772FA166E5DB51EFFC77FB8D832AC4D2 + +[FDFFA662AE3357BF5970338EE7589F6C] +GoodName=Densha de Go! 64 (J) (Localization Patch v1.01) +CRC=68D128AE 67D60F21 +RefMD5=772FA166E5DB51EFFC77FB8D832AC4D2 +Transferpak=Yes + +[1051E1402EE110F3C5E372C9E1C5B338] +GoodName=Derby Stallion 64 (J) (Beta) +CRC=96BA4EFB C9988E4E +Players=4 +SaveType=Flash RAM +Mempak=Yes + +[7F57463856540104B21A5289312B626F] +GoodName=Derby Stallion 64 (J) [!] +CRC=A5F667E1 DA1FBD1F +Players=4 +SaveType=Flash RAM +Mempak=Yes + +[BDA717ECC8434F12F313342485828B58] +GoodName=Destruction Derby 64 (E) (M3) [!] +CRC=630AA37D 896BD7DB +Players=4 +SaveType=None +Mempak=Yes +CountPerOp=1 +Rumble=Yes + +[7FCCB47498EEC06E96AE9372247D1E90] +GoodName=Destruction Derby 64 (U) [!] +CRC=DEE584A2 0F161187 +Players=4 +SaveType=None +Mempak=Yes +CountPerOp=1 +Rumble=Yes + +[02EEF6ED11174664A548626337879E8C] +GoodName=Destruction Derby 64 (U) [f1] (PAL) +CRC=8637C692 CAD23999 +RefMD5=7FCCB47498EEC06E96AE9372247D1E90 + +[825EA802BC3CBA523667B64DD696C597] +GoodName=Destruction Derby 64 (U) [t1] +CRC=8637BEAA 9B0EB296 +RefMD5=7FCCB47498EEC06E96AE9372247D1E90 + +[6D75719BFA6244C4591070D3F7356072] +GoodName=Dexanoid R1 by Protest Design (PD) +CRC=76712159 35666812 +Players=1 +SaveType=None +Status=3 +Rumble=No + +[875FA77726E7CD99BD410E3FC86C7777] +GoodName=Dexanoid R1 by Protest Design (PD) [b1] +CRC=1EDA4DE0 22BF698D +RefMD5=6D75719BFA6244C4591070D3F7356072 + +[CF2276AFD84E06AC780DBA2E0EA4806D] +GoodName=Dexanoid R1 by Protest Design (PD) [f1] (PAL) +CRC=CFEAACE9 1D532607 +RefMD5=6D75719BFA6244C4591070D3F7356072 + +[AE13E575386775E766F0E00AD2A40C9E] +GoodName=Dexanoid R1 by Protest Design (PD) [f2] (PAL) +CRC=3C7AEE05 56099CB6 +RefMD5=6D75719BFA6244C4591070D3F7356072 + +[8E4D5C6D95EFD1C94BB13644F7672909] +GoodName=Dexanoid R1 by Protest Design (PD) [t1] +CRC=0EC580B5 EBEE9C03 +RefMD5=6D75719BFA6244C4591070D3F7356072 + +[54BE265E7B2C28AB92BF1A4130ACB5A2] +GoodName=Dezaemon 3D (J) [!] +CRC=8979169C F189F6A0 +Players=1 +Rumble=Yes + +[01E34CD8A451F0B5AEF93CCF9ADB37AF] +GoodName=Dezaemon 3D (J) [b1] +CRC=8979169C F189F6A0 +RefMD5=54BE265E7B2C28AB92BF1A4130ACB5A2 + +[60A5F3E1E94F696BF5384022247B4059] +GoodName=Dezaemon 3D (J) [b1][t1] +CRC=33487563 AC0AE62A +RefMD5=54BE265E7B2C28AB92BF1A4130ACB5A2 + +[358941CA393F6D7415E99B28D49CCF68] +GoodName=Dezaemon 3D (J) [b2] +CRC=8979169C F189F6A0 +RefMD5=54BE265E7B2C28AB92BF1A4130ACB5A2 + +[108B1A72E6F93E6935E1AD8D619797DB] +GoodName=Dezaemon 3D (J) [t1] +CRC=33487563 AC0AE62A +RefMD5=54BE265E7B2C28AB92BF1A4130ACB5A2 + +[820929EBBE6FD332AC1720F94B745A8B] +GoodName=Die Hard 64 (U) (Prototype) (Level 1) +CRC=870611BA D8B1226C + +[3D1E03B097F2124F8F713013D8219291] +GoodName=Die Hard 64 (U) (Prototype) (Level 2) +CRC=08D49262 03763D39 + +[1B28C4CA21648D318BC6DD3EF27BB1FA] +GoodName=Die Hard 64 (U) (Prototype) (Level 3) +CRC=A1F51C25 16D61291 + +[0F0B7B78B345FBF2581D834CB4A81245] +GoodName=Diddy Kong Racing (E) (M3) (V1.0) [!] +CRC=FD73F775 9724755A +Players=4 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[79748E4E030B047DBAE8252C21305C75] +GoodName=Diddy Kong Racing (E) (M3) (V1.0) [f1] +CRC=85443325 77D72F56 +RefMD5=0F0B7B78B345FBF2581D834CB4A81245 + +[542FED7864218156EA90050013CD048E] +GoodName=Diddy Kong Racing (E) (M3) (V1.0) [o1] +CRC=FD73F775 9724755A +RefMD5=0F0B7B78B345FBF2581D834CB4A81245 + +[6B2BAFE540E0AF052A78E85B992BE999] +GoodName=Diddy Kong Racing (E) (M3) (V1.1) [!] +CRC=596E145B F7D9879F +Players=4 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[35CF26D4D33717BA730D7978E2F2107D] +GoodName=Diddy Kong Racing (E) (M3) (V1.1) [f1] (Z64) +CRC=D84C17CA 13F8F651 +RefMD5=6B2BAFE540E0AF052A78E85B992BE999 + +[10747662A55241B9234CD114C940504F] +GoodName=Diddy Kong Racing (J) [!] +CRC=7435C9BB 39763CF4 +Players=4 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[0D68A405BCB04318A294DBEABF1DE063] +GoodName=Diddy Kong Racing (J) [f1] (Z64) +CRC=F389A35A 17785562 +RefMD5=10747662A55241B9234CD114C940504F + +[4F0E07F0EEAC7E5D7CE3A75461888D03] +GoodName=Diddy Kong Racing (U) (M2) (V1.0) [!] +CRC=53D440E7 7519B011 +Players=4 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[94D81D14A2D768DD0EDA3A845AFB25CD] +GoodName=Diddy Kong Racing (U) (M2) (V1.0) [T+Bra_EmuBrazil] +CRC=53D440E7 7519B011 +RefMD5=4F0E07F0EEAC7E5D7CE3A75461888D03 + +[49551E729A39F9640058AB5771A49311] +GoodName=Diddy Kong Racing (U) (M2) (V1.0) [b1] +CRC=D5295672 9CB57015 +RefMD5=4F0E07F0EEAC7E5D7CE3A75461888D03 + +[DBE3F0869F817DCD52A5CB9D43BB4FD1] +GoodName=Diddy Kong Racing (U) (M2) (V1.0) [b2] +CRC=D5295672 9CB57015 +RefMD5=4F0E07F0EEAC7E5D7CE3A75461888D03 + +[AB34FECD9A7A1030EC0892328F9CEF8A] +GoodName=Diddy Kong Racing (U) (M2) (V1.0) [b3] +CRC=D5295672 9CB57015 +RefMD5=4F0E07F0EEAC7E5D7CE3A75461888D03 + +[699A6BA5281EA0C83190E9D45C708C26] +GoodName=Diddy Kong Racing (U) (M2) (V1.0) [b4] +CRC=D5295672 9CB57015 +RefMD5=4F0E07F0EEAC7E5D7CE3A75461888D03 + +[F388EE4148A7A4A2C8A815823D23149C] +GoodName=Diddy Kong Racing (U) (M2) (V1.0) [b5] +CRC=D5295672 9CB57015 +RefMD5=4F0E07F0EEAC7E5D7CE3A75461888D03 + +[C980D2C07B98452110A3A8E52DB5DA88] +GoodName=Diddy Kong Racing (U) (M2) (V1.0) [b6] +CRC=D5295672 9CB57015 +RefMD5=4F0E07F0EEAC7E5D7CE3A75461888D03 + +[07703E5A6268EEDF552FE770F24273A7] +GoodName=Diddy Kong Racing (U) (M2) (V1.0) [b7] +CRC=D5295672 9CB57015 +RefMD5=4F0E07F0EEAC7E5D7CE3A75461888D03 + +[A3551578B7298A2E4719A9108E0AA37B] +GoodName=Diddy Kong Racing (U) (M2) (V1.0) [f1] +CRC=D5295672 9CB57015 +RefMD5=4F0E07F0EEAC7E5D7CE3A75461888D03 + +[1236FB3FC8464B559BDEDFA966D6679F] +GoodName=Diddy Kong Racing (U) (M2) (V1.0) [f1][h1C] +CRC=D5295672 9CB57015 +RefMD5=4F0E07F0EEAC7E5D7CE3A75461888D03 + +[A1D47DB4C6B93C78FE55CBFC1BB28D28] +GoodName=Diddy Kong Racing (U) (M2) (V1.0) [f2] +CRC=D5295672 9CB57015 +RefMD5=4F0E07F0EEAC7E5D7CE3A75461888D03 + +[B4E658DFF037706FFB2EB64F1DFDBB3F] +GoodName=Diddy Kong Racing (U) (M2) (V1.0) [f3] +CRC=E9C8E262 A1D5FACA +RefMD5=4F0E07F0EEAC7E5D7CE3A75461888D03 + +[FA94645F1A15ABA440AD0136ED92E9D1] +GoodName=Diddy Kong Racing (U) (M2) (V1.0) [f4] +CRC=2954A98F C2236510 +RefMD5=4F0E07F0EEAC7E5D7CE3A75461888D03 + +[511833A46BE4E00D1B3655C88E278422] +GoodName=Diddy Kong Racing (U) (M2) (V1.0) [o1] +CRC=53D440E7 7519B011 +RefMD5=4F0E07F0EEAC7E5D7CE3A75461888D03 + +[DF4FC3C46307527707F9106E75074829] +GoodName=Diddy Kong Racing (U) (M2) (V1.0) [o1][f1] +CRC=D5295672 9CB57015 +RefMD5=4F0E07F0EEAC7E5D7CE3A75461888D03 + +[422FD8833F865C4A6C17FCAC4450A69E] +GoodName=Diddy Kong Racing (U) (M2) (V1.0) [o2] +CRC=53D440E7 7519B011 +RefMD5=4F0E07F0EEAC7E5D7CE3A75461888D03 + +[B31F8CCA50F31ACC9B999ED5B779D6ED] +GoodName=Diddy Kong Racing (U) (M2) (V1.1) [!] +CRC=E402430D D2FCFC9D +Players=4 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[FBCCFED51A43B0012CE927CC73D6AADA] +GoodName=Diddy Kong Racing SRAM by Group5 (PD) +CRC=9F35059D 48B7F411 +Players=4 +SaveType=SRAM + +[C4C1B52F9C4469C6C747942891DE3CFD] +GoodName=Dinosaur Planet (Dec 2000 Beta) +CRC=906C3F77 CE495EA1 +Players=1 +SaveType=Flash RAM + +[0E0E920AB13EF13508F5A98CC4CD2FF8] +GoodName=Disney's Donald Duck - Goin' Quackers (U) [!] +CRC=C16C421B A21580F7 +Players=1 +SaveType=None +Mempak=Yes +CountPerOp=3 + +[BD1DE2FC1CF31096423563A40ECBF933] +GoodName=Disney's Tarzan (E) [!] +CRC=D614E5BF A76DBCC1 +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[AF740B224E5DD0BD09F7254811559ADF] +GoodName=Disney's Tarzan (E) [h1C] +CRC=D614E5BF A76DBCC1 +RefMD5=BD1DE2FC1CF31096423563A40ECBF933 + +[5D82E903F65341487DDC11AF80AD607A] +GoodName=Disney's Tarzan (F) [!] +CRC=001A3BD0 AFB3DE1A +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[DF3CDD959E8C63B45F557FC197CE0E63] +GoodName=Disney's Tarzan (G) [!] +CRC=4C261323 4F295E1A +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[A29E203DDB6293B7D105BF4A2EEEDD1E] +GoodName=Disney's Tarzan (G) [h1C] +CRC=4C261323 4F295E1A +RefMD5=DF3CDD959E8C63B45F557FC197CE0E63 + +[EAE7E0EE5328ED9F13B9CF9990189928] +GoodName=Disney's Tarzan (U) [!] +CRC=CBFE69C7 F2C0AB2A +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[C56AD8ABD0FB5EFEF1FA0229F9A2EFF0] +GoodName=Disney's Tarzan (U) [f1] (PAL) +CRC=988C4CC3 C9F310C5 +RefMD5=EAE7E0EE5328ED9F13B9CF9990189928 + +[CC8B0A9F15B92D68963668A3495A6BF6] +GoodName=Disney's Tarzan (U) [f2] (PAL) +CRC=8BDDD635 EC0E9198 +RefMD5=EAE7E0EE5328ED9F13B9CF9990189928 + +[E9C2B20EA27E6CAB89842AF4D768724E] +GoodName=Disney's Tarzan (U) [t1] +CRC=8BEE2831 D09BC906 +RefMD5=EAE7E0EE5328ED9F13B9CF9990189928 + +[38DCF67CBA39A84108ADF48EE53544B0] +GoodName=Display List Ate My Mind Demo by Kid Stardust (PD) +CRC=887C368D D1663AA2 + +[A92F9FCD93D20778ED8FF15546BB30F5] +GoodName=Doctor V64 BIOS V1.01 +CRC=204F4E4C 59000000 + +[3509A4E21E43CEDBD704F8A1192C31DF] +GoodName=Doctor V64 BIOS V1.02 +CRC=204F4E4C 59000000 + +[A7BD2F54D9646D43A2A4AD388450223B] +GoodName=Doctor V64 BIOS V1.03 +CRC=204F4E4C 59000000 + +[30E25793ACC95529F8C69A55C6679E73] +GoodName=Doctor V64 BIOS V1.04 +CRC=204F4E4C 59000000 + +[9B69D303AFFA2CD9ABA96C21A2C21476] +GoodName=Doctor V64 BIOS V1.05 +CRC=204F4E4C 59000000 + +[ADE88A1544D469D77D4568364EF25319] +GoodName=Doctor V64 BIOS V1.08 +CRC=204F4E4C 59000000 + +[1C0FCFC7B304698F77069A5F31D27DE1] +GoodName=Doctor V64 BIOS V1.09 +CRC=204F4E4C 59000000 + +[A133F08F88F6D49E1D23D051524AD094] +GoodName=Doctor V64 BIOS V1.10 +CRC=204F4E4C 59000000 + +[601E5335E43F83676F9F341B57D03611] +GoodName=Doctor V64 BIOS V1.10r (RBubba Hack) +CRC=204F4E4C 59000000 + +[4AFA73E31031C0F582C11CDA47CC8729] +GoodName=Doctor V64 BIOS V1.11 +CRC=204F4E4C 59000000 + +[AAC7B04083FB1B9AC5B478AD89D8D3BA] +GoodName=Doctor V64 BIOS V1.21 +CRC=00000000 00000000 + +[4EAE45340300293065CEF5B598C0AC6E] +GoodName=Doctor V64 BIOS V1.22 +CRC=00000000 00000000 + +[ED9D2C04A7A0934372216ED8321EA6E3] +GoodName=Doctor V64 BIOS V1.30 +CRC=204F4E4C 59000000 + +[041813684340CE4D988B2EBA341CE5C5] +GoodName=Doctor V64 BIOS V1.31 (Blue) +CRC=204F4E4C 59000000 + +[2DF942636FB2BF924844A8F4129913BE] +GoodName=Doctor V64 BIOS V1.31 +CRC=204F4E4C 59000000 + +[B978DD8BA5F4DAC6850B7D1297EB1F11] +GoodName=Doctor V64 BIOS V1.32 +CRC=00000000 00000000 + +[F015AE0F3AD80975FB21B43EF7F14422] +GoodName=Doctor V64 BIOS V1.33 +CRC=00000000 00000000 + +[F9D9666DE2F946C9A7D6173DFADF9A81] +GoodName=Doctor V64 BIOS V1.33b +CRC=204F4E4C 59000000 + +[E60CE3D4354066CFD80129CB6C2466D5] +GoodName=Doctor V64 BIOS V1.40 +CRC=204F4E4C 59000000 + +[D62566C4A47396BFC97173D8CF468A5D] +GoodName=Doctor V64 BIOS V1.40b +CRC=00000000 00000000 + +[22134E81100D2854323B064EDD98AAC4] +GoodName=Doctor V64 BIOS V1.41 +CRC=204F4E4C 59000000 + +[25D9CDCD8C23AF6559228C4435FF0CB3] +GoodName=Doctor V64 BIOS V1.41b +CRC=00000000 00000000 + +[69A7D3A2F2805BC2FC84DB917F8AF592] +GoodName=Doctor V64 BIOS V1.50 +CRC=204F4E4C 59000000 + +[9516794650A56E60353135BB9A63C872] +GoodName=Doctor V64 BIOS V1.51 +CRC=204F4E4C 59000000 + +[FCB5472F929C8DA0DAED4C0984F8053B] +GoodName=Doctor V64 BIOS V1.52 (CH2 Hack) +CRC=204F4E4C 59000000 + +[27369BF665AD2FE9F23C6C6D202AA5E8] +GoodName=Doctor V64 BIOS V1.52 +CRC=204F4E4C 59000000 + +[941BA29D2945FA5C903FB0FC6491AC62] +GoodName=Doctor V64 BIOS V1.53 +CRC=00000000 00000000 + +[E7C2944774E1610EE6DF7358717B5DA3] +GoodName=Doctor V64 BIOS V1.60 +CRC=00000000 00000000 + +[B85FCEC60C7BEA9106BD9B9C14479EE7] +GoodName=Doctor V64 BIOS V1.61 +CRC=00000000 00000000 + +[D4BC7E3227225E303A7F6491C1DBB4CB] +GoodName=Doctor V64 BIOS V1.70 +CRC=00000000 00000000 + +[BCAC0108F0D521FF5478BA6C50B23774] +GoodName=Doctor V64 BIOS V1.71 +CRC=00000000 00000000 + +[D2DA27872F13C0BBB2D686C495F13499] +GoodName=Doctor V64 BIOS V1.72 +CRC=00000000 00000000 + +[13CD4C03FCA1BC23AE8B57885E76BCA6] +GoodName=Doctor V64 BIOS V1.73 +CRC=00000000 00000000 + +[A2604CB559D289837F718DB02AFEA85E] +GoodName=Doctor V64 BIOS V1.74 (Revive Version) +CRC=00000000 00000000 + +[8B95ABB5F6E71454FE2C415A0787A384] +GoodName=Doctor V64 BIOS V1.74 +CRC=00000000 00000000 + +[83B122B18B98B96A63C6F824833116BC] +GoodName=Doctor V64 BIOS V1.75 +CRC=00000000 00000000 + +[B444CC20AEFAD0DE4A552D8DD0486E82] +GoodName=Doctor V64 BIOS V1.76 +CRC=00000000 00000000 + +[B5D92FF099B3B74C6D0F0D75590EAC36] +GoodName=Doctor V64 BIOS V1.80 +CRC=00000000 00000000 + +[8CD8FDF74A47CA163CD23AE1D01B7E95] +GoodName=Doctor V64 BIOS V1.81 +CRC=00000000 00000000 + +[AAD6807D240FC3FF4FEDAB57135AD458] +GoodName=Doctor V64 BIOS V1.82 +CRC=00000000 00000000 + +[4121DD79CEBF67EBCA1AA2B3A7AED858] +GoodName=Doctor V64 BIOS V1.83 +CRC=00000000 00000000 + +[D3EA654D4679E0BF40BB671CA7D4A7A3] +GoodName=Doctor V64 BIOS V1.90 +CRC=00000000 00000000 + +[CF8B2C134C3FCD5A5D74402D75CA0543] +GoodName=Doctor V64 BIOS V1.91 +CRC=00000000 00000000 + +[0F83626497B7ACC4AAB3EB39CDE893D3] +GoodName=Doctor V64 BIOS V1.92 +CRC=00000000 00000000 + +[6B626C55C99CD12E88A3DB3B52372104] +GoodName=Doctor V64 BIOS V1.93 +CRC=00000000 00000000 + +[483BD87237BB38884E7E22F4981ACFDB] +GoodName=Doctor V64 BIOS V1.94 +CRC=00000000 00000000 + +[553F6E6766B85CB0247E5CA62F515C75] +GoodName=Doctor V64 BIOS V2.00 +CRC=00000000 00000000 + +[A89761018FA98E5C919F4CA0BB3E6001] +GoodName=Doctor V64 BIOS V2.00b +CRC=00000000 00000000 + +[AE36DD0BCC2F515917B0CF52AEE48AC1] +GoodName=Doctor V64 BIOS V2.01 (Red) +CRC=00000000 00000000 + +[0C91C461ED69EC1E93E9E0DEF9053546] +GoodName=Doctor V64 BIOS V2.01 +CRC=00000000 00000000 + +[BA2816F0B775099E42F124E5C43FE30C] +GoodName=Doctor V64 BIOS V2.01b +CRC=00000000 00000000 + +[DDD1958DF0330B79288B51E65E1E36A0] +GoodName=Doctor V64 BIOS V2.02 +CRC=00000000 00000000 + +[5AAA98D1FDF963FB88B3D25476924A04] +GoodName=Doctor V64 BIOS V2.02b +CRC=00000000 00000000 + +[030EAB316DC3A2D33AAC3DE15FDC4473] +GoodName=Doctor V64 BIOS V2.03 (Black) +CRC=00000000 00000000 + +[2F4E88C48823714825F35148F5B5738D] +GoodName=Doctor V64 BIOS V2.03 (Blue) +CRC=00000000 00000000 + +[7F34EB3E1363580FEA95B23A9CB1C3AF] +GoodName=Doctor V64 BIOS V2.03 (Green) +CRC=00000000 00000000 + +[A550DEBDF72B753B52882A1A573560B5] +GoodName=Doctor V64 BIOS V2.03 (Purple) +CRC=00000000 00000000 + +[014A2B82FDF9A72FC5A26A7EAF8F8176] +GoodName=Doctor V64 BIOS V2.03 (Red) +CRC=00000000 00000000 + +[41010B4BFE1F8DB801237B02A9FA265F] +GoodName=Doctor V64 BIOS V2.03 +CRC=00000000 00000000 + +[E8B403A0F0E212FA5C1220AF10D9C379] +GoodName=Donald Duck - Quack Attack (E) (M5) [!] +CRC=3DF17480 193DED5A +Players=1 +SaveType=None +Mempak=Yes +CountPerOp=3 + +[07C4944DDAAD234F1F6B0B200BEA60B2] +GoodName=Donald Duck - Quack Attack (E) (M5) [b1] +CRC=85E42D70 132BD5C2 +RefMD5=E8B403A0F0E212FA5C1220AF10D9C379 + +[3BAFF04C5DD367F362248DC627D848C1] +GoodName=Donald Duck - Quack Attack (E) (M5) [f1] (NTSC) +CRC=8A5B9018 0A661D8F +RefMD5=E8B403A0F0E212FA5C1220AF10D9C379 + +[3141A1EE8DCDE0F772E915E629823F13] +GoodName=Donchan Puzzle Hanabi de Doon! (Aleck64) +CRC=D52FE29D 8EA6A759 +SaveType=Eeprom 4KB + +[AF83E0CF36298E62E9EB2EB8C89AA710] +GoodName=Animal Crossing (Ch) (iQue) [!] +CRC=916EB31B F47097A5 + +[118E9CE360B97A6F8DAB2C9F30660BF5] +GoodName=Donkey Kong 64 (E) [!] +CRC=11936D8C 6F2C4B43 +SaveType=Eeprom 16KB +Players=4 +Rumble=Yes +CountPerOp=1 + +[428067DC7DB42DFC977A775F0A6E55B1] +GoodName=Donkey Kong 64 (E) [b1] +CRC=11936D8C 6F2C4B43 +RefMD5=118E9CE360B97A6F8DAB2C9F30660BF5 + +[C48C46362602766EA758FAAEED88AF50] +GoodName=Donkey Kong 64 (E) [f1] (Boot&Save) +CRC=1F95CAAA 047FC22A +RefMD5=118E9CE360B97A6F8DAB2C9F30660BF5 + +[7BE2AAB259C437E8BA91FF8E5903837C] +GoodName=Donkey Kong 64 (E) [f1] (Save) +CRC=1F95CAAA 047FC22A +RefMD5=118E9CE360B97A6F8DAB2C9F30660BF5 + +[5B677F4BF93D6578252FCAD2C8CEB637] +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] +GoodName=Donkey Kong 64 (U) (Kiosk Demo) [b1] +CRC=F5C21403 8FCA0710 +RefMD5=98A5836E3A5DA7BD0B5819E7498ACEA2 + +[34E6B35260F03CA72593FA373E38BBEA] +GoodName=Donkey Kong 64 (U) (Kiosk Demo) [b2] +CRC=0DD4ABAB B5A2A91E +RefMD5=98A5836E3A5DA7BD0B5819E7498ACEA2 + +[3F1A1B941E58FF977EF47B65CE359A26] +GoodName=Donkey Kong 64 (U) (Kiosk Demo) [f1] (PAL) +CRC=F5C21403 8FCA0710 +RefMD5=98A5836E3A5DA7BD0B5819E7498ACEA2 + +[9EC41ABF2519FC386CADD0731F6E868C] +GoodName=Donkey Kong 64 (U) [!] +CRC=EC58EABF AD7C7169 +SaveType=Eeprom 16KB +Players=4 +CountPerOp=1 +Rumble=Yes + +[6B4772AA1743FEAC1919618B3FC6B3E1] +GoodName=Donkey Kong 64 (U) [b1] +CRC=EC58EABF AD7C7169 +RefMD5=9EC41ABF2519FC386CADD0731F6E868C + +[4D4483C0CA3B86997E41A7032F6AD25F] +GoodName=Donkey Kong 64 (U) [f1] (Save) +CRC=CE84793D 27ECC1AD +RefMD5=9EC41ABF2519FC386CADD0731F6E868C + +[CED71061B6A8581DC0B95970D522848A] +GoodName=Donkey Kong 64 (U) [f2] +CRC=CE84793D 27ECC1AD +RefMD5=9EC41ABF2519FC386CADD0731F6E868C + +[E56EF244D61B15DBAEF474F9C0C0B23A] +GoodName=Donkey Kong 64 (U) [f3] +CRC=CED986FD 3344AC38 +RefMD5=9EC41ABF2519FC386CADD0731F6E868C + +[11DA2A2D0E91074BB8FF1FCB029535FD] +GoodName=Donkey Kong 64 - Tag Anywhere (V5) (U) +CRC=31739C69 A99E3CB2 +RefMD5=9EC41ABF2519FC386CADD0731F6E868C + +[190CCCA6526DC4A1F611E3B40F5131C0] +GoodName=Doom 64 (E) [!] +CRC=2C739EAC 9EF77726 +Players=1 +SaveType=None +Mempak=Yes + +[B482F51B616F4337F1B3BF5EFDD650D4] +GoodName=Doom 64 (E) [b1] +CRC=2C739EAC 9EF77726 +RefMD5=190CCCA6526DC4A1F611E3B40F5131C0 + +[06F15EF2228C1B1147C41DCCAA07D9DE] +GoodName=Doom 64 (J) [!] +CRC=7AA65B36 FDCEE5AD +Players=1 +SaveType=None +Mempak=Yes + +[053BB6D2E14D67F0FB0B509F2A6B4485] +GoodName=Doom 64 (J) [b1] +CRC=7AA65B36 FDCEE5AD +RefMD5=06F15EF2228C1B1147C41DCCAA07D9DE + +[B67748B64A2CC7EFD2F3AD4504561E0E] +GoodName=Doom 64 (U) (V1.0) [!] +CRC=A83E101A E937B69D +Players=1 +SaveType=None +Mempak=Yes + +[BF710F7D1D51EC89AC3F58022B2B5D7F] +GoodName=Doom 64 (U) (V1.0) [T+Bra1.0_Doom64BR] +CRC=B01A1DAB 7F7827E3 +RefMD5=B67748B64A2CC7EFD2F3AD4504561E0E + +[6EACFE4F39265F24FB8145FDED8272F6] +GoodName=Doom 64 (U) (V1.0) [b1] +CRC=A83E101A E937B69D +RefMD5=B67748B64A2CC7EFD2F3AD4504561E0E + +[81FD532B1C7C2CCD687E56696E073C83] +GoodName=Doom 64 (U) (V1.0) [b2] +CRC=A83E101A E937B69D +RefMD5=B67748B64A2CC7EFD2F3AD4504561E0E + +[7497ADADADA89230827C06E4BFFBBBD8] +GoodName=Doom 64 (U) (V1.0) [o1] +CRC=A83E101A E937B69D +RefMD5=B67748B64A2CC7EFD2F3AD4504561E0E + +[4DC885150DFEC67ACDD807F9FFE9596E] +GoodName=Doom 64 (U) (V1.0) [t1] +CRC=13D0EE29 D57A41AD +RefMD5=B67748B64A2CC7EFD2F3AD4504561E0E + +[29E85B9D9072AC232CEB87EFE826269A] +GoodName=Doom 64 (U) (V1.0) [t2] +CRC=13D0EE29 D57A41AD +RefMD5=B67748B64A2CC7EFD2F3AD4504561E0E + +[1B1378BB9EE819F740550F566745AF73] +GoodName=Doom 64 (U) (V1.1) [!] +CRC=423E96F4 CE88F05B +Players=1 +SaveType=None +Mempak=Yes + +[C2166455E94E89E9E3AB612B4377C443] +GoodName=Doraemon - Nobita to 3tsu no Seireiseki (J) [!] +CRC=BFF7B1C2 AEBF148E +Players=4 + +[989E7B15D24649B784813E1A07DF6887] +GoodName=Doraemon - Nobita to 3tsu no Seireiseki (J) [b1] +CRC=BFF7B1C2 AEBF148E +RefMD5=C2166455E94E89E9E3AB612B4377C443 + +[7E0DA017551101DA1C4FB6A0C49A2328] +GoodName=Doraemon - Nobita to 3tsu no Seireiseki (J) [b2] +CRC=BFF7B1C2 AEBF148E +RefMD5=C2166455E94E89E9E3AB612B4377C443 + +[BE0000D3415787F9920E178942C297C5] +GoodName=Doraemon - Nobita to 3tsu no Seireiseki (J) [b3] +CRC=BFF7B1C2 AEBF148E +RefMD5=C2166455E94E89E9E3AB612B4377C443 + +[C2909D5799099819E9A7ECE3CD4737FC] +GoodName=Doraemon - Nobita to 3tsu no Seireiseki (J) [t1] +CRC=55C0515C 901DA4A7 +RefMD5=C2166455E94E89E9E3AB612B4377C443 + +[0580D96A71671C9E6972FDCF5897CC26] +GoodName=Doraemon 2 - Nobita to Hikari no Shinden (J) [!] +CRC=B6306E99 B63ED2B2 +SaveType=Eeprom 16KB +Players=1 +Rumble=Yes + +[7CC16A6090CAC3749DD6B71CA7A58605] +GoodName=Doraemon 2 - Nobita to Hikari no Shinden (J) [b1] +CRC=B6306E99 B63ED2B2 +RefMD5=0580D96A71671C9E6972FDCF5897CC26 + +[5A28008B05923016EA411BACE06EF32A] +GoodName=Doraemon 2 - Nobita to Hikari no Shinden (J) [b2] +CRC=4E30BD3A B77D6DFB +RefMD5=0580D96A71671C9E6972FDCF5897CC26 + +[7E4BCA92DA50145C9906B2A72F9351B5] +GoodName=Doraemon 2 - Nobita to Hikari no Shinden (J) [f1] (PAL) +CRC=4E30BD3A B77D6DFB +RefMD5=0580D96A71671C9E6972FDCF5897CC26 + +[58ADC17903754FEBF77DC9CD3DB8B7D8] +GoodName=Doraemon 2 - Nobita to Hikari no Shinden (J) [f2] +CRC=4E30BD3A B77D6DFB +RefMD5=0580D96A71671C9E6972FDCF5897CC26 + +[BEFA319919474BAE05DFCB570CC0CF31] +GoodName=Doraemon 2 - Nobita to Hikari no Shinden (J) [t1] +CRC=4ECEB1DE 552B6E88 +RefMD5=0580D96A71671C9E6972FDCF5897CC26 + +[A4A1D490BA67831775FC381B846E2168] +GoodName=Doraemon 3 - Nobita no Machi SOS! (J) [!] +CRC=A8275140 B9B056E8 +SaveType=Eeprom 16KB +Players=1 +Rumble=Yes + +[FB7565FE1EAAED1CACFAE3B011FA6CB6] +GoodName=Doraemon 3 - Nobita no Machi SOS! (J) [f1] (PAL-NTSC) +CRC=D8059804 92739B11 +RefMD5=A4A1D490BA67831775FC381B846E2168 + +[A4F7C57C180297B2E7BA5A5FEB44FE0B] +GoodName=Doubutsu no Mori (J) [!] +CRC=BD8E206D 98C35E1C +Players=1 +SaveType=Flash RAM +Mempak=Yes + +[4AB8D6535028805F5794D3F01003CFD5] +GoodName=Doubutsu no Mori (J) [T+Eng2007-08-10_Brandon Dixon] +CRC=BD8E206D 98C35E1C +RefMD5=A4F7C57C180297B2E7BA5A5FEB44FE0B + +[01BDCC854D0AB798500E7BC31A24D94F] +GoodName=Doubutsu no Mori (J) [T+Eng2010-12-02_Zoinkity] +CRC=0290AEB9 67A3B6C1 +RefMD5=A4F7C57C180297B2E7BA5A5FEB44FE0B + +[7DDBCA3F642CB4CAA780E81733C94037] +GoodName=Doubutsu no Mori (J) [T+Eng90%] +CRC=8F0CC36D C738259E +RefMD5=A4F7C57C180297B2E7BA5A5FEB44FE0B + +[7C58DB7EE170912A2DF84E67A489058A] +GoodName=Doubutsu no Mori (J) [T-Eng2007-02-08_Brandon Dixon] +CRC=BD8E206D 98C35E1C +RefMD5=A4F7C57C180297B2E7BA5A5FEB44FE0B + +[5E2A5C56CA1A0CCAEA3AE5F852E0C58D] +GoodName=Doubutsu no Mori (J) [T-Eng2007-02-09_Brandon Dixon] +CRC=BD8E206D 98C35E1C +RefMD5=A4F7C57C180297B2E7BA5A5FEB44FE0B + +[0AA8E4B96EBB5B8A5CF91CFB04BC3741] +GoodName=Doubutsu no Mori (J) [T-Eng2007-03-22_Brandon Dixon] +CRC=BD8E206D 98C35E1C +RefMD5=A4F7C57C180297B2E7BA5A5FEB44FE0B + +[DD291B9C65420FD892107F6C665B7A45] +GoodName=Dr. Mario 64 (Ch) (iQue) [!] +CRC=EF62A343 11E41E37 +Players=4 + +[FE49420725F9C1CF0F15BA5682D27709] +GoodName=Dr. Mario 64 (Ch) (V2) (iQue) (Manual) [!] + +[B524D10A8A26764EB2198ACEC3F09948] +GoodName=Dr. Mario 64 (Ch) (V4) (iQue) (Manual) [!] + +[1A7936367413E5D6874ABDA6D623AD32] +GoodName=Dr. Mario 64 (U) [!] +CRC=769D4D13 DA233FFE +Players=4 +SaveType=Eeprom 4KB + +[0AD0800D351F77EC31092096D58C25F0] +GoodName=Dragon King by CrowTRobo (PD) [b1] +CRC=19E0E54C CB721FD2 + +[944ECED50E57D46779576F732CB27DC0] +GoodName=Dragon King by CrowTRobo (PD) +CRC=19E0E54C CB721FD2 + +[770D0D2BB08235613569667A284BCA2C] +GoodName=Dragon Sword 64 (E) (Prototype) +CRC=40DFEDA0 3AA09CB2 + +[64011DD56FF84CF9EB46153E7AECCD26] +GoodName=Dragon Sword 64 (U) (Prototype) (1999-08-25) +CRC=AE6b1E11 B7CBD69E + +[F120FADB52B414EB4FB7D13092AC3CDB] +GoodName=Dual Heroes (E) [!] +CRC=B6524461 ED6D04B1 +SaveType=None +Mempak=Yes +Players=2 + +[B01D031BE1789565E2B8A44CD76B96C6] +GoodName=Dual Heroes (E) [b1] +CRC=B6524461 ED6D04B1 +RefMD5=F120FADB52B414EB4FB7D13092AC3CDB + +[DFEBF3A9570B95D95CA6BE2CE8311D1D] +GoodName=Dual Heroes (E) [b2] +CRC=B6524461 ED6D04B1 +RefMD5=F120FADB52B414EB4FB7D13092AC3CDB + +[B406AD1694D65725FD31A054F6ECE213] +GoodName=Dual Heroes (E) [f1] (NTSC) +CRC=926C2E3B 9829A216 +RefMD5=F120FADB52B414EB4FB7D13092AC3CDB + +[E7652ED5CECEB5B1BC14495C58546D1C] +GoodName=Dual Heroes (J) [!] +CRC=056EAB63 C215FCD5 +Players=2 +SaveType=None +Mempak=Yes + +[A7D3E42EFFD6E7935DA7C9A6B6899CAC] +GoodName=Dual Heroes (J) [o1] +CRC=056EAB63 C215FCD5 +RefMD5=E7652ED5CECEB5B1BC14495C58546D1C + +[54C610270D3F5EEA39BC6A8F73B3B909] +GoodName=Dual Heroes (J) [o2] +CRC=056EAB63 C215FCD5 +RefMD5=E7652ED5CECEB5B1BC14495C58546D1C + +[923D65E69F51858C697E0E5759CD038B] +GoodName=Dual Heroes (U) [!] +CRC=A62230C3 F0834488 +Players=2 +SaveType=None +Mempak=Yes + +[E3EF8D7ACCA9CCB551C26B0F879E6B25] +GoodName=Dual Heroes (U) [b1] +CRC=A62230C3 F0834488 +RefMD5=923D65E69F51858C697E0E5759CD038B + +[02192B4B3797983BBE5E452336584208] +GoodName=Duck Dodgers Starring Daffy Duck (U) (M3) [!] +CRC=FBB9F1FA 6BF88689 +Players=1 +SaveType=Eeprom 4KB +CountPerOp=1 +Rumble=Yes + +[B5A5A71483679DCCACBDA770647A9DBF] +GoodName=Duck Dodgers Starring Daffy Duck (U) (M3) [t1] +CRC=83E7E0D2 B5B7E503 +RefMD5=02192B4B3797983BBE5E452336584208 + +[86E98AACA0D90BF744DA090539BA4AD8] +GoodName=Duke Nukem - ZER0 H0UR (E) [!] +CRC=DC36626A 3F3770CB +Players=4 +SaveType=None +Mempak=Yes +CountPerOp=1 +Rumble=Yes + +[51A1EEE441240229BEB2E6CD8FAB285C] +GoodName=Duke Nukem - ZER0 H0UR (E) [f1] (NTSC) +CRC=0BD8008B 26051E1D +RefMD5=86E98AACA0D90BF744DA090539BA4AD8 + +[E2B73FEB0843874EA831A2E0076FCB72] +GoodName=Duke Nukem - ZER0 H0UR (F) [!] +CRC=32CA974B B2C29C50 +Players=4 +SaveType=None +Mempak=Yes +CountPerOp=1 +Rumble=Yes + +[026789D47DB5FE202A76F89797B33AC7] +GoodName=Duke Nukem - ZER0 H0UR (U) [!] +CRC=04DAF07F 0D18E688 +Players=4 +SaveType=None +Mempak=Yes +CountPerOp=1 +Rumble=Yes + +[69ED326664E48BAA9CE743E6E9C450DA] +GoodName=Duke Nukem - ZER0 H0UR (U) [b1] +CRC=04DAF07F 0D18E688 +RefMD5=026789D47DB5FE202A76F89797B33AC7 + +[75239D11AEE906C9ABEA752BA1E2AA00] +GoodName=Duke Nukem - ZER0 H0UR (U) [b2] +CRC=BCEAF9B7 F84FF876 +RefMD5=026789D47DB5FE202A76F89797B33AC7 + +[4446E99E8D43E1B7557412ACEA918F68] +GoodName=Duke Nukem - ZER0 H0UR (U) [b3] +CRC=BCEAF9B7 F84FF876 +RefMD5=026789D47DB5FE202A76F89797B33AC7 + +[BD4E03620567C6291F11B9217AC67C28] +GoodName=Duke Nukem - ZER0 H0UR (U) [b4] +CRC=04DAF07F 0D18E688 +RefMD5=026789D47DB5FE202A76F89797B33AC7 + +[A3D49AAC6BC8EEA0D707042A68D2D48C] +GoodName=Duke Nukem - ZER0 H0UR (U) [t1] +CRC=BCEAF9B7 F84FF876 +RefMD5=026789D47DB5FE202A76F89797B33AC7 + +[8657CBA95C409B74C1F5632CBC36643F] +GoodName=Duke Nukem 64 (E) [!] +CRC=57BFF74D DE747743 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[BB2472B3F8A41FBF3AEC3CCEF7EA8C78] +GoodName=Duke Nukem 64 (E) (Beta) +CRC=FF14C1DA 167FDE92 +RefMD5=8657CBA95C409B74C1F5632CBC36643F + +[A6AC9D140112BD7A3AA8A5ABA79EBD88] +GoodName=Duke Nukem 64 (E) [b1] +CRC=57BFF74D DE747743 +RefMD5=8657CBA95C409B74C1F5632CBC36643F + +[31F08F1D2F789C5D698B7E05F287E7AE] +GoodName=Duke Nukem 64 (E) [o1] +CRC=57BFF74D DE747743 +RefMD5=8657CBA95C409B74C1F5632CBC36643F + +[E2E79C7167BDB26E176D220904739C91] +GoodName=Duke Nukem 64 (F) +CRC=1E12883D D3B92718 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[C7F1A43764A26DA2E43F2A36A5F76E4C] +GoodName=Duke Nukem 64 (U) [!] +CRC=A273AB56 DA33DB9A +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[9BE63892A2AA2B20B75B3AC4E7B7DCDF] +GoodName=Duke Nukem 64 (U) [b1] +CRC=3F84EB47 141964BF +RefMD5=C7F1A43764A26DA2E43F2A36A5F76E4C + +[685EB7D3D1F2C82932EDF7B476A6E21B] +GoodName=Duke Nukem 64 (U) [b2] +CRC=A273AB56 DA33DB9A +RefMD5=C7F1A43764A26DA2E43F2A36A5F76E4C + +[D13D7E9AA29D972CB93C39A15F304FAA] +GoodName=Duke Nukem 64 (U) [b3] +CRC=A273AB56 DA33DB9A +RefMD5=C7F1A43764A26DA2E43F2A36A5F76E4C + +[82FE3916997DA14A02C2301AC2B5E321] +GoodName=Duke Nukem 64 (U) [h1C] +CRC=A273AB56 DA33DB9A +RefMD5=C7F1A43764A26DA2E43F2A36A5F76E4C + +[6F14B999499E90761D8444F784564AB3] +GoodName=Duke Nukem 64 (U) [o1] +CRC=A273AB56 DA33DB9A +RefMD5=C7F1A43764A26DA2E43F2A36A5F76E4C + +[557F89A263B2028936753956F7902299] +GoodName=Duke Nukem 64 (U) [t1] +CRC=3F84EB47 141964BF +RefMD5=C7F1A43764A26DA2E43F2A36A5F76E4C + +[A6DF7D8C1E2DAB58496EF633AC09366E] +GoodName=Duke Nukem 64 (U) [t2] +CRC=3F84EB47 141964BF +RefMD5=C7F1A43764A26DA2E43F2A36A5F76E4C + +[8B7E6FF3453F660DCFC7B968E622E7C9] +GoodName=Duke Nukem 64 (U) [t3] +CRC=3F84EB47 141964BF +RefMD5=C7F1A43764A26DA2E43F2A36A5F76E4C + +[9A008AF4E90D7C55F21039F4E82170EF] +GoodName=Dynamix Intro (Hidden Song) by Widget and Immortal (PD) +CRC=B8E73356 040E42EC + +[5809670A42CA34D39A39598EFA82F5F3] +GoodName=Dynamix Intro by Widget and Immortal (PD) +CRC=086E91C9 89F47C51 +Players=0 +Status=3 +Rumble=No +SaveType=None + +[E06B804B5A8809C42E99B229106CC813] +GoodName=Dynamix Readme by Widget and Immortal (PD) +CRC=186CC1A9 A0DE4C8D +RefMD5=5809670A42CA34D39A39598EFA82F5F3 + +[F32E61E30C5BC232A01E52F8BC2EEF07] +GoodName=Dynamix Intro by Widget and Immortal (PD) [h1C] +CRC=086E91C9 89F47C51 +RefMD5=5809670A42CA34D39A39598EFA82F5F3 + +[1830EDE2557E8685E6F76D05CC65076A] +GoodName=ECW Hardcore Revolution (E) [!] +CRC=8C38E5DB B37C27D7 +SaveType=None +Mempak=Yes +Players=4 +Rumble=Yes + +[5D1E41AA28169E71B4919FA08F1ACD9B] +GoodName=ECW Hardcore Revolution (G) [!] +CRC=2138A076 408AD8B2 +SaveType=None +Mempak=Yes +Players=4 +Rumble=Yes + +[91545C2642DB6349B8D18BF0BEE29162] +GoodName=ECW Hardcore Revolution (E) [b1] +CRC=8C38E5DB B37C27D7 +RefMD5=1830EDE2557E8685E6F76D05CC65076A + +[8EEBB16B7A4D39AE8BC8CCCBC41F0A01] +GoodName=ECW Hardcore Revolution (U) [!] +CRC=BDF9766D BD068D70 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[BF2DF4B86FAA2181A7ACFE2643FA2293] +GoodName=Earthworm Jim 3D (E) (M6) [!] +CRC=492B9DE8 C6CCC81C +Players=1 +SaveType=Eeprom 4KB + +[97EA079ECF105EA16654A855644D870A] +GoodName=Earthworm Jim 3D (E) (M6) [b1] +CRC=492B9DE8 C6CCC81C +RefMD5=BF2DF4B86FAA2181A7ACFE2643FA2293 + +[980DFB38AD9A883119DE135F45B7DB36] +GoodName=Earthworm Jim 3D (U) [!] +CRC=DF574191 9EB5123D +Players=1 +SaveType=Eeprom 4KB + +[554EE4BF15388DDE586DE90AC72EF5FA] +GoodName=Earthworm Jim 3D (U) [T+Rus] +CRC=34DBB6CF EA06789D +RefMD5=980DFB38AD9A883119DE135F45B7DB36 + +[B27336A278658AC6D62AB6C4C3FB1DB6] +GoodName=Earthworm Jim 3D (U) [f1] (PAL) +CRC=04853364 948ACF82 +RefMD5=980DFB38AD9A883119DE135F45B7DB36 + +[6B870EBEDCBD81B9FF369008F904C1CD] +GoodName=Earthworm Jim 3D (U) [hI] +CRC=04842D98 1A9FF551 +RefMD5=980DFB38AD9A883119DE135F45B7DB36 + +[60F0CBE10DCE67FDD6527A78B51DCCBC] +GoodName=Earthworm Jim 3D (U) [t1] +CRC=0484CD98 1AFE0B59 +RefMD5=980DFB38AD9A883119DE135F45B7DB36 + +[935DD85AD198BBDE92161CDCE47CBFB3] +GoodName=Eikou no Saint Andrews (J) [!] +CRC=0DED0568 1502515E +Players=4 +Mempak=Yes + +[936DB74AE766BB1219E8A712F0D06E4A] +GoodName=Eikou no Saint Andrews (J) [b1] +CRC=0DED0568 1502515E +RefMD5=935DD85AD198BBDE92161CDCE47CBFB3 + +[0F7C52AD7C7C88103960F44FCD0B119A] +GoodName=Eikou no Saint Andrews (J) [b2] +CRC=0DED0568 1502515E +RefMD5=935DD85AD198BBDE92161CDCE47CBFB3 + +[08CCA8D372EA8C38148F77AB5A03354D] +GoodName=Eikou no Saint Andrews (J) [h1C] +CRC=0DED0568 1502515E +RefMD5=935DD85AD198BBDE92161CDCE47CBFB3 + +[CEC824B5DA28B974B1562338EB728805] +GoodName=Eikou no Saint Andrews (J) [h2C] +CRC=0DED0568 1502515E +RefMD5=935DD85AD198BBDE92161CDCE47CBFB3 + +[7EB0C27F162B74032C3823E721EDA00B] +GoodName=Eleven Beat - World Tournament (Aleck64) +CRC=6D9D1FE4 84D10BEA + +[15DF97A59B2354B130DEC3FB86BBA513] +GoodName=Elmo's Letter Adventure (U) [!] +CRC=F2A653CB 60633B3B +SaveType=None +Players=1 +CountPerOp=1 + +[F733453ED26AFA0ACA8D3EB3B5B6D8EA] +GoodName=Elmo's Number Journey (U) [!] +CRC=02B1538F C94B88D0 +Players=1 +SaveType=None + +[9B456ACB96291FC8B55232A08AE03346] +GoodName=Eltale Monsters (J) [!] +CRC=E13AE2DC 4FB65CE8 +Players=1 +SaveType=None +Mempak=Yes + +[752EF6D2C2A6DBBB8CBAEFB596412C1D] +GoodName=Eltale Monsters (J) [b1] +CRC=E13AE2DC 4FB65CE8 +RefMD5=9B456ACB96291FC8B55232A08AE03346 + +[D42CC78A2BF0D34518B8E0D0439E432E] +GoodName=Eltale Monsters (J) [b2] +CRC=E13AE2DC 4FB65CE8 +RefMD5=9B456ACB96291FC8B55232A08AE03346 + +[75A8F25B679A0D148F0D8E1143104845] +GoodName=Eurasia First N64 Intro by Sispeo (PD) +CRC=52F22511 B9D85F75 + +[761DC0DE0913D697ED1F9899948552BB] +GoodName=Eurasia Intro by Ste (PD) [b1] +CRC=52F22511 B9D85F75 + +[F7E6C9CFF1BC16B0DEDA0ECEFC5C3DFB] +GoodName=Eurasia Intro by Ste (PD) +CRC=93A94333 5A613C39 + +[F1D0406A74AD74BE5891620B7FE6640D] +GoodName=Evek - V64jr Save Manager by WT_Riker (PD) +CRC=D49DFF90 8DB53A8C + +[F4B41863440137C6A3BA22942F3E0DA2] +GoodName=Excitebike 64 (Ch) (iQue) [!] +Players=4 +CountPerOp=1 + +[876F87C91A4B6339DAA8FC1F41EB7ACD] +GoodName=Excitebike 64 (Ch) (iQue) (Manual) [!] + +[8FA253FD69B73DF9A831EF2F731491F2] +GoodName=Excitebike 64 (E) [!] +CRC=202A8EE4 83F88B89 +SaveType=Eeprom 16KB +Players=4 +CountPerOp=1 +Mempak=Yes +Rumble=Yes + +[BF15A61AFF71C93BF5E05243F57BCA1D] +GoodName=Excitebike 64 (J) [!] +CRC=861C3519 F6091CE5 +SaveType=Eeprom 16KB +Players=4 +Mempak=Yes +Rumble=Yes + +[E0018C33346714B63A55C0E040F23DEA] +GoodName=Excitebike 64 (U) (Kiosk Demo) [!] +CRC=AF754F7B 1DD17381 +SaveType=Eeprom 16KB +Mempak=Yes +Rumble=Yes + +[7200D1C1CF489FAFFF767729F215E6E6] +GoodName=Excitebike 64 (U) (V1.0) [!] +CRC=07861842 A12EBC9F +SaveType=Eeprom 16KB +Players=4 +CountPerOp=1 +Mempak=Yes +Rumble=Yes + +[496929EA74183198D121035EA808C480] +GoodName=Excitebike 64 (U) (V1.0) [b1] +CRC=07861842 A12EBC9F +RefMD5=7200D1C1CF489FAFFF767729F215E6E6 + +[48D1FA279FEA4C99CFEEC90E9AD1668F] +GoodName=Excitebike 64 (U) (V1.0) [f1] +CRC=E5B7F405 2C4462BF +RefMD5=7200D1C1CF489FAFFF767729F215E6E6 + +[285D3277D28CA3B9A5A2BE8971CCD767] +GoodName=Excitebike 64 (U) (V1.0) [f2] (Save) +CRC=E5B7F405 2C4462BF +RefMD5=7200D1C1CF489FAFFF767729F215E6E6 + +[21954E4E404D9E87DBDB87DD309F3E94] +GoodName=Excitebike 64 (U) (V1.1) [!] +CRC=F9D411E3 7CB29BC0 +SaveType=Eeprom 16KB +Players=4 +CountPerOp=1 +Mempak=Yes +Rumble=Yes + +[6DCFDE0423D1DB58EA9E6A8F1BFFD849] +GoodName=Explode Demo by NaN (PD) +CRC=3E5D6755 9AE4BD3B + +[3B2CA0DA0810C95B31DF8C1FB8811BE2] +GoodName=Extreme-G (E) (M5) [!] +CRC=8E9D834E 1E8B29A9 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[BF72E10EB79E00E095829112576F01FE] +GoodName=Extreme-G (E) (M5) [b1] +CRC=8E9D834E 1E8B29A9 +RefMD5=3B2CA0DA0810C95B31DF8C1FB8811BE2 + +[A059E27DE410BDA05D8603C22776979F] +GoodName=Extreme-G (E) (M5) [b2] +CRC=8E9D834E 1E8B29A9 +RefMD5=3B2CA0DA0810C95B31DF8C1FB8811BE2 + +[B74A059D227830C606BA79134278F55E] +GoodName=Extreme-G (E) (M5) [b3] +CRC=8E9D834E 1E8B29A9 +RefMD5=3B2CA0DA0810C95B31DF8C1FB8811BE2 + +[2257945EABC008E4D6464196B288D5BF] +GoodName=Extreme-G (E) (M5) [b4] +CRC=8E9D834E 1E8B29A9 +RefMD5=3B2CA0DA0810C95B31DF8C1FB8811BE2 + +[972D0468CEB1221214ADED7181DA7853] +GoodName=Extreme-G (E) (M5) [h1C] +CRC=8E9D834E 1E8B29A9 +RefMD5=3B2CA0DA0810C95B31DF8C1FB8811BE2 + +[A7CD65E5A4A8838D1CD452BA66E74DF6] +GoodName=Extreme-G (J) [!] +CRC=EE802DC4 690BD57D +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[3E660D3F991C0529E90BFEC0244DB31A] +GoodName=Extreme-G (U) [!] +CRC=FDA245D2 A74A3D47 +SaveType=None +Mempak=Yes +Players=4 +Rumble=Yes + +[6D954294E254E239B3EA694C2D9ADFF9] +GoodName=Extreme-G (U) [h1C] +CRC=FDA245D2 A74A3D47 +RefMD5=3E660D3F991C0529E90BFEC0244DB31A + +[E5D2C7CE59282C0D716DD67CA787CF7B] +GoodName=Extreme-G (U) [o1] +CRC=FDA245D2 A74A3D47 +RefMD5=3E660D3F991C0529E90BFEC0244DB31A + +[B760D4C35303C74B893F1168415D743D] +GoodName=Extreme-G (U) [t1] +CRC=9FD881BC 0A62D002 +RefMD5=3E660D3F991C0529E90BFEC0244DB31A + +[BB7F98E657FB4B5FCC7DC04BD72E2D2B] +GoodName=Extreme-G XG2 (E) (M5) [!] +CRC=1185EC85 4B5A7731 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[F17884A2C16FB6FD11A74D65B1388B4A] +GoodName=Extreme-G XG2 (J) [!] +CRC=399B9B81 D533AD11 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[44FE06BA3686C02A7988F27600A533DA] +GoodName=Extreme-G XG2 (U) [!] +CRC=5CD4150B 470CC2F1 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[B0F9C3EC65C1C88A43C694EBF429E008] +GoodName=Extreme-G XG2 (U) [t1] +CRC=21910973 0F2E70D2 +RefMD5=44FE06BA3686C02A7988F27600A533DA + +[A6BD93EA576CDF8569F68171452F7E8A] +GoodName=F-1 Pole Position 64 (E) (M3) [!] +CRC=FDD248B2 569A020E +Players=1 +SaveType=None +Mempak=Yes + +[ACBB37B24238F82B2333B710CBEE388A] +GoodName=F-1 Pole Position 64 (E) (M3) [b1] +CRC=FDD248B2 569A020E +RefMD5=A6BD93EA576CDF8569F68171452F7E8A + +[049DB657F4223D949F56E9DC5B6A9180] +GoodName=F-1 Pole Position 64 (U) (M3) [!] +CRC=AE82687A 9A3F388D +Players=1 +SaveType=None +Mempak=Yes + +[6CE5D16E977B1D4E0E71E209B2932099] +GoodName=F-1 Pole Position 64 (U) (M3) [b1] +CRC=AE82687A 9A3F388D +RefMD5=049DB657F4223D949F56E9DC5B6A9180 + +[C8C14D748679AE6F8FF1A62C4AD3B61E] +GoodName=F-1 Pole Position 64 (U) (M3) [b2] +CRC=AE82687A 9A3F388D +RefMD5=049DB657F4223D949F56E9DC5B6A9180 + +[9E684FDCAC7B5999CC863084DECA463D] +GoodName=F-1 Pole Position 64 (U) (M3) [h1C] +CRC=AE82687A 9A3F388D +RefMD5=049DB657F4223D949F56E9DC5B6A9180 + +[9FBE3363DA6C146EF2E29605BCA834FF] +GoodName=F-1 World Grand Prix (E) (Prototype) [!] +CRC=CC3CC8B3 0EC405A4 +Players=2 +SaveType=Eeprom 4KB +Rumble=Yes + +[08B8942E977A81CAF81DAC2237E1AA65] +GoodName=F-1 World Grand Prix (E) (Prototype) [h1C] +CRC=CC3CC8B3 0EC405A4 +RefMD5=9FBE3363DA6C146EF2E29605BCA834FF + +[FAC450EAFF8FA46A1414DB02E6EEAB9F] +GoodName=F-1 World Grand Prix (E) [!] +CRC=C006E3C0 A67B4BBB +Players=2 +SaveType=Eeprom 4KB +Rumble=Yes + +[35F6C42D5A9284688284C24250F4D6BE] +GoodName=F-1 World Grand Prix (F) [!] +CRC=B70BAEE5 3A5005A8 +Players=2 +SaveType=Eeprom 4KB +Rumble=Yes + +[A8C78454C70BD73375AAF69C4078D5DA] +GoodName=F-1 World Grand Prix (G) [!] +CRC=38442634 66B3F060 +Players=2 +SaveType=Eeprom 4KB +Rumble=Yes + +[AA15FA62A776917E594A17B49BBC6980] +GoodName=F-1 World Grand Prix (G) [b1] +CRC=38442634 66B3F060 +RefMD5=A8C78454C70BD73375AAF69C4078D5DA + +[43115145F2DC0F3D0C6091D05CB9FA52] +GoodName=F-1 World Grand Prix (G) [b1][o1] +CRC=38442634 66B3F060 +RefMD5=A8C78454C70BD73375AAF69C4078D5DA + +[38B0DB4916328672ED592759FFB1F09C] +GoodName=F-1 World Grand Prix (G) [h1C] +CRC=38442634 66B3F060 +RefMD5=A8C78454C70BD73375AAF69C4078D5DA + +[3CEE1895A80005940887C9830B09DDE6] +GoodName=F-1 World Grand Prix (G) [o1] +CRC=38442634 66B3F060 +RefMD5=A8C78454C70BD73375AAF69C4078D5DA + +[6E5858A47CB42F9B1CB26042BA229EF6] +GoodName=F-1 World Grand Prix (G) [o1][h1C] +CRC=38442634 66B3F060 +RefMD5=A8C78454C70BD73375AAF69C4078D5DA + +[F248F0AAE609111BA9DFF9FD7AFBC485] +GoodName=F-1 World Grand Prix (J) [!] +CRC=64BF47C4 F4BD22BA +Players=2 +SaveType=Eeprom 4KB +Rumble=Yes + +[7DFE40E387971269F38FE3CBE803567A] +GoodName=F-1 World Grand Prix (J) [h1C] +CRC=64BF47C4 F4BD22BA +RefMD5=F248F0AAE609111BA9DFF9FD7AFBC485 + +[A81B1DE864DF3F4BB0903760BE673F21] +GoodName=F-1 World Grand Prix (U) [!] +CRC=CC3CC8B3 0EC405A4 +SaveType=Eeprom 4KB +Players=2 +Rumble=Yes + +[4E450DD2899FE7434110E30E19DD10A2] +GoodName=F-1 World Grand Prix (U) [h1C] +CRC=CC3CC8B3 0EC405A4 +RefMD5=A81B1DE864DF3F4BB0903760BE673F21 + +[05426547E5AD9DBF88CF0A401032079D] +GoodName=F-1 World Grand Prix (U) [h2C] +CRC=CC3CC8B3 0EC405A4 +RefMD5=A81B1DE864DF3F4BB0903760BE673F21 + +[BC0FD2468AC7769A37C3C58CD5699585] +GoodName=F-1 World Grand Prix II (E) (M4) [!] +CRC=07C1866E 5775CCDE +Players=2 +Rumble=Yes + +[D9B59E463A73FA880E6682A08D1C3071] +GoodName=F-1 World Grand Prix II (E) (M4) [f1] (NTSC) +CRC=67C38660 94038DC6 +RefMD5=BC0FD2468AC7769A37C3C58CD5699585 + +[E94A9142B1D981A6556747BA147E1A19] +GoodName=F-1 World Grand Prix II (E) (M4) [h1C] +CRC=07C1866E 5775CCDE +RefMD5=BC0FD2468AC7769A37C3C58CD5699585 + +[4024477AAED7DD5FF5EA60BF568123B7] +GoodName=F-ZERO X (Ch) (iQue) [!] +Players=4 + +[8400C0875E16F599C1B7FC433E339D58] +GoodName=F-ZERO X (Ch) (V2) (iQue) (Manual) [!] + +[9729FC397E8D178EA974869E07DF0502] +GoodName=F-ZERO X (Ch) (V4) (iQue) (Manual) [!] + +[EE79A8FE287B5DCAEA584439363342FC] +GoodName=F-ZERO X (E) [!] +CRC=776646F6 06B9AC2B +Players=4 +SaveType=SRAM +Rumble=Yes + +[0722E679F9695D9E5F1D2823DC7D8004] +GoodName=F-ZERO X (E) [b1] +CRC=776646F6 06B9AC2B +RefMD5=EE79A8FE287B5DCAEA584439363342FC + +[99DC3FF78356CE77CB240AC7782EE6E5] +GoodName=F-ZERO X (E) [b2] +CRC=DAA6CA7D 56AA4394 +RefMD5=EE79A8FE287B5DCAEA584439363342FC + +[2E95E5833894A6E1E3D109E3B3D809F1] +GoodName=F-ZERO X (E) [b3] +CRC=EC986EA9 EB463E4A +RefMD5=EE79A8FE287B5DCAEA584439363342FC + +[308384EEEB6A88B5B498179E7484944F] +GoodName=F-ZERO X (E) [b4] +CRC=DAA6CA7D 56AA4394 +RefMD5=EE79A8FE287B5DCAEA584439363342FC + +[D1368C0E3869B85947A55C3DA6FFCA10] +GoodName=F-ZERO X (E) [f1] +CRC=DAA6CA7D 56AA4394 +RefMD5=EE79A8FE287B5DCAEA584439363342FC + +[ACE58F325D5EECBE033B21F2C7BFE870] +GoodName=F-ZERO X (E) [h1C] +CRC=776646F6 06B9AC2B +RefMD5=EE79A8FE287B5DCAEA584439363342FC + +[58D200D43620007314304F4E6C9E6528] +GoodName=F-ZERO X (J) [!] +CRC=4D3E622E 9B828B4E +Players=4 +SaveType=SRAM +Rumble=Yes + +[C14AE14C6DE0DCA126C423C4ADBEE315] +GoodName=F-ZERO X (J) [b1] +CRC=076C5C15 BDA9D062 +RefMD5=58D200D43620007314304F4E6C9E6528 + +[E6EC9D86F94CEB2E311F9C23BBD3781F] +GoodName=F-ZERO X (J) [b2] +CRC=076C5C15 BDA9D062 +RefMD5=58D200D43620007314304F4E6C9E6528 + +[6AC12C2D6C0CCDF27C0D5179A500BB2D] +GoodName=F-ZERO X (J) [b3] +CRC=076C5C15 BDA9D062 +RefMD5=58D200D43620007314304F4E6C9E6528 + +[75AEA2B252309552E434B30EDFE72711] +GoodName=F-ZERO X (J) [t1] +CRC=076C5C15 BDA9D062 +RefMD5=58D200D43620007314304F4E6C9E6528 + +[C1CDB77BEA29A4B6F9A0829F8BA8A3F3] +GoodName=F-ZERO X (U) (DXP Track Pack Hack) +CRC=3983D1A9 2004158C +SaveType=SRAM +Players=4 +Rumble=Yes + +[753437D0D8ADA1D12F3F9CF0F0A5171F] +GoodName=F-ZERO X (U) [!] +CRC=B30ED978 3003C9F9 +SaveType=SRAM +Players=4 +Rumble=Yes + +[3AE32658B839FFA3189E3CA84E0B884A] +GoodName=F-ZERO X (U) [f1] (Sex V1.0 Hack) +CRC=7E399849 03DAC1CD + +[8363F102FE496B8D06494AA22E183A3E] +GoodName=F-ZERO X (U) [f1] (Sex V1.1 Hack) +CRC=D767D118 A1B07602 + +[7AC3B9A3AA846C439575912811B3E6E0] +GoodName=F-ZERO X (U) [f1] +CRC=B0B4EDFF B2A20628 +RefMD5=753437D0D8ADA1D12F3F9CF0F0A5171F + +[EA168957B644AFE852DA1B827AFC3F9F] +GoodName=F-ZERO X (U) [f2] (GameShark) +CRC=0B46D03D 5FFAE173 +RefMD5=753437D0D8ADA1D12F3F9CF0F0A5171F + +[44D5F87127053A21DB120BD108B7AC0C] +GoodName=F1 Racing Championship (B) (M2) [!] +CRC=53CCAD28 AEA6EDA2 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[9581FC6CEAC86DC8A2AEE4053043E422] +GoodName=F1 Racing Championship (E) (M5) [!] +CRC=3CECBCB8 6126BF07 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[AA951294528CA2CF55F810F9FE433F8D] +GoodName=F1 Racing Championship (E) (M5) [f1] (NTSC) +CRC=67D239A0 960F3A1A +RefMD5=9581FC6CEAC86DC8A2AEE4053043E422 + +[26B18D35984528AE2F90ADBB2F2642F7] +GoodName=FIFA - Road to World Cup 98 (E) (M7) [!] +CRC=0E31EDF0 C37249D5 +Players=4 +SaveType=None +Mempak=Yes + +[479554129EB27A3546BAC96C80AF4F88] +GoodName=FIFA - Road to World Cup 98 (E) (M7) [o1] +CRC=0E31EDF0 C37249D5 +RefMD5=26B18D35984528AE2F90ADBB2F2642F7 + +[2C6D146A8473511CFCFBBE8518F49D71] +GoodName=FIFA - Road to World Cup 98 (U) (M7) [!] +CRC=CB1ACDDE CF291DF2 +Players=4 +SaveType=None +Mempak=Yes + +[4E275B05BABCA9F2CD77749026BEA5ED] +GoodName=FIFA - Road to World Cup 98 (U) (M7) [b1] +CRC=CB1ACDDE CF291DF2 +RefMD5=2C6D146A8473511CFCFBBE8518F49D71 + +[4CAAE8CA91F58D746B6A00BCBC122B87] +GoodName=FIFA - Road to World Cup 98 (U) (M7) [b2] +CRC=CB1ACDDE CF291DF2 +RefMD5=2C6D146A8473511CFCFBBE8518F49D71 + +[217D93B21FEC3A5506DB014BF445B581] +GoodName=FIFA - Road to World Cup 98 (U) (M7) [b3] +CRC=CB1ACDDE CF291DF2 +RefMD5=2C6D146A8473511CFCFBBE8518F49D71 + +[4421F891F0BA3CC7AA0FD566A162F2C8] +GoodName=FIFA - Road to World Cup 98 (U) (M7) [b4] +CRC=CB1ACDDE CF291DF2 +RefMD5=2C6D146A8473511CFCFBBE8518F49D71 + +[0B8303E33B3F6E57531FB8EB3FAE65E9] +GoodName=FIFA - Road to World Cup 98 (U) (M7) [o1] +CRC=CB1ACDDE CF291DF2 +RefMD5=2C6D146A8473511CFCFBBE8518F49D71 + +[3611779F29997267622CBC80E2D087CC] +GoodName=FIFA - Road to World Cup 98 - World Cup heno Michi (J) [!] +CRC=F5733C67 17A3973A +Players=4 +SaveType=None +Mempak=Yes + +[6432C622C05EA9CD3217E280AC2CE37C] +GoodName=FIFA 99 (E) (M8) [!] +CRC=0198A651 FC219D84 +Players=4 +SaveType=None +Mempak=Yes + +[940FFB6C94F84BFFD972A69ED86DD2FD] +GoodName=FIFA 99 (E) (M8) [hI] +CRC=F82C85BE DEB717E2 +RefMD5=6432C622C05EA9CD3217E280AC2CE37C + +[148DE3073727B9FD156F10AFADD46864] +GoodName=FIFA 99 (U) [!] +CRC=7613A630 3ED696F3 +Players=4 +SaveType=None +Mempak=Yes + +[22082B8D892A2560032FD4DA5AB975A1] +GoodName=FIFA 99 (U) [b1] +CRC=21250314 E6A82CB9 +RefMD5=148DE3073727B9FD156F10AFADD46864 + +[9A7006212947EE7648EE1D13162E55E0] +GoodName=FIFA Soccer 64 (E) (M3) [!] +CRC=C3F19159 65D2BC5A +Players=4 +SaveType=None +Mempak=Yes + +[1D71761771E3BFFC091E38B9E8B5E590] +GoodName=FIFA Soccer 64 (E) (M3) [b1] +CRC=C3F19159 65D2BC5A +RefMD5=9A7006212947EE7648EE1D13162E55E0 + +[B5FBF033D76FDE89375D84B8918A5B61] +GoodName=FIFA Soccer 64 (E) (M3) [o1] +CRC=C3F19159 65D2BC5A +RefMD5=9A7006212947EE7648EE1D13162E55E0 + +[084ABA16D84C87712A731D485FCDBE3E] +GoodName=FIFA Soccer 64 (E) (M3) [o2] +CRC=C3F19159 65D2BC5A +RefMD5=9A7006212947EE7648EE1D13162E55E0 + +[376FFEC460443409BC29BB815ABFB42A] +GoodName=FIFA Soccer 64 (E) (M3) [o3] +CRC=C3F19159 65D2BC5A +RefMD5=9A7006212947EE7648EE1D13162E55E0 + +[CF55223F9E3BD118969A34950BEDFD1F] +GoodName=FIFA Soccer 64 (E) (M3) [o4] +CRC=C3F19159 65D2BC5A +RefMD5=9A7006212947EE7648EE1D13162E55E0 + +[CC7C58A032AABA19E72CCBFA6B3EEFF6] +GoodName=FIFA Soccer 64 (U) (M3) [!] +CRC=C3F19159 65D2BC5A +Players=4 +SaveType=None +Mempak=Yes + +[CA56F2DE80839EC88750C15A21AA7C53] +GoodName=FIFA Soccer 64 (U) (M3) [b1] +CRC=C3F19159 65D2BC5A +RefMD5=CC7C58A032AABA19E72CCBFA6B3EEFF6 + +[37B24EE746A1EFD54730B5E24551E8CB] +GoodName=FIFA Soccer 64 (U) (M3) [o1] +CRC=C3F19159 65D2BC5A +RefMD5=CC7C58A032AABA19E72CCBFA6B3EEFF6 + +[D99B1A3F6D72DEFD76F3620959B94944] +GoodName=Famista 64 (J) [!] +CRC=6DFF4C37 B1B763FD +Mempak=Yes + +[EACE2271AE7F32A71625C9074115D640] +GoodName=Famista 64 (J) [b1] +CRC=6DFF4C37 B1B763FD + +[FE1B92F6A7E15A1AF367FAD957375B20] +GoodName=Famista 64 (J) [b2] +CRC=6DFF4C37 B1B763FD + +[4C9B2848A2EED723C331973A926488AB] +GoodName=Famista 64 (J) [b3] +CRC=6DFF4C37 B1B763FD + +[35F3928F12DA627DB79EDFC96B93F8D3] +GoodName=Famista 64 (J) [b4] +CRC=6DFF4C37 B1B763FD + +[9213243118ACCE5664D1A35CCDCCD87E] +GoodName=Famista 64 (J) [b5] +CRC=6DFF4C37 B1B763FD + +[155FA36DD3927A73534461B50417325F] +GoodName=Famista 64 (J) [b6] +CRC=6DFF4C37 B1B763FD + +[30413678CE47E1A2EB8DA80AF0D768F5] +GoodName=Famista 64 (J) [b7] +CRC=6DFF4C37 B1B763FD + +[ADAD4FF18E09D2F5B29AA6B5F159EF4E] +GoodName=Famista 64 (J) [o1] +CRC=6DFF4C37 B1B763FD + +[04DD2A319F4F5C22569B612CFDF9F00C] +GoodName=Fighter Destiny 2 (U) [!] +CRC=AEEF2F45 F97E30F1 +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[7B5AFA5D60F53FA640A5F2F24F5B2741] +GoodName=Fighter Destiny 2 (U) [f1] (PAL-NTSC) +CRC=11FBD007 E7029A81 +RefMD5=04DD2A319F4F5C22569B612CFDF9F00C + +[EF5CB24CE3FE4E0F850901205437B574] +GoodName=Fighter's Destiny (E) [!] +CRC=36F1C74B F2029939 +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[44B0BE1C4B48F6119D3AC9424903D0EB] +GoodName=Fighter's Destiny (F) [!] +CRC=0C41F9C2 01717A0D +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[1CF379ACA2397222AF9F3DC5D8E3C444] +GoodName=Fighter's Destiny (G) [!] +CRC=FE94E570 E4873A9C +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[D61D97A7658C419A25A9BAC96B0A3DF8] +GoodName=Fighter's Destiny (U) [!] +CRC=52F78805 8B8FCAB7 +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[6E7C82AFF9F73A3DBF5B18D924BDF103] +GoodName=Fighter's Destiny (U) [b1] +CRC=52F78805 8B8FCAB7 +RefMD5=D61D97A7658C419A25A9BAC96B0A3DF8 + +[5FB4DE8B475C4427F0F30A28C1266CF9] +GoodName=Fighter's Destiny (U) [o1] +CRC=52F78805 8B8FCAB7 +RefMD5=D61D97A7658C419A25A9BAC96B0A3DF8 + +[722C3A74A90305D6079A37994CEBF5B2] +GoodName=Fighting Cup (J) [!] +CRC=49E46C2D 7B1A110C +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[0035E8205336982E362402AAEA37D147] +GoodName=Fighting Force 64 (E) [!] +CRC=66CF0FFE AD697F9C +Players=2 +SaveType=None +Mempak=Yes +CountPerOp=1 +Rumble=Yes + +[E7008D17FD71D9C2BDA1362C885388B2] +GoodName=Fighting Force 64 (U) [!] +CRC=32EFC7CB C3EA3F20 +Players=2 +SaveType=None +Mempak=Yes +CountPerOp=1 +Rumble=Yes + +[13962910EFD82C2A2333CF38EE1FCD96] +GoodName=Fighting Force 64 (U) [T+Ita_Cattivik66] +CRC=32EFC7CB C3EA3F20 +RefMD5=E7008D17FD71D9C2BDA1362C885388B2 + +[55868ECCCC14F43BF61032DE21D9F026] +GoodName=Fighting Force 64 (U) [t1] +CRC=655BE931 9FB2E4FB +RefMD5=E7008D17FD71D9C2BDA1362C885388B2 + +[F427033D9184ACA164B971E559C0B420] +GoodName=Fighting Force 64 (U) [t1][f1] (PAL) +CRC=6976748D 1BF61F62 +RefMD5=E7008D17FD71D9C2BDA1362C885388B2 + +[3B86A6C5B478A0D33A6547D3EA276AFE] +GoodName=Fire Demo by Lac (PD) +CRC=8E248649 2E1CDE52 +SaveType=None +Players=0 +Rumble=No +Status=3 + +[75F4A7E5932FB4AE791875E770E51C72] +GoodName=Fireworks Demo by CrowTRobo (PD) +CRC=ECAEC238 EE351DDA + +[BD46DD6275077D5A701482571F5DCDCC] +GoodName=Fish Demo by NaN (PD) +CRC=5CABD891 6229F6CE + +[ADD115AAD0AB7D33BFD243936D809178] +GoodName=Flying Dragon (E) [!] +CRC=22E9623F B60E52AD +SaveType=None +Mempak=Yes +Players=2 +CountPerOp=1 +Rumble=Yes + +[272B359D8F8AC48ACBF053C262F422E4] +GoodName=Flying Dragon (U) [!] +CRC=A92D52E5 1D26B655 +SaveType=None +Mempak=Yes +Players=2 +CountPerOp=1 +Rumble=Yes + +[46E9A352AD6AFB83B0557EC659957B2E] +GoodName=Flying Dragon (U) [b1] +CRC=A92D52E5 1D26B655 +RefMD5=272B359D8F8AC48ACBF053C262F422E4 + +[1E672743A9B6B4E9DFB40D4004735F38] +GoodName=Flying Dragon (U) [b2] +CRC=A92D52E5 1D26B655 +RefMD5=272B359D8F8AC48ACBF053C262F422E4 + +[171E55BF4383676C0B8F3D38B0D6A739] +GoodName=Fogworld USA Demo by Horizon64 (PD) [h1C][o1] +CRC=11C646E7 4D86C048 + +[B9A7BEFADFC4C46D61883B012FD2E69F] +GoodName=Fogworld USA Demo by Horizon64 (PD) +CRC=11C646E7 4D86C048 + +[8286DED701DFA22436D311BD5B93BD29] +GoodName=Forsaken 64 (E) (M4) [!] +CRC=142A17AA 13028D96 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[74650F7154E0B2DD7C364F511B0D6A77] +GoodName=Forsaken 64 (G) [!] +CRC=C3CD76FF 9B9DCBDE +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[F023F3189722A96ACDCF0BDD9154EF11] +GoodName=Forsaken 64 (G) [h1C] +CRC=C3CD76FF 9B9DCBDE +RefMD5=74650F7154E0B2DD7C364F511B0D6A77 + +[B775E4FF0205C405E3AA0A8DF50C54DE] +GoodName=Forsaken 64 (G) [o1] +CRC=C3CD76FF 9B9DCBDE +RefMD5=74650F7154E0B2DD7C364F511B0D6A77 + +[5CDEE5503A57D14533C66B35A5848899] +GoodName=Forsaken 64 (U) [!] +CRC=9E330C01 8C0314BA +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[C61FBF0BE56FBCD8FD373EDFB5D3E538] +GoodName=Forsaken 64 (U) [b1] +CRC=9E330C01 8C0314BA +RefMD5=5CDEE5503A57D14533C66B35A5848899 + +[795F7C1D3D98125C3AEA0FFFE54410DE] +GoodName=Forsaken 64 (U) [t1] +CRC=21FF0391 09F141A1 +RefMD5=5CDEE5503A57D14533C66B35A5848899 + +[ECB92E2663D5B3EEA08A149FC31E3701] +GoodName=Forsaken 64 (U) [t2] +CRC=21FF0391 09F141A1 +RefMD5=5CDEE5503A57D14533C66B35A5848899 + +[A50182B02E3F0D28BE1AC341DDC92DCA] +GoodName=Forsaken 64 (U) [t3] +CRC=5E0C3DF7 8BA027D9 +RefMD5=5CDEE5503A57D14533C66B35A5848899 + +[360DC6BE6D06DCA12E53C077AC0D2571] +GoodName=Fox Sports College Hoops '99 (U) [!] +CRC=3261D479 ED0DBC25 +Players=2 +SaveType=None +Mempak=Yes + +[EE0C756F832827E3ACDF6DBD410ADCA4] +GoodName=Fox Sports College Hoops '99 (U) [f1] (PAL) +CRC=3261D429 70AF148E +RefMD5=360DC6BE6D06DCA12E53C077AC0D2571 + +[5C4496C6D937364DE0022D1C07BE38A1] +GoodName=Fractal Zoomer Demo by RedboX (PD) +CRC=30E6FE79 3EEA5386 + +[7C87831B28D5E49F4EC2BDAE9D01F3B9] +GoodName=Freekworld BBS Intro by Rene (PD) [a1] +CRC=714001E3 2EB04B67 + +[DE7384A7DA97EEEAEF80CBEFBD17961A] +GoodName=Freekworld BBS Intro by Rene (PD) +CRC=714001E3 2EB04B67 + +[7CCB9B385D1405603E7F645352EA62AA] +GoodName=Freekworld New Intro by Ste (PD) +CRC=69458FFE C9D007AB + +[372F76C0DBE0BE41F5A0A47252869E8E] +GoodName=Friendship Demo by Renderman (PD) [b1] +CRC=CEE5C8CD D3D85466 + +[C18F1C91F6F15971DB18167EB72E6CEF] +GoodName=Friendship Demo by Renderman (PD) +CRC=CEE5C8CD D3D85466 + +[097189B4C9BF6775E4685951B6E66F24] +GoodName=Frogger 2 (U) (Prototype 1) [!] +CRC=AD19A172 9004666A +Mempak=Yes + +[CB2C9C6104C3EF69A1CF979525F2F73D] +GoodName=Frogger 2 (U) (Prototype 2) [!] +CRC=E8E5B179 44AA30E8 +Mempak=Yes + +[27F61A55E27EA7F1EDE4CA11966ACC7C] +GoodName=Frogger 2 (U) (Alpha) [o1] +CRC=E8E5B179 44AA30E8 +RefMD5=CB2C9C6104C3EF69A1CF979525F2F73D + +[FA6CE44ECF86DEC0AFA321D82CD3ED6E] +GoodName=Frogger 2 (U) (Alpha) [o2] +CRC=E8E5B179 44AA30E8 +RefMD5=CB2C9C6104C3EF69A1CF979525F2F73D + +[BBCDE4966BEE5602A80D9B8C1011DFA6] +GoodName=Fushigi no Dungeon - Fuurai no Shiren 2 - Oni Shuurai! Shiren Jou! (J) [!] +CRC=F774EAEE F0D8B13E +Players=1 +SaveType=SRAM +Mempak=Yes +CountPerOp=1 + +[316C59DAE45C20250A0419A937E7D65B] +GoodName=G.A.S.P!! Fighter's NEXTream (E) [!] +CRC=68FCF726 49658CBC +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[6C73558DE5A1EEE6597D7264F9A11B0C] +GoodName=G.A.S.P!! Fighter's NEXTream (J) [!] +CRC=AF8679B6 5E1011BF +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[D7C983F603EE7AE8156C6EAEEF7195C4] +GoodName=G.A.S.P!! Fighter's NEXTream (J) [o1] +CRC=AF8679B6 5E1011BF +RefMD5=6C73558DE5A1EEE6597D7264F9A11B0C + +[F61757BE8ECF0D7068C23CFCE23D2F10] +GoodName=GBlator for CD64 (PD) [f1] (V64-PAL) +CRC=5D1795D2 C0D72338 + +[ECE232D98B095604D1C15F9571DE45F8] +GoodName=GBlator for CD64 (PD) +CRC=5D8B9226 47605A2A + +[E3FDAB4E3C417E623A02875D6A6E7467] +GoodName=GBlator for NTSC Dr V64 (PD) +CRC=5C1AAD1C AF7BF297 + +[0F85543F27896856EB82C52E3C7CCAB5] +GoodName=GBlator for PAL Dr V64 (PD) +CRC=5D0F8DD2 990BE538 + +[628AA3CD492559B705488F634797E045] +GoodName=GT 64 - Championship Edition (E) (M3) [!] +CRC=EE4A0E33 8FD588C9 +SaveType=Eeprom 16KB +Players=2 +CountPerOp=1 +Mempak=Yes +Rumble=Yes + +[15DB716942C36A0CB392226001536A2A] +GoodName=GT 64 - Championship Edition (E) (M3) [b1] +CRC=B6A90FB4 E2C235BA +RefMD5=628AA3CD492559B705488F634797E045 + +[6969E979395A0AF64CAF2DF9C1054C94] +GoodName=GT 64 - Championship Edition (E) (M3) [f1] (NTSC) +CRC=B6A90FB4 E2C235BA +RefMD5=628AA3CD492559B705488F634797E045 + +[F3E25D0A7B98E8E25B7570A6E056D33C] +GoodName=GT 64 - Championship Edition (E) (M3) [f2] (NTSC) +CRC=93A292F1 ADF98E2E +RefMD5=628AA3CD492559B705488F634797E045 + +[FE81AA381719FADA693D803BAE7D5EB9] +GoodName=GT 64 - Championship Edition (U) [!] +CRC=C49ADCA2 F1501B62 +Players=2 +SaveType=Eeprom 16KB +CountPerOp=1 +Mempak=Yes +Rumble=Yes + +[4695A944B019F3829F2616591659A7CE] +GoodName=GT 64 - Championship Edition (U) [b1] +CRC=C49ADCA2 F1501B62 +RefMD5=FE81AA381719FADA693D803BAE7D5EB9 + +[9B5A92F32B9C807B2A9C01E42EF8F461] +GoodName=GT Demo (PD) [a1] +CRC=2575EF19 D13D2A2C + +[C41F0D1EDD2C8259EB27A8C97CAA3D71] +GoodName=GT Demo (PD) +CRC=2575EF19 D13D2A2C + +[3DE02CF363E4D081530FEF53FDAB5780] +GoodName=Game Boy 64 (POM '98) (PD) (Illegal Mode Enabled) +CRC=97FC2167 4616872B + +[6C36E6A39ABBAB3E9139E9ECBC67E569] +GoodName=Game Boy 64 (POM '98) (PD) +CRC=97FC2167 4616872B + +[47C7DF82B3ADEAE19C8AFACE40FEB1AC] +GoodName=Game Boy 64 + Super Mario 3 (PD) +CRC=60D0A702 432236C6 + +[7AD954ADD3779FB3BE5904D1B935EBFB] +GoodName=GameBooster 64 V1.1 (NTSC) (Unl) [b1] +CRC=1A5C1CAD 7BAF97F2 + +[C60F99DCF6B05FAA2C33970462F93865] +GoodName=GameBooster 64 V1.1 (NTSC) (Unl) [f1] +CRC=5C1AAD1C AF7BF297 + +[60D0264B38E22EF0D6B9549E4C81C29F] +GoodName=GameBooster 64 V1.1 (NTSC) (Unl) +CRC=12678830 4E5AE439 + +[DB02D36555E2473EA3036B8E0868254E] +GoodName=GameBooster 64 V1.1 (PAL) (Unl) [b1] +CRC=D06002A7 2243C636 + +[4C383E57BC1062466328D0B59FB7AA67] +GoodName=GameBooster 64 V1.1 (PAL) (Unl) [f1] (Sound) +CRC=3BCCD2DB 953FA1F5 + +[1A56FE2B2FE339C7DD4FF8D37EC8654B] +GoodName=GameBooster 64 V1.1 (PAL) (Unl) +CRC=12678830 4E5AE439 + +[437EFD7FD7F84F4C0F802D3BF1F8464E] +GoodName=GameShark Pro V2.0 (Unl) +CRC=16FB52A4 7AED1FB3 + +[F275A4216744D8F04B4A0CD74DE53111] +GoodName=GameShark Pro V3.3 (Apr 2000) (Unl) [!] +CRC=EA6D5BF8 E2B4696C + +[9F556D184D945369DDD11B5F815814A8] +GoodName=GameShark Pro V3.3 (Mar 2000) (Unl) [!] +CRC=8F89ABA0 C34C2610 + +[96CA36D474E82C270A129D775C63167A] +GoodName=Ganbare Goemon - Derodero Douchuu Obake Tenkomori (J) [!] +CRC=457B9CD9 09C55352 +Players=2 +SaveType=SRAM +Rumble=Yes +CountPerOp=1 + +[7EB07675E2E9CB547A3B238AA71F57CC] +GoodName=Ganbare Goemon - Derodero Douchuu Obake Tenkomori (J) [t1] +CRC=BD8E0304 33E3998A +RefMD5=96CA36D474E82C270A129D775C63167A + +[3F50712011BE1CB59B45684D7D61F11E] +GoodName=Ganbare Goemon - Derodero Douchuu Obake Tenkomori (J) [t2] +CRC=A39C0306 F1DD4CC6 +RefMD5=96CA36D474E82C270A129D775C63167A + +[2BDE49F2855030DE342976C9A95B81B3] +GoodName=Ganbare Goemon - Mononoke Sugoroku (J) [!] +CRC=B2C6D27F 2DA48CFD +Players=4 +SaveType=SRAM +Mempak=Yes + +[9B929E0BF8D63E62820F2FA6257CC5CF] +GoodName=Ganbare Goemon - Neo Momoyama Bakufu no Odori (J) [!] +CRC=832C168B 56A2CDAE +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[7F4E8F2ECF04BE27E660AC2EFDAC0C68] +GoodName=Ganbare Goemon - Neo Momoyama Bakufu no Odori (J) [b1] +CRC=832C168B 56A2CDAE +RefMD5=9B929E0BF8D63E62820F2FA6257CC5CF + +[19BFC2C0124C009B51FE1724B07FAC81] +GoodName=Ganbare Goemon - Neo Momoyama Bakufu no Odori (J) [b2] +CRC=832C168B 56A2CDAE +RefMD5=9B929E0BF8D63E62820F2FA6257CC5CF + +[A2B81C0B7E3989152CA90901D05E6352] +GoodName=Ganbare Goemon - Neo Momoyama Bakufu no Odori (J) [h1C] +CRC=832C168B 56A2CDAE +RefMD5=9B929E0BF8D63E62820F2FA6257CC5CF + +[A7C82BB5098A7526D5417EE9A8981F48] +GoodName=Ganbare Goemon - Neo Momoyama Bakufu no Odori (J) [h1C][t1] +CRC=7BB5698F D99BF02B +RefMD5=9B929E0BF8D63E62820F2FA6257CC5CF + +[8D8F3A8393F3F5489B3B144369565594] +GoodName=Ganbare Nippon! Olympics 2000 (J) [!] +CRC=21FFFD0A FA0D1D98 +Players=4 +SaveType=SRAM +Rumble=Yes + +[28C2108A375F7731E719333A09439D2F] +GoodName=Gauntlet Legends (E) [!] +CRC=D543BCD6 2BA5E256 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[0806E6DB8B2BF0501BE9F2D78D280DCF] +GoodName=Gauntlet Legends (E) [b1] +CRC=D543BCD6 2BA5E256 +RefMD5=28C2108A375F7731E719333A09439D2F + +[3B2615D754A61E45B1034D555D830A78] +GoodName=Gauntlet Legends (J) [!] +CRC=70B0260E 6716D04C +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[9CB963E8B71F18568F78EC1AF120362E] +GoodName=Gauntlet Legends (U) [!] +CRC=729B5E32 B728D980 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[50F8E73CA0160EB1A339AC2137A7B559] +GoodName=Gauntlet Legends (U) [f1] (PAL) +CRC=AA89A18D 0FC2AFE6 +RefMD5=9CB963E8B71F18568F78EC1AF120362E + +[5270D98F9E67DC7EF354ECE109C2A18F] +GoodName=Getter Love!! (J) [!] +CRC=489C84E6 4C6E49F9 +Players=4 +Mempak=Yes +Rumble=Yes + +[3BE170E7E94A03BD4E36732EB137EE39] +GoodName=Getter Love!! (J) [b1] +CRC=489C84E6 4C6E49F9 +RefMD5=5270D98F9E67DC7EF354ECE109C2A18F + +[1E6573F2A7454C133EB05A14C15909A9] +GoodName=Getter Love!! (J) [b2] +CRC=489C84E6 4C6E49F9 +RefMD5=5270D98F9E67DC7EF354ECE109C2A18F + +[43B9A7A5CCB6EA3F4860F9F80D73669D] +GoodName=Gex 3 - Deep Cover Gecko (E) (M2) (Fre-Ger) [!] +CRC=874733A4 A823745A +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes + +[9F0492A34D7A2D7C4E9F29DC1848A04A] +GoodName=Gex 3 - Deep Cover Gecko (E) (M3) (Eng-Spa-Ita) [!] +CRC=99179359 2FE7EBC3 +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes + +[6770DDEC84EB21A5E0D0F55DFD52A01A] +GoodName=Gex 3 - Deep Cover Gecko (U) [!] +CRC=3EDC7E12 E26C1CC9 +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes + +[6E0FCFF93600A28C379EF52940C54E68] +GoodName=Gex 3 - Deep Cover Gecko (U) [f1] (PAL) +CRC=E68A9F6E 24FB3315 +RefMD5=6770DDEC84EB21A5E0D0F55DFD52A01A + +[EF0988EFDCEA31B88A3920CEEC17B4FF] +GoodName=Gex 3 - Deep Cover Gecko (U) [t1] +CRC=E6896018 6013AD31 +RefMD5=6770DDEC84EB21A5E0D0F55DFD52A01A + +[5BBA457E286D250101CE274E0E58080D] +GoodName=Gex 64 - Enter the Gecko (E) [!] +CRC=E68A000E 639166DD +Players=1 +SaveType=None +Mempak=Yes + +[47F9D900C97ECE154BB40A9C6DCCD3FD] +GoodName=Gex 64 - Enter the Gecko (U) [!] +CRC=89FED774 CAAFE21B +Players=1 +SaveType=None +Mempak=Yes + +[A33677B04870DE18013B760B4F53F6BF] +GoodName=Gex 64 - Enter the Gecko (U) [f1] (PAL) +CRC=4445612B F8CC9F8B +RefMD5=47F9D900C97ECE154BB40A9C6DCCD3FD + +[68828BDCAAE1C222DABB679B74B8ACD0] +GoodName=Gex 64 - Enter the Gecko (U) [t1] +CRC=71ED5D14 76A110D0 +RefMD5=47F9D900C97ECE154BB40A9C6DCCD3FD + +[3419EC10EE470F1888811D4A9B5FAACE] +GoodName=Ghemor - CD64 Xfer & Save Util (CommsLink) by CrowTRobo (PD) +CRC=2F67DC59 74AAD9F1 + +[20DA03C2098F83A790E929AC9A4CDB2E] +GoodName=Ghemor - CD64 Xfer & Save Util (Parallel) by CrowTRobo (PD) +CRC=0D99E899 43E0FCD1 + +[2F2163C53DB135792331DF00398B3F87] +GoodName=Glover (E) (M3) [!] +CRC=F5237301 99E3EE93 +Players=1 +SaveType=Eeprom 4KB + +[8881FBEAE9B84485CF66876B60CD45DF] +GoodName=Glover (E) (M3) [f1] (NTSC) +CRC=4D2B5318 47DB5316 +RefMD5=2F2163C53DB135792331DF00398B3F87 + +[43C3375BBD6496B6C51D08EC193BC8ED] +GoodName=Glover (Prototype) +CRC=254CC736 6F5C721B + +[87AA5740DFF79291EE97832DA1F86205] +GoodName=Glover (U) [!] +CRC=8E6E01FF CCB4F948 +Players=1 +SaveType=Eeprom 4KB + +[A1C34717476027DFBA72EEA56F94D650] +GoodName=Glover (U) [b1] +CRC=0E450FFC 9FFC8375 +RefMD5=87AA5740DFF79291EE97832DA1F86205 + +[873DC63304F632A71B309988C39C48F7] +GoodName=Glover (U) [b2] +CRC=7773E2BB 71D0A925 +RefMD5=87AA5740DFF79291EE97832DA1F86205 + +[87615822A0E00DD4FC7FDF636D4B8139] +GoodName=Glover (U) [t1] +CRC=51938192 BD4A98A1 +RefMD5=87AA5740DFF79291EE97832DA1F86205 + +[4E15D92CCA23E1A01BB65246431B5C5A] +GoodName=Glover 2 - Unreleased Beta Version (New Build) (Prototype) +CRC=8E9F21D2 DC19C5AB + +[A8567DDABD3672FFF18BC5DF933CF8C7] +GoodName=Glover 2 (Prototype) +CRC=B7F40BCF 553556A5 + +[29BC5C1A24D3979D376AD421000AC9CB] +GoodName=Goemon's Great Adventure (U) [!] +CRC=4252A5AD AE6FBF4E +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[231BAC1AFB3DE138072C2D697783059B] +GoodName=Golden Nugget 64 (U) [!] +CRC=4690FB1C 4CD56D44 +Players=4 +SaveType=None +Mempak=Yes + +[7CE28ADAB6FE43207B4BB19564C38AEF] +GoodName=Golden Nugget 64 (U) [b1] +CRC=4690FB1C 4CD56D44 +RefMD5=231BAC1AFB3DE138072C2D697783059B + +[5340DD96CF1CD7AC6D72000D40B915CE] +GoodName=Golden Nugget 64 (U) [b2] +CRC=4690FB1C 4CD56D44 +RefMD5=231BAC1AFB3DE138072C2D697783059B + +[E048C2FE226634F039882C35A2A4EEA9] +GoodName=Golden Nugget 64 (U) [b3] +CRC=4690FB1C 4CD56D44 +RefMD5=231BAC1AFB3DE138072C2D697783059B + +[2DB6ED9A6A244CB209FFDF52D9006E4D] +GoodName=Golden Nugget 64 (U) [f1] (PAL) +CRC=438CEBDC 44C1837C +RefMD5=231BAC1AFB3DE138072C2D697783059B + +[F68F02A69829469F208D538D7CF4A215] +GoodName=Golden Nugget 64 (U) [h1C] +CRC=4690FB1C 4CD56D44 +RefMD5=231BAC1AFB3DE138072C2D697783059B + +[CFF69B70A8AD674A0EFE5558765855C9] +GoodName=GoldenEye 007 (E) [!] +CRC=0414CA61 2E57B8AA +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes +Status=4 + +[ECD4F078DC77F4B2D12C1C0F5CABA323] +GoodName=GoldenEye 007 (E) [b1] +CRC=0414CA61 2E57B8AA +RefMD5=CFF69B70A8AD674A0EFE5558765855C9 + +[D83BDE156D6FC400C28308A447B8FCA0] +GoodName=GoldenEye 007 (E) [h1C] +CRC=0414CA61 2E57B8AA +RefMD5=CFF69B70A8AD674A0EFE5558765855C9 + +[F7A0EFCF8DB90FBD6FD9BFC570A4804A] +GoodName=GoldenEye 007 (E) [t1] (Rapid Fire) +CRC=540F359D FF327745 +RefMD5=CFF69B70A8AD674A0EFE5558765855C9 + +[1880DA358F875C0740D4A6731E110109] +GoodName=GoldenEye 007 (J) [!] +CRC=A24F4CF1 A82327BA +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes +Status=4 + +[FB916F914D9635F8FCBCE37A6466079D] +GoodName=GoldenEye 007 (J) [t1] (Rapid Fire) +CRC=B244B30C 72A648D8 +RefMD5=1880DA358F875C0740D4A6731E110109 + +[3AA7D5F55E3E5E6C7419CC1625AF69BC] +GoodName=GoldenEye 007 (U) (Frozen Enemies Hack) +CRC=DCBCACD1 D72FAA33 + +[9AB9FB9782C7BB42A48C1465CD8F4EF6] +GoodName=GoldenEye 007 (E) (Citadel Hack) +CRC=44853212 B1F75C3E + +[ECAB0839D3ED0E3AA8516EF1C077CF0D] +GoodName=GoldenEye 007 (U) (Citadel Hack) +CRC=1C6F7718 CBAC1E7E + +[7DD2F0E19E35511C3E1C81D206CDC472] +GoodName=GoldenEye 007 (U) (G5 Multi (for backups) Hack) +CRC=F2C3A524 A1C4DB13 + +[F4AB4CD6A8AF21E8A51BF48578CC7F24] +GoodName=GoldenEye 007 (U) (G5 Multi Hack) +CRC=DCBC50D1 09FD1AA3 + +[FD35D8A9DE0F5AB500A588A6AB5F6FB9] +GoodName=GoldenEye 007 (U) (Tetris Hack) +CRC=A84D23BA A1974DBD + +[3BC50511DE8598A49E79F4CF2E4CF8E0] +GoodName=GoldenEye 007 (U) (God Mode Hack) +CRC=DCBCACD1 E1051EA6 + +[86C6B996A55F90FC2410B16AE4BA5EE0] +GoodName=GoldenEye 007 (U) (No Music Hack) +CRC=DCBCACD1 A67DDFB4 + +[15B57CDECA506B34FF6246ED06AABD50] +GoodName=GoldenEye 007 (U) (No Power Bar Hack) +CRC=DCBCACD1 F294D541 + +[70C525880240C1E838B8B1BE35666C3B] +GoodName=GoldenEye 007 (U) [!] +CRC=DCBC50D1 09FD1AA3 +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes +Status=4 + +[0B5A50E8D477B3BC53BE997264FE84A5] +GoodName=GoldenEye 007 (U) [b1] +CRC=DCBC50D1 09FD1AA3 +RefMD5=70C525880240C1E838B8B1BE35666C3B + +[C7A22DC5D95EBE1F8EDB0D68C13027C1] +GoodName=GoldenEye 007 (U) [h1C] +CRC=DCBC50D1 09FD1AA3 +RefMD5=70C525880240C1E838B8B1BE35666C3B + +[22FF6C18EB028792EF350554B1E1FA68] +GoodName=GoldenEye 007 (U) [o1] +CRC=DCBC50D1 09FD1AA3 +RefMD5=70C525880240C1E838B8B1BE35666C3B + +[6B8BA063C40420C164AA81ACB6089CB6] +GoodName=GoldenEye 007 (U) [o2] +CRC=DCBC50D1 09FD1AA3 +RefMD5=70C525880240C1E838B8B1BE35666C3B + +[18C00B5C3D9DF09AB9E8A737E61C3B47] +GoodName=GoldenEye 007 (U) [t1] (Rapid Fire) +CRC=E09DAF6C 8A2B86F4 +RefMD5=70C525880240C1E838B8B1BE35666C3B + +[2E50BC853F6EFC1E0D5E4679739F43C4] +GoodName=GoldenEye 007 (U) [t2] +CRC=8E1B3303 9D4F5035 +RefMD5=70C525880240C1E838B8B1BE35666C3B + +[95B784D6DD3470903BAF6BBB533E088B] +GoodName=GoldenEye 007 (U) [t3] (All Guns Zoom Mode) +CRC=1C6F7718 CBAC1E7E +RefMD5=70C525880240C1E838B8B1BE35666C3B + +[AD3D099C84096DBACAD7F1CF982631B2] +GoodName=GoldenEye 007 Intro by SonCrap (PD) +CRC=9303DD17 0813B398 + +[67F2E18ED18A5F0EA3FE2D913E3F1786] +GoodName=GoldenEye X +; Alternate Title=GoldenEye X (5e Clouds) +CRC=FDF95D15 618546CA +RefMD5=E03B088B6AC9E0080440EFED07C1E40F + +[435D75D07878D305293EC4D591B86303] +GoodName=GoldenEye X +; Alternate Title=GoldenEye X (5e Cloudless) +CRC=E8B3F63D E5A997B1 +RefMD5=E03B088B6AC9E0080440EFED07C1E40F + +[9B8A7541D0234F4D97004ECBC216D9C2] +GoodName=HIPTHRUST by MooglyGuy (PD) +CRC=88A12FB3 8A583CBD + +[821A739790F1D390DC7D4168C5E032DE] +GoodName=HSD Quick Intro (PD) +CRC=BD1263E5 388C9BE7 + +[26F7D8F4640EBDFA823F84E5F89D62BF] +GoodName=HSV Adventure Racing (A) [!] +CRC=72611D7D 9919BDD2 +Players=4 +SaveType=None +CountPerOp=3 +Rumble=Yes +Mempak=Yes + +[7B38C3F7DA8D9778B41B0047A133590A] +GoodName=HSV Adventure Racing (A) [b1] +CRC=72611D7D 9919BDD2 +RefMD5=26F7D8F4640EBDFA823F84E5F89D62BF + +[8C7AF37A3CB7306EBCCAC4029EB5C57D] +GoodName=HSV Adventure Racing (A) [f1] (NTSC) +CRC=B20CC247 B879579A +RefMD5=26F7D8F4640EBDFA823F84E5F89D62BF + +[3D4C7B11076BAFA4620BCC154C0EEEF3] +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) +CRC=9856E53D AF483207 + +[A02A4FB4B93E9847348440652CEF8D4D] +GoodName=Harukanaru Augusta Masters 98 (J) [!] +CRC=09AE57B1 182A5637 +Players=1 +Mempak=Yes +Rumble=Yes + +[397A69AA3829EA5FECB4CDF399084E31] +GoodName=Harukanaru Augusta Masters 98 (J) [b1] +CRC=09AE57B1 182A5637 +RefMD5=A02A4FB4B93E9847348440652CEF8D4D + +[FA6B3E3A04DE8D96B2C26F974F59A34D] +GoodName=Harukanaru Augusta Masters 98 (J) [b2] +CRC=09AE57B1 182A5637 +RefMD5=A02A4FB4B93E9847348440652CEF8D4D + +[4454122EC735252E40EC22FF5DE021C6] +GoodName=Harukanaru Augusta Masters 98 (J) [h1C] +CRC=09AE57B1 182A5637 +RefMD5=A02A4FB4B93E9847348440652CEF8D4D + +[6DA848A70D83ECE130D274124760928E] +GoodName=Harvest Moon 64 (U) [!] +CRC=98DF9DFC 6606C189 +Players=1 +SaveType=SRAM +CountPerOp=1 + +[3CDD87026EFEC9A03648D225F97858A5] +GoodName=Harvest Moon 64 (U) [T+Pol001] +CRC=98DF9DFC 6606C189 +RefMD5=6DA848A70D83ECE130D274124760928E + +[245FD6D774B74D4703822511CA174A54] +GoodName=Harvest Moon 64 (U) [b1] +CRC=98DF9DFC 6606C189 +RefMD5=6DA848A70D83ECE130D274124760928E + +[218DE5B3709555DA3870CE859D1975E5] +GoodName=Harvest Moon 64 (U) [f1] (PAL) +CRC=6BCF21E8 CAB5AF4F +RefMD5=6DA848A70D83ECE130D274124760928E + +[956AEC111B74720D55496F81ADA0FEFD] +GoodName=Harvest Moon 64 (U) [t1] +CRC=60CC9644 C62AE877 +RefMD5=6DA848A70D83ECE130D274124760928E + +[54AD823812D2C2E8B1688C4ACE2E654D] +GoodName=Harvest Moon 64 (U) [t1][f1] (PAL-NTSC) +CRC=60CC9644 C62AE877 +RefMD5=6DA848A70D83ECE130D274124760928E + +[19F4694B8557BC095EE07B5C8FBD23B5] +GoodName=Heavy 64 Demo by Destop (PD) +CRC=5D391A40 84D7A637 + +[5E8539E037EEA88C5A2746F60E431C8D] +GoodName=Heiwa Pachinko World 64 (J) [!] +CRC=3E70E866 4438BAE8 +Players=1 + +[9D0D85E3A0C94B98D6404E8FC28E7B01] +GoodName=Heiwa Pachinko World 64 (J) [b1] +CRC=3E70E866 4438BAE8 +RefMD5=5E8539E037EEA88C5A2746F60E431C8D + +[C2BEDCB364162D6DAC86548D7721F827] +GoodName=Heiwa Pachinko World 64 (J) [b2] +CRC=3E70E866 4438BAE8 +RefMD5=5E8539E037EEA88C5A2746F60E431C8D + +[3B6994B373BEC6E917F0B834AA6D1A46] +GoodName=Heiwa Pachinko World 64 (J) [b3] +CRC=3E70E866 4438BAE8 +RefMD5=5E8539E037EEA88C5A2746F60E431C8D + +[013E130D0D4F132741AA38D1A397E10A] +GoodName=Heiwa Pachinko World 64 (J) [h1C] +CRC=3E70E866 4438BAE8 +RefMD5=5E8539E037EEA88C5A2746F60E431C8D + +[FDF797C5FFB531FCF04E0A1928691EA3] +GoodName=Heiwa Pachinko World 64 (J) [o1] +CRC=3E70E866 4438BAE8 +RefMD5=5E8539E037EEA88C5A2746F60E431C8D + +[1546877FD85C00A83515005727E5FDA5] +GoodName=Hercules - The Legendary Journeys (E) (M6) [!] +CRC=AE90DBEB 79B89123 +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[6BBD8C42F6EF8F5B9541D6F4DB657DD7] +GoodName=Hercules - The Legendary Journeys (U) [!] +CRC=7F3CEB77 8981030A +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[57D8E020643146B325A11612FEFACF74] +GoodName=Hercules - The Legendary Journeys (U) [o1] +CRC=7F3CEB77 8981030A +RefMD5=6BBD8C42F6EF8F5B9541D6F4DB657DD7 + +[8CF8043BDFA89A2B0C4699D0E695E844] +GoodName=Hercules - The Legendary Journeys (U) [t1][f1] (PAL-NTSC) +CRC=DB7184C9 F53AC14A +RefMD5=6BBD8C42F6EF8F5B9541D6F4DB657DD7 + +[C2C3115821C738A4834E977E8325F89E] +GoodName=Hercules - The Legendary Journeys (U) [t1][f1][b1] +CRC=DB7184C9 F53AC14A +RefMD5=6BBD8C42F6EF8F5B9541D6F4DB657DD7 + +[3F1CF2D6C1580FDCCD662F9FCF8C4214] +GoodName=Hercules - The Legendary Journeys (U) [t1][f2] (PAL-NTSC) +CRC=DB7184C9 F53AC14A +RefMD5=6BBD8C42F6EF8F5B9541D6F4DB657DD7 + +[2080262A251D270F9CE819887F2104A7] +GoodName=Hexen (E) [!] +CRC=95B2B30B 2B6415C1 +Players=4 +SaveType=None +Mempak=Yes +CountPerOp=1 + +[E86A8BF46985B7CE8459AFBE5FC3DCC3] +GoodName=Hexen (E) [h1C] +CRC=95B2B30B 2B6415C1 +RefMD5=2080262A251D270F9CE819887F2104A7 + +[A5921C00111200257284CE0ABA0904CA] +GoodName=Hexen (F) [!] +CRC=5C1B5FBD 7E961634 +Players=4 +SaveType=None +Mempak=Yes +CountPerOp=1 + +[08CBB141DEC604E4DAD2787F237D57A2] +GoodName=Hexen (G) [!] +CRC=9AB3B50A BC666105 +Players=4 +SaveType=None +Mempak=Yes +CountPerOp=1 + +[35E9ECE11306EF7D8F5F09F65761D365] +GoodName=Hexen (G) [h1C] +CRC=9AB3B50A BC666105 +RefMD5=08CBB141DEC604E4DAD2787F237D57A2 + +[672152CF4DCB5D0A19662C11EFF71452] +GoodName=Hexen (J) [!] +CRC=66751A57 54A29D6E +Players=4 +SaveType=None +Mempak=Yes +CountPerOp=1 + +[EB98F1B8C6898AF7417F6882946DA9B3] +GoodName=Hexen (U) [!] +CRC=9CAB6AEA 87C61C00 +Players=4 +SaveType=None +Mempak=Yes +CountPerOp=1 + +[B06625703DB3A03BAE3D02FD0F904541] +GoodName=Hexen (U) [b1] +CRC=9CAB6AEA 87C61C00 +RefMD5=EB98F1B8C6898AF7417F6882946DA9B3 + +[EA5A22A5A2DA96D88939171CEA41A1F1] +GoodName=Hexen (U) [h1C] +CRC=9CAB6AEA 87C61C00 +RefMD5=EB98F1B8C6898AF7417F6882946DA9B3 + +[9301923AE938320FF0186B7279AFE6D8] +GoodName=Hexen (U) [t1] +CRC=E6BA0A06 8A3D2C2F +RefMD5=EB98F1B8C6898AF7417F6882946DA9B3 + +[59BA99120BE9D438C53EAED6091B9B7D] +GoodName=Hexen (U) [t2] +CRC=E6BA0A06 8A3D2C2F +RefMD5=EB98F1B8C6898AF7417F6882946DA9B3 + +[1280C78F286FC1C437A4905EE42C47F1] +GoodName=Hey You, Pikachu! (U) [!] +CRC=D3F10E5D 052EA579 +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes +AiDmaModifier=88 + +[DCC316EFFC4928F5B0AE8D273D8024BF] +GoodName=HiRes CFB Demo (PD) +CRC=4072572D A23DB72C + +[73084495F3209C54900525436BBBC531] +GoodName=Hiryuu no Ken Twin (J) [!] +CRC=35FF8F1A 6E79E3BE +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[8976913EFBE98EFED3B0B32CBCAA8B49] +GoodName=Hiryuu no Ken Twin (J) [h1C] +CRC=35FF8F1A 6E79E3BE +RefMD5=73084495F3209C54900525436BBBC531 + +[E0C39E55DE1D588371D5F99056F3578C] +GoodName=Hiryuu no Ken Twin (J) [h2C] +CRC=35FF8F1A 6E79E3BE +RefMD5=73084495F3209C54900525436BBBC531 + +[EA9B6EA32CCEB8F7EFBB2FEA211B8E89] +GoodName=Hiryuu no Ken Twin (J) [h3C] +CRC=35FF8F1A 6E79E3BE +RefMD5=73084495F3209C54900525436BBBC531 + +[80CC112F62E9A8581A1BB6A1D1E1488B] +GoodName=Holy Magic Century (E) [!] +CRC=277B129D DD3879FF +Players=1 +SaveType=None +Mempak=Yes + +[FA6A2E00BBFF236DAC91F08544AFFA40] +GoodName=Holy Magic Century (E) [b1] +CRC=277B129D DD3879FF +RefMD5=80CC112F62E9A8581A1BB6A1D1E1488B + +[988F5ABD96259196343659E913666820] +GoodName=Holy Magic Century (F) +CRC=B35FEBB0 7427B204 +Players=1 +SaveType=None +Mempak=Yes + +[668908C495432AD099C5439E38809053] +GoodName=Holy Magic Century (F) [h1C] +CRC=B35FEBB0 7427B204 +RefMD5=988F5ABD96259196343659E913666820 + +[27D3EFBD35B1F580330961480B988FB5] +GoodName=Holy Magic Century (F) [o1] +CRC=B35FEBB0 7427B204 +RefMD5=988F5ABD96259196343659E913666820 + +[AB676C3E9D26A77450DDB4AACD1A3861] +GoodName=Holy Magic Century (G) [!] +CRC=75FA0E14 C9B3D105 +Players=1 +SaveType=None +Mempak=Yes + +[ACF823A6EF4E77FE5B940D716DCED6E9] +GoodName=Holy Magic Century (G) [b1] +CRC=75FA0E14 C9B3D105 +RefMD5=AB676C3E9D26A77450DDB4AACD1A3861 + +[E26F4FFD2AA19E6EE9F9216A15189F14] +GoodName=Holy Magic Century (G) [b2] +CRC=75FA0E14 C9B3D105 +RefMD5=AB676C3E9D26A77450DDB4AACD1A3861 + +[F40D3DE4745BACC69458BAB25D6067F9] +GoodName=Holy Magic Century (G) [b3] +CRC=75FA0E14 C9B3D105 +RefMD5=AB676C3E9D26A77450DDB4AACD1A3861 + +[B1A67AEBC2BE89A800E5EB60C0DFA968] +GoodName=Hoshi no Kirby 64 (J) (V1.0) [!] +CRC=C1D702BD 6D416547 +SaveType=SRAM +Players=4 +Rumble=Yes + +[460A42ED5612EBBF92F386689067384E] +GoodName=Hoshi no Kirby 64 (J) (V1.0) [f1] +CRC=22F301B6 D0A03C3C +RefMD5=B1A67AEBC2BE89A800E5EB60C0DFA968 + +[07EA11684D74DA87719F05A1BDC4CCB3] +GoodName=Hoshi no Kirby 64 (J) (V1.0) [f2] +CRC=57CD5D6D 046282B1 +RefMD5=B1A67AEBC2BE89A800E5EB60C0DFA968 + +[FFDB4456F799722BCFE430632C3986AE] +GoodName=Hoshi no Kirby 64 (J) (V1.1) [!] +CRC=CA1BB86F 41CCA5C5 +Players=4 +SaveType=SRAM +Rumble=Yes + +[3EC0471E2CBEE17471DDBF80C56606D5] +GoodName=Hoshi no Kirby 64 (J) (V1.2) [!] +CRC=0C581C7A 3D6E20E4 +Players=4 +SaveType=Eeprom 16KB +Rumble=Yes + +[35E039F8E79843917D02BE06D00C457B] +GoodName=Hoshi no Kirby 64 (J) (V1.3) [!] +CRC=BCB1F89F 060752A2 +Players=4 +SaveType=Eeprom 16KB +Rumble=Yes + +[EF34DA35EF8A0734843CB182C19FEB26] +GoodName=Hot Wheels Turbo Racing (E) (M3) [!] +CRC=E7D20193 C1158E93 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[BB8A58282C5D4E32B34556407ACD920E] +GoodName=Hot Wheels Turbo Racing (E) (M3) [b1] +CRC=E7D20193 C1158E93 +RefMD5=EF34DA35EF8A0734843CB182C19FEB26 + +[4311A1AEF1898678331F7E3486055307] +GoodName=Hot Wheels Turbo Racing (U) [!] +CRC=C7C98F8E 42145DDE +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[50091668743D2DE7CAA253420D32C2D8] +GoodName=Hot Wheels Turbo Racing (U) [f1] (PAL) +CRC=14DE709E F882947D +RefMD5=4311A1AEF1898678331F7E3486055307 + +[7D32A665027ABB585BD4FB7194752B34] +GoodName=Hot Wheels Turbo Racing (U) [t1] +CRC=1FDFCBDC FCD77D11 +RefMD5=4311A1AEF1898678331F7E3486055307 + +[97E706ED9CC6F30708FFDC187C85D59F] +GoodName=Human Grand Prix - New Generation (J) [!] +CRC=5535972E BD8E3295 +Players=1 +SaveType=None +Mempak=Yes + +[F9A6FFD35D478A8E2B369460BFAB2CC8] +GoodName=Human Grand Prix - New Generation (J) [b1] +CRC=5535972E BD8E3295 +RefMD5=97E706ED9CC6F30708FFDC187C85D59F + +[7BD3F10D47DB6D062280D8AE750A1ACB] +GoodName=Human Grand Prix - New Generation (J) [o1] +CRC=5535972E BD8E3295 +RefMD5=97E706ED9CC6F30708FFDC187C85D59F + +[DA861C4D9202F661575466450A27C412] +GoodName=Hybrid Heaven (E) (M3) [!] +CRC=641D3A7F 86820466 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[24B023696975D27EAE8319EF40001348] +GoodName=Hybrid Heaven (E) (M3) [b1] +CRC=641D3A7F 86820466 +RefMD5=DA861C4D9202F661575466450A27C412 + +[E6F18336406EF3BFC990483BBF184ACD] +GoodName=Hybrid Heaven (E) (M3) [f1] (NTSC) +CRC=DCCEDB8F BA79BEDE +RefMD5=DA861C4D9202F661575466450A27C412 + +[9946EFF915FC947A226407AC1F7B35C4] +GoodName=Hybrid Heaven (J) [!] +CRC=0DE2CE36 D41D29E6 +Players=2 +SaveType=SRAM +Mempak=Yes +Rumble=Yes + +[94B284286A090B5980B7F18A4FA77853] +GoodName=Hybrid Heaven (J) [b1] +CRC=0DE2CE36 D41D29E6 +RefMD5=9946EFF915FC947A226407AC1F7B35C4 + +[151E92F5E3EE294BAFF5D4C3E4E95D77] +GoodName=Hybrid Heaven (J) [f1] (PAL) +CRC=DE4E5E2E DCD0615D +RefMD5=9946EFF915FC947A226407AC1F7B35C4 + +[C47E95BB32AB132C41D67BD243F9E02A] +GoodName=Hybrid Heaven (U) [!] +CRC=102888BF 434888CA +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[115521BAC11608FEBCE874F243ACC66E] +GoodName=Hybrid Heaven (U) [f1] (PAL) +CRC=FB610592 898A9705 +RefMD5=C47E95BB32AB132C41D67BD243F9E02A + +[0A44393E1C97E4F91303029E27F28AF4] +GoodName=Hybrid Heaven (U) [t1] +CRC=E8DBC96A DAC9E2EE +RefMD5=C47E95BB32AB132C41D67BD243F9E02A + +[434BB8DE49011573AC38E893224C5623] +GoodName=Hydro Thunder (E) [!] +CRC=B58988E9 B1FC4BE8 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[1F57194EA272CF5DB500D228E9C94D75] +GoodName=Hydro Thunder (E) [f1] (NTSC) +CRC=EDFB6B01 8893F62C +RefMD5=434BB8DE49011573AC38E893224C5623 + +[4B4C85D9DD2D460ADAFABAE8DB48B4FA] +GoodName=Hydro Thunder (F) [!] +CRC=29A045CE ABA9060E +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[54F43E6B68782E98CAABEA5E7976B2BE] +GoodName=Hydro Thunder (U) [!] +CRC=C8DC65EB 3D8C8904 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[22AAD544C062FB8A2DC6B2DEB32DE188] +GoodName=Hydro Thunder (U) [b1] +CRC=C8DC65EB 3D8C8904 +RefMD5=54F43E6B68782E98CAABEA5E7976B2BE + +[71DCDBE9F4B37A251E2877900CDBF406] +GoodName=Hydro Thunder (U) [b1][f1] (PAL) +CRC=63CCD041 F12A8BC0 +RefMD5=54F43E6B68782E98CAABEA5E7976B2BE + +[A5B6E5D7B689216BA5C8F6360BF89B67] +GoodName=Hydro Thunder (U) [b1][t1] +CRC=B6DB2595 BC45273B +RefMD5=54F43E6B68782E98CAABEA5E7976B2BE + +[85ACEBC851A407630D7464CCB63408BE] +GoodName=Hydro Thunder (U) [b2] +CRC=C8DC65EB 3D8C8904 +RefMD5=54F43E6B68782E98CAABEA5E7976B2BE + +[F47575C35C7352E685B848CDAFF96B80] +GoodName=Hydro Thunder (U) [b3] +CRC=C8DC65EB 3D8C8904 +RefMD5=54F43E6B68782E98CAABEA5E7976B2BE + +[D2F7B3ACE75A2CE7A06BEAC929711D94] +GoodName=Hyper Olympics in Nagano 64 (J) [!] +CRC=2FC5C34C 7A05CC9D +Players=4 +SaveType=None +Mempak=Yes + +[3B6FF1829CBBEAE87704F53950791D64] +GoodName=Hyper Olympics in Nagano 64 (J) [b1] +CRC=2FC5C34C 7A05CC9D +RefMD5=D2F7B3ACE75A2CE7A06BEAC929711D94 + +[F4D2BE1C47486AB3A6FCCCD2E7532C67] +GoodName=Hyper Olympics in Nagano 64 (J) [b2] +CRC=2FC5C34C 7A05CC9D +RefMD5=D2F7B3ACE75A2CE7A06BEAC929711D94 + +[BAC8634F10F286E6A0DB889FCD12B25E] +GoodName=Hyper Olympics in Nagano 64 (J) [b3] +CRC=2FC5C34C 7A05CC9D +RefMD5=D2F7B3ACE75A2CE7A06BEAC929711D94 + +[20AE0BA68601EB0A49D61BC7A00FEADD] +GoodName=Hyper Olympics in Nagano 64 (J) [o1] +CRC=2FC5C34C 7A05CC9D +RefMD5=D2F7B3ACE75A2CE7A06BEAC929711D94 + +[92A6FFA1C8D537C7A97C5C613CAE05C6] +GoodName=Ide Yousuke no Mahjong Juku (J) [!] +CRC=77DA3B8D 162B0D7C +Players=1 +SaveType=Eeprom 16KB + +[DC577D70E9308F94E5F3CE03F3508539] +GoodName=Ide Yousuke no Mahjong Juku (J) [b1] +CRC=77DA3B8D 162B0D7C +RefMD5=92A6FFA1C8D537C7A97C5C613CAE05C6 + +[25B297143E9E5CCBB4B80A7FB6AF399B] +GoodName=Iggy's Reckin' Balls (E) [!] +CRC=D692CC5E EC58D072 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes +DisableExtraMem=1 + +[26CEC7A56ABB81F3468CFA26D8F16B67] +GoodName=Iggy's Reckin' Balls (E) [o1] +CRC=D692CC5E EC58D072 +RefMD5=25B297143E9E5CCBB4B80A7FB6AF399B + +[464211ABB602EE1005974D2D835A3BCF] +GoodName=Iggy's Reckin' Balls (U) [!] +CRC=E616B5BC C9658B88 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes +DisableExtraMem=1 + +[8BF0EAFB7014B7B5CE8E7D778B6B4B99] +GoodName=Iggy's Reckin' Balls (U) [o1] +CRC=E616B5BC C9658B88 +RefMD5=464211ABB602EE1005974D2D835A3BCF + +[C70B0B680807F2B8C2C3D5DC495FA8C2] +GoodName=Iggy-kun no Bura Bura Poyon (J) [!] +CRC=69458B9E FC95F936 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes +DisableExtraMem=1 + +[827106236756DC5B585C4226184835FA] +GoodName=Iggy-kun no Bura Bura Poyon (J) [o1] +CRC=69458B9E FC95F936 +RefMD5=C70B0B680807F2B8C2C3D5DC495FA8C2 + +[C605F40BF669E00A5E51BAF0D00621EA] +GoodName=In-Fisherman Bass Hunter 64 (U) [!] +CRC=8C138BE0 95700E46 +SaveType=Eeprom 4KB +Players=1 +Rumble=Yes +CountPerOp=1 + +[1AF93922A67085AB2C777B1F08AF365B] +GoodName=In-Fisherman Bass Hunter 64 (U) [f1] (PAL) +CRC=F050D644 B5A5CED1 +RefMD5=C605F40BF669E00A5E51BAF0D00621EA + +[70DE1EAB508596B6BBEFD168B5D07194] +GoodName=Indiana Jones and the Infernal Machine (U) [!] +CRC=AF9DCC15 1A723D88 +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[63D7AB29BA3DFC5D5B12C1D9C5832355] +GoodName=Indiana Jones and the Infernal Machine (E) (Unreleased) +CRC=3A6F8C6B 2897BAEB +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[A7781D441AF55C4FF8AFC68AB3A59313] +GoodName=Indy Racing 2000 (U) [!] +CRC=E436467A 82DE8F9B +SaveType=Eeprom 4KB +Players=2 +Rumble=Yes + +[34489365B550F32C97337D86D52D8C84] +GoodName=International Superstar Soccer '98 (E) [!] +CRC=F41B6343 C10661E6 +Players=4 +SaveType=None +Mempak=Yes + +[7DCC05B98E2FA690B478808EBBAD5D1A] +GoodName=International Superstar Soccer '98 (U) [!] +CRC=7F0FDA09 6061CE0B +Players=4 +SaveType=None +Mempak=Yes + +[43B326B27B89288F2D17D22EA49F86BD] +GoodName=International Superstar Soccer '98 (U) [o1] +CRC=7F0FDA09 6061CE0B +RefMD5=7DCC05B98E2FA690B478808EBBAD5D1A + +[9F101B6F6BEF4F267DEB5C6C37A24B97] +GoodName=International Superstar Soccer 2000 (E) (M2) (Eng-Ger) [!] +CRC=336364A0 06C8D5BF +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[CC2BE97A16744860FAE8A94611479C4C] +GoodName=International Superstar Soccer 2000 (E) (M2) (Fre-Ita) [!] +CRC=BAE8E871 35FF944E +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[23A4ED8D79882594206173B1D476F0E9] +GoodName=International Superstar Soccer 2000 (U) (M2) [!] +CRC=8E835437 CD5748B4 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[ACF18822457A451B09BD88E15A70505C] +GoodName=International Superstar Soccer 2000 (U) (M2) [f1] (PAL) +CRC=30B6A6AB 319EFD09 +RefMD5=23A4ED8D79882594206173B1D476F0E9 + +[DE9498BE76134BD066AA714CE2C71A16] +GoodName=International Superstar Soccer 2000 (U) (V1.1) (M2) [!] +CRC=96816CCD 272EA8C +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[376803F28CA8B2133671783419933CA2] +GoodName=International Superstar Soccer 64 (E) [!] +CRC=E2D37CF0 F57E4EAE +Players=4 +SaveType=None +Mempak=Yes +CountPerOp=1 + +[7FCC22F4BF1FC82F886C455981D2A420] +GoodName=International Superstar Soccer 64 (E) [b1] +CRC=E2D37CF0 F57E4EAE +RefMD5=376803F28CA8B2133671783419933CA2 + +[FD0102D535BC3BBB22DD823A636DC757] +GoodName=International Superstar Soccer 64 (E) [b2] +CRC=E2D37CF0 F57E4EAE +RefMD5=376803F28CA8B2133671783419933CA2 + +[65B9CAC3900435ED6893B9D489F1655F] +GoodName=International Superstar Soccer 64 (E) [h1C] +CRC=E2D37CF0 F57E4EAE +RefMD5=376803F28CA8B2133671783419933CA2 + +[70D480A73DB5751EED9E826108005834] +GoodName=International Superstar Soccer 64 (E) [h2C] +CRC=E2D37CF0 F57E4EAE +RefMD5=376803F28CA8B2133671783419933CA2 + +[6A345402AE1DB5CE1041365E36126BCE] +GoodName=International Superstar Soccer 64 (U) [!] +CRC=5F2763C4 62412AE5 +Players=4 +SaveType=None +Mempak=Yes +CountPerOp=1 + +[C0969E1C141BE6E144E651CAB1AEA3D8] +GoodName=International Superstar Soccer 64 (U) [b1] +CRC=5F2763C4 62412AE5 +RefMD5=6A345402AE1DB5CE1041365E36126BCE + +[0321FCDCD35E6DC0D3F4DC1251919997] +GoodName=International Superstar Soccer 64 (U) [h1C] +CRC=5F2763C4 62412AE5 +RefMD5=6A345402AE1DB5CE1041365E36126BCE + +[37A4F634CADB89DC3E43D389ED050925] +GoodName=International Superstar Soccer 64 (U) [h2C] +CRC=5F2763C4 62412AE5 +RefMD5=6A345402AE1DB5CE1041365E36126BCE + +[35662CFD07FD6AF4BAB90CA23F7C98E6] +GoodName=International Track & Field 2000 (U) [!] +CRC=20073BC7 5E3B0111 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[970488FB7D9C5C25BD924E6F898B84A0] +GoodName=International Track & Field Summer Games (E) (M3) [!] +CRC=6712C779 3B72781D +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[F9190DBAF547D6D3F5F3569ACCF26061] +GoodName=iQue Club (Ch) (V3) (iQue) [!] + +[1247B093E0FD6CCFD50D15DE59301076] +GoodName=J.League Dynamite Soccer 64 (J) [!] +CRC=87766747 91C27165 +Players=4 +Mempak=Yes + +[849DA5F1790A386B1CD9118CA1398E9D] +GoodName=J.League Dynamite Soccer 64 (J) [b1] +CRC=87766747 91C27165 +RefMD5=1247B093E0FD6CCFD50D15DE59301076 + +[F3A1B04E1F3436E183932B54212B75B5] +GoodName=J.League Dynamite Soccer 64 (J) [b2] +CRC=87766747 91C27165 +RefMD5=1247B093E0FD6CCFD50D15DE59301076 + +[20FBBA5FCCB7454367E071A744D6BB2F] +GoodName=J.League Dynamite Soccer 64 (J) [b3] +CRC=87766747 91C27165 +RefMD5=1247B093E0FD6CCFD50D15DE59301076 + +[2085FBD994D3597A8A520F695E336382] +GoodName=J.League Dynamite Soccer 64 (J) [b4] +CRC=87766747 91C27165 +RefMD5=1247B093E0FD6CCFD50D15DE59301076 + +[E0071B3CE2E29597DC4C73D83402723C] +GoodName=J.League Dynamite Soccer 64 (J) [h1C] +CRC=87766747 91C27165 +RefMD5=1247B093E0FD6CCFD50D15DE59301076 + +[F7544B9DF78D3CDB1C1B31006372C531] +GoodName=J.League Dynamite Soccer 64 (J) [h2C] +CRC=87766747 91C27165 +RefMD5=1247B093E0FD6CCFD50D15DE59301076 + +[F848E34DC2918C708D2D0C02E082B06B] +GoodName=J.League Dynamite Soccer 64 (J) [h3C] +CRC=87766747 91C27165 +RefMD5=1247B093E0FD6CCFD50D15DE59301076 + +[30E23D3DE446E37E5E7FBEF6794A6FC9] +GoodName=J.League Eleven Beat 1997 (J) [!] +CRC=4FBFA429 6920BB15 +Players=4 +Mempak=Yes + +[E3CE4ADB8A7C0CF39E11A2846E00178A] +GoodName=J.League Eleven Beat 1997 (J) [b1][h1C] +CRC=4FBFA429 6920BB15 +RefMD5=30E23D3DE446E37E5E7FBEF6794A6FC9 + +[BEF0F36513F6FA8B01638319252B2B99] +GoodName=J.League Eleven Beat 1997 (J) [b2][h1C] +CRC=4FBFA429 6920BB15 +RefMD5=30E23D3DE446E37E5E7FBEF6794A6FC9 + +[476FDC0554BD3B4746FC871FDD02F4B2] +GoodName=J.League Eleven Beat 1997 (J) [h1C] +CRC=4FBFA429 6920BB15 +RefMD5=30E23D3DE446E37E5E7FBEF6794A6FC9 + +[209DB8333EEB526AE9A91209175348CE] +GoodName=J.League Live 64 (J) [!] +CRC=54554A42 E4985FFB +Players=4 +Mempak=Yes + +[46F584DBFA1E292F0ECA74CA1B12009C] +GoodName=J.League Live 64 (J) [b1] +CRC=54554A42 E4985FFB +RefMD5=209DB8333EEB526AE9A91209175348CE + +[800ACC7D609ECDB3E09E68CBD05F5FA0] +GoodName=J.League Tactics Soccer (J) (V1.0) [!] +CRC=E8D29DA0 15E61D94 +Players=4 + +[F604701C59C7D2BBA2492D0073E928F2] +GoodName=J.League Tactics Soccer (J) (V1.0) [b1] +CRC=E8D29DA0 15E61D94 +RefMD5=800ACC7D609ECDB3E09E68CBD05F5FA0 + +[7D5AFCD953BB15EC204B175761CA28C2] +GoodName=J.League Tactics Soccer (J) (V1.0) [f1] (PAL) +CRC=E8D2A500 5AA8DBCA +RefMD5=800ACC7D609ECDB3E09E68CBD05F5FA0 + +[793DBF504E20C92F6B73B4E8A25A220C] +GoodName=J.League Tactics Soccer (J) (V1.1) [!] +CRC=C6CE0AAA D117F019 +Players=4 + +[45F6B7EAF40E8445205904934EE365A6] +GoodName=JPEG Slideshow Viewer by Garth Elgar (PD) +CRC=A957851C 535A5667 + +[8EE01DE7DA2E9AD08D7ED913A5EE8632] +GoodName=Jangou Simulation Mahjong Do 64 (J) [!] +CRC=C73AD016 48C5537D +Players=1 +Mempak=Yes + +[82388A4B44EF74F9C250C8152AB93669] +GoodName=Jangou Simulation Mahjong Do 64 (J) [b1] +CRC=C73AD016 48C5537D +RefMD5=8EE01DE7DA2E9AD08D7ED913A5EE8632 + +[014464F2AC70FBBB94B08B9762E65A72] +GoodName=Jangou Simulation Mahjong Do 64 (J) [b2] +CRC=C73AD016 48C5537D +RefMD5=8EE01DE7DA2E9AD08D7ED913A5EE8632 + +[304F496CE0858959700C7F71E55C55B7] +GoodName=Jangou Simulation Mahjong Do 64 (J) [b3] +CRC=C73AD016 48C5537D +RefMD5=8EE01DE7DA2E9AD08D7ED913A5EE8632 + +[E3706865241D2BCA4F397B4567CF2C2E] +GoodName=Japan Pro Golf Tour 64 (J) [CART HACK] +CRC=C99936D1 23D1D65D + +[A45F7200537C0D928A88CBBA2DFEB680] +GoodName=Jeopardy! (U) [!] +CRC=69256460 B9A3F586 +Players=3 +SaveType=None + +[05318721C273CB65CFBDF78AC2724BF2] +GoodName=Jeopardy! (U) [h1C] +CRC=69256460 B9A3F586 +RefMD5=A45F7200537C0D928A88CBBA2DFEB680 + +[190584D9C0DC2875183FB84C5072B8F1] +GoodName=Jeopardy! (U) [o1] +CRC=69256460 B9A3F586 +RefMD5=A45F7200537C0D928A88CBBA2DFEB680 + +[79BDD4467E102A1CBB4CC74DFC96BF7D] +GoodName=Jeopardy! (U) [o1][h1C] +CRC=69256460 B9A3F586 +RefMD5=A45F7200537C0D928A88CBBA2DFEB680 + +[4C5BE1BFC1CCCFF501EBA2A685226962] +GoodName=Jeremy McGrath Supercross 2000 (E) [!] +CRC=21F7ABFB 6A8AA7E8 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[8046A4B8ABD4353B2AB9696106CCF8D2] +GoodName=Jeremy McGrath Supercross 2000 (U) [!] +CRC=BB30B1A5 FCF712CE +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[29E0AB31B3FC6A6B1EFC11FBDB82CB97] +GoodName=Jeremy McGrath Supercross 2000 (U) [f1] +CRC=46C6F185 E13841C8 +RefMD5=8046A4B8ABD4353B2AB9696106CCF8D2 + +[BAAF237E71AA7526C9B2F01C08B68A53] +GoodName=Jet Force Gemini (E) (M4) [!] +CRC=68D7A1DE 0079834A +Players=4 +SaveType=Flash RAM +Rumble=Yes + +[821E7F74880BBD04AA9501D3BB25138E] +GoodName=Jet Force Gemini (E) (M4) [T+Ita0.9beta_Rulesless] +CRC=68D7A1DE 0079834A +RefMD5=BAAF237E71AA7526C9B2F01C08B68A53 + +[76996A6CC868AC0E2BB2506A3C4DB606] +GoodName=Jet Force Gemini (E) (M4) [f1] +CRC=B66E0F7C 2709C22F +RefMD5=BAAF237E71AA7526C9B2F01C08B68A53 + +[5BBE9ADE7171F2E1DAAA7C48FAD38728] +GoodName=Jet Force Gemini (U) (Kiosk Demo) [!] +CRC=DFD8AB47 3CDBEB89 +Players=4 +Rumble=Yes + +[E423A21C971B8A91C3E8980E2605B840] +GoodName=Jet Force Gemini (U) (Kiosk Demo) [b1] +CRC=DFD8AB47 3CDBEB89 +RefMD5=5BBE9ADE7171F2E1DAAA7C48FAD38728 + +[2525E3734B921E662903E94BAB119C32] +GoodName=Jet Force Gemini (U) (Kiosk Demo) [b1][f1] (Save) +CRC=9C660FA0 C06A610D +RefMD5=5BBE9ADE7171F2E1DAAA7C48FAD38728 + +[B4E3489F9B655439F9902F7A466CF973] +GoodName=Jet Force Gemini (U) (Kiosk Demo) [b1][f2] +CRC=8547FED3 C4945FAF +RefMD5=5BBE9ADE7171F2E1DAAA7C48FAD38728 + +[69144CEED3F4D7B208D81A3DC3F57AD0] +GoodName=Jet Force Gemini (U) (Kiosk Demo) [b2] +CRC=DFD8AB47 3CDBEB89 +RefMD5=5BBE9ADE7171F2E1DAAA7C48FAD38728 + +[772CC6EAB2620D2D3CDC17BBC26C4F68] +GoodName=Jet Force Gemini (U) [!] +CRC=8A6009B6 94ACE150 +Players=4 +SaveType=Flash RAM +Rumble=Yes + +[92E6117285EC6A2D836B1C6839DDFD9B] +GoodName=Jet Force Gemini (U) [b1] +CRC=75CAA990 9FFDC9BD +RefMD5=772CC6EAB2620D2D3CDC17BBC26C4F68 + +[745FCD72A921ED178AF6C319B09DF1F3] +GoodName=Jet Force Gemini (U) [b2] +CRC=CDB8B4D0 8832352D +RefMD5=772CC6EAB2620D2D3CDC17BBC26C4F68 + +[878D8A26FD02FDB08200464CB6F566EF] +GoodName=Jikkyou G1 Stable (J) (V1.0) [!] +CRC=AF19D9F5 B70223CC +Players=4 +Mempak=Yes + +[4BBAF03594C6DCECB135AC8C57CB4CD7] +GoodName=Jikkyou G1 Stable (J) (V1.0) [b1] +CRC=AF19D9F5 B70223CC +RefMD5=878D8A26FD02FDB08200464CB6F566EF + +[482BDD39AD2574B943DB780B12A9BDFB] +GoodName=Jikkyou G1 Stable (J) (V1.1) [!] +CRC=575F340B 9F1398B2 +Players=4 +Mempak=Yes + +[1FB40EE386B58FEAB6CF29DDB33BCCCC] +GoodName=Jikkyou J.League 1999 - Perfect Striker 2 (J) (V1.0) [!] +CRC=63112A53 A29FA88F +Players=4 +Mempak=Yes +Rumble=Yes + +[3D2CCA1B2E3BDE267769812219EDB864] +GoodName=Jikkyou J.League 1999 - Perfect Striker 2 (J) (V1.0) [b1] +CRC=63112A53 A29FA88F +RefMD5=1FB40EE386B58FEAB6CF29DDB33BCCCC + +[84B1421F658D5185812D861E23437520] +GoodName=Jikkyou J.League 1999 - Perfect Striker 2 (J) (V1.0) [b2] +CRC=63112A53 A29FA88F +RefMD5=1FB40EE386B58FEAB6CF29DDB33BCCCC + +[B141C46C0FB2918D59933107EA8C1B7A] +GoodName=Jikkyou J.League 1999 - Perfect Striker 2 (J) (V1.0) [f1] (PAL) +CRC=3DBD5E85 EA9A328A +RefMD5=1FB40EE386B58FEAB6CF29DDB33BCCCC + +[476203B64E2204306B591D5D3AFC7183] +GoodName=Jikkyou J.League 1999 - Perfect Striker 2 (J) (V1.0) [f2] (PAL) +CRC=22CA2C52 CA62736F +RefMD5=1FB40EE386B58FEAB6CF29DDB33BCCCC + +[D9F8B84FD6FD21F0B1D750062AC86EFC] +GoodName=Jikkyou J.League 1999 - Perfect Striker 2 (J) (V1.1) [!] +CRC=6309FC17 1D4F5EF3 +Players=4 +Mempak=Yes +Rumble=Yes + +[58153AC5C4030D1BFD3C15CF57FB02E7] +GoodName=Jikkyou J.League Perfect Striker (J) [!] +CRC=146C4366 72A6DEB3 +Players=4 +Mempak=Yes + +[759B8749E55113526E8C1C468E244CA8] +GoodName=Jikkyou J.League Perfect Striker (J) [b1] +CRC=146C4366 72A6DEB3 +RefMD5=58153AC5C4030D1BFD3C15CF57FB02E7 + +[F012DC3C0CAA38618A1FAD27C73FCBD5] +GoodName=Jikkyou J.League Perfect Striker (J) [b2] +CRC=146C4366 72A6DEB3 +RefMD5=58153AC5C4030D1BFD3C15CF57FB02E7 + +[6D1D465EBAACD3747B1362037ABED9EF] +GoodName=Jikkyou J.League Perfect Striker (J) [b3] +CRC=146C4366 72A6DEB3 +RefMD5=58153AC5C4030D1BFD3C15CF57FB02E7 + +[C7152167915E8EB928C0CBBF9AF9886E] +GoodName=Jikkyou J.League Perfect Striker (J) [f1] (PAL) +CRC=3BCCA16E 0AF6D30F +RefMD5=58153AC5C4030D1BFD3C15CF57FB02E7 + +[7FC933A64884A382AA07605EA7204FF5] +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) [!] +CRC=0AC244D1 1F0EC605 +Players=4 +Mempak=Yes +Transferpak=Yes + +[B653C963ED8D3A749676810F07CFE4E5] +GoodName=Jikkyou Powerful Pro Yakyuu 2000 (J) (V1.1) [!] +CRC=4264DF23 BE28BDF7 +Players=4 +Mempak=Yes +Transferpak=Yes + +[FDA57F65EB159278223EB9D03267C27F] +GoodName=Jikkyou Powerful Pro Yakyuu 4 (J) (V1.0) [!] +CRC=34495BAD 502E9D26 +Players=4 +Mempak=Yes + +[7CC328FFAA5B77CD6247124DD0AF8899] +GoodName=Jikkyou Powerful Pro Yakyuu 4 (J) (V1.0) [b1] +CRC=34495BAD 502E9D26 +RefMD5=FDA57F65EB159278223EB9D03267C27F + +[924E6553AEDE5EA66E2E14D29E48D929] +GoodName=Jikkyou Powerful Pro Yakyuu 4 (J) (V1.0) [b2] +CRC=34495BAD 502E9D26 +RefMD5=FDA57F65EB159278223EB9D03267C27F + +[D9BA9FC609BFCDAC0081B7C568311BE1] +GoodName=Jikkyou Powerful Pro Yakyuu 4 (J) (V1.0) [b3] +CRC=34495BAD 502E9D26 +RefMD5=FDA57F65EB159278223EB9D03267C27F + +[2BBD484BFA0F16C09C7F13FBDC2637C6] +GoodName=Jikkyou Powerful Pro Yakyuu 4 (J) (V1.0) [b4] +CRC=34495BAD 502E9D26 +RefMD5=FDA57F65EB159278223EB9D03267C27F + +[1480E755E96B392490F606A75BC306C6] +GoodName=Jikkyou Powerful Pro Yakyuu 4 (J) (V1.0) [b5] +CRC=34495BAD 502E9D26 +RefMD5=FDA57F65EB159278223EB9D03267C27F + +[950B88955933F42514A3F4284F5A285C] +GoodName=Jikkyou Powerful Pro Yakyuu 4 (J) (V1.0) [o1] +CRC=34495BAD 502E9D26 +RefMD5=FDA57F65EB159278223EB9D03267C27F + +[B454490EB44F0978F009FA41DE8C478E] +GoodName=Jikkyou Powerful Pro Yakyuu 4 (J) (V1.1) [!] +CRC=D7891F1C C3E43788 +Players=4 +Mempak=Yes + +[E9F989E09E3F1519AEFE619889A4F710] +GoodName=Jikkyou Powerful Pro Yakyuu 5 (J) (V1.0) [!] +CRC=D22943DA AC2B77C0 +Players=4 +Mempak=Yes + +[CAFF2DAC142F169EE76965CA00518B26] +GoodName=Jikkyou Powerful Pro Yakyuu 5 (J) (V1.0) [b1] +CRC=D22943DA AC2B77C0 +RefMD5=E9F989E09E3F1519AEFE619889A4F710 + +[4AC1589C067AC573FD63912A5C6C47A5] +GoodName=Jikkyou Powerful Pro Yakyuu 5 (J) (V1.0) [f1] +CRC=95854656 C8A24DC5 +RefMD5=E9F989E09E3F1519AEFE619889A4F710 + +[8AF9D04DBA1313D1F5F4BA51D9592FBB] +GoodName=Jikkyou Powerful Pro Yakyuu 5 (J) (V1.0) [f2] (PAL) +CRC=38D637C1 5F05D28F +RefMD5=E9F989E09E3F1519AEFE619889A4F710 + +[6EF19BF8D8D6196390745F1B858AC16A] +GoodName=Jikkyou Powerful Pro Yakyuu 5 (J) (V1.1) [!] +CRC=1C8CDF74 F761051F +Players=4 +Mempak=Yes + +[68A27FBAB060857C267A639931D2C3D6] +GoodName=Jikkyou Powerful Pro Yakyuu 5 (J) (V1.2) [!] +CRC=AC173077 5A14C012 +Players=4 +Mempak=Yes + +[060D0313E23B660180441FCC7D24D7DB] +GoodName=Jikkyou Powerful Pro Yakyuu 6 (J) (V1.0) [!] +CRC=B75E20B7 B3FEFDFD +Mempak=Yes +Transferpak=Yes + +[E6129460E23170FFD4EC4B09D5E0CC56] +GoodName=Jikkyou Powerful Pro Yakyuu 6 (J) (V1.0) [b1] +CRC=B75E20B7 B3FEFDFD +RefMD5=060D0313E23B660180441FCC7D24D7DB + +[23EE24FABA0EDFB04B5B0407E174496B] +GoodName=Jikkyou Powerful Pro Yakyuu 6 (J) (V1.1) [!] +CRC=3C084040 081B060C +Mempak=Yes +Transferpak=Yes + +[03BD8E5CA2B1B7D74398DB4739979282] +GoodName=Jikkyou Powerful Pro Yakyuu 6 (J) (V1.2) [!] +CRC=438E6026 3BA24E07 +Mempak=Yes +Transferpak=Yes + +[A05E7DB2409DEECCA36E48E9D931CACB] +GoodName=Jikkyou World Soccer - World Cup France '98 (J) (V1.0) [!] +CRC=3FEA5620 7456DB40 +Players=4 +Mempak=Yes + +[538B54C2AAEA73FAA3A021D42A3225BE] +GoodName=Jikkyou World Soccer - World Cup France '98 (J) (V1.1) [!] +CRC=C954B38C 6F62BEB3 +Players=4 +Mempak=Yes + +[2E5FD9303138E8F558BF67BB9E799960] +GoodName=Jikkyou World Soccer - World Cup France '98 (J) (V1.2) [!] +CRC=E1C7ABD6 4E707F28 +Players=4 +Mempak=Yes + +[EF0F425689586850A6F5796124B0C85B] +GoodName=Jikkyou World Soccer 3 (J) [!] +CRC=E0A79F8C 32CC97FA +Players=4 +Mempak=Yes +CountPerOp=1 + +[68230D510015FF6817EF898C0B8B636C] +GoodName=Jinsei Game 64 (J) [!] +CRC=4AAAF6ED 376428AD +Players=4 +Rumble=Yes + +[FBB0F6AF0A931EE4FEAEE4F3CC7DBE03] +GoodName=Jinsei Game 64 (J) [f1] (PAL) +CRC=7B016055 F8AC6092 +RefMD5=68230D510015FF6817EF898C0B8B636C + +[7AB29C6AD2D8F4007D8213EB3411E0BD] +GoodName=John Romero's Daikatana (E) (M3) [!] +CRC=0F743195 D8A6DB95 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[2B417AD282DB321C9C67EDA7131A7F06] +GoodName=John Romero's Daikatana (E) (M3) [f1] (NTSC) +CRC=B6835E54 04A4A0D0 +RefMD5=7AB29C6AD2D8F4007D8213EB3411E0BD + +[164050084561ECB691A51B6D1E5BF4AE] +GoodName=John Romero's Daikatana (E) (M3) [h1C] +CRC=0F743195 D8A6DB95 +RefMD5=7AB29C6AD2D8F4007D8213EB3411E0BD + +[57D31EA7121DD5A05B547225EFA5CFD7] +GoodName=John Romero's Daikatana (J) [!] +CRC=9D7E3C4B E60F4A6C +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[5B4C268422469F50B94779E655F2B798] +GoodName=John Romero's Daikatana (U) [!] +CRC=D0151AB0 FE5CA14B +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[DFF0EFE2B35FCDE506D21B0C0BD373A5] +GoodName=Kakutou Denshou - F-Cup Maniax (J) [!] +CRC=4F29474F 30CB707A +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[9A70D30114F440B5240C10260AB2C8ED] +GoodName=Kakutou Denshou - F-Cup Maniax (J) [f1] (PAL) +CRC=F6E3494A E4EC8933 +RefMD5=DFF0EFE2B35FCDE506D21B0C0BD373A5 + +[EEC0FAB75AF59E9C23E6DE2132DE89FF] +GoodName=Ken Griffey Jr.'s Slugfest (U) [!] +CRC=36281F23 009756CF +SaveType=Flash RAM +Players=2 +Rumble=Yes + +[040A9EA84FA3C73A8F318358E3250AA4] +GoodName=Ken Griffey Jr.'s Slugfest (U) [b1] +CRC=76A8C9F4 3391893D +RefMD5=EEC0FAB75AF59E9C23E6DE2132DE89FF + +[D9160E48CE1F06B9B749B43A38367A28] +GoodName=Ken Griffey Jr.'s Slugfest (U) [b2] +CRC=36281F23 009756CF +RefMD5=EEC0FAB75AF59E9C23E6DE2132DE89FF + +[BF07DE5816FFEC94AF30CB9B9B35909F] +GoodName=Ken Griffey Jr.'s Slugfest (U) [f1] +CRC=76A8C9F4 3391893D +RefMD5=EEC0FAB75AF59E9C23E6DE2132DE89FF + +[47B0348020C4200608B7EBD512028788] +GoodName=Ken Griffey Jr.'s Slugfest (U) [f2] (PAL) +CRC=76A8C9F4 3391893D +RefMD5=EEC0FAB75AF59E9C23E6DE2132DE89FF + +[57C6B3E6309AC2F4BB64B5161E4ED8EF] +GoodName=Ken Griffey Jr.'s Slugfest (U) [f3] (Nosave) +CRC=730D25F4 4A37A36E +RefMD5=EEC0FAB75AF59E9C23E6DE2132DE89FF + +[3E003A77F044F0C97748BE6861C55038] +GoodName=Ken Griffey Jr.'s Slugfest (U) [f4] (Nosave-Z64) +CRC=EAC07419 0F9F72A0 +RefMD5=EEC0FAB75AF59E9C23E6DE2132DE89FF + +[9362C5AC8CA78C12FF553CB7F12A7FF1] +GoodName=Ken Griffey Jr.'s Slugfest (U) [f5] +CRC=76A8C9F4 3391893D +RefMD5=EEC0FAB75AF59E9C23E6DE2132DE89FF + +[69F3D2580CB4C91C91C2E238C72B4403] +GoodName=Kid Stardust Intro with Sound by Kid Stardust (PD) +CRC=64709212 699BCF3B + +[68EB1713156605D5B05CFB838C214EF2] +GoodName=Kid Stardust Intro with Sound by Kid Stardust (PD) [a1] +CRC=64709212 699BCF3B +RefMD5=69F3D2580CB4C91C91C2E238C72B4403 + +[C93D92F10A1A97D2BA87386BE7D178FD] +GoodName=Killer Instinct Gold (E) [!] +CRC=979B263E F8470004 +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes + +[A63F43CC53D9E57A045E1E20A5B12592] +GoodName=Killer Instinct Gold (E) [o1] +CRC=979B263E F8470004 +RefMD5=C93D92F10A1A97D2BA87386BE7D178FD + +[8E33AD20C31FEB61D7230FAD28846C5C] +GoodName=Killer Instinct Gold (U) (V1.0) [!] +CRC=9E8FE2BA 8B270770 +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes + +[F73EA6171B04CD9FF05B76274E824194] +GoodName=Killer Instinct Gold (U) (V1.0) [b1] +CRC=9E8FE2BA 8B270770 +RefMD5=8E33AD20C31FEB61D7230FAD28846C5C + +[F871B07C700F5BB373E648FC64D99D2E] +GoodName=Killer Instinct Gold (U) (V1.0) [b1][t1] +CRC=06CB44B7 3163DB94 +RefMD5=8E33AD20C31FEB61D7230FAD28846C5C + +[D4CD4F6A5029048B44C8B420982E664E] +GoodName=Killer Instinct Gold (U) (V1.0) [b2] +CRC=06CB44B7 3163DB94 +RefMD5=8E33AD20C31FEB61D7230FAD28846C5C + +[3EE5EF09471ED2ADF02E6E1BA8D17963] +GoodName=Killer Instinct Gold (U) (V1.0) [b3] +CRC=06CB44B7 3163DB94 +RefMD5=8E33AD20C31FEB61D7230FAD28846C5C + +[DD44E1D799FB9000983C5291D9D34306] +GoodName=Killer Instinct Gold (U) (V1.0) [b4] +CRC=06CB44B7 3163DB94 +RefMD5=8E33AD20C31FEB61D7230FAD28846C5C + +[C0B6DEEF900B63A5E4624804B14A1BA6] +GoodName=Killer Instinct Gold (U) (V1.0) [b5] +CRC=9E8FE2BA 8B270770 +RefMD5=8E33AD20C31FEB61D7230FAD28846C5C + +[4C58608F3879627886051B7C035E3C23] +GoodName=Killer Instinct Gold (U) (V1.0) [o1] +CRC=9E8FE2BA 8B270770 +RefMD5=8E33AD20C31FEB61D7230FAD28846C5C + +[DF607E79B1539F7D6F9AD34C31F42296] +GoodName=Killer Instinct Gold (U) (V1.0) [o2] +CRC=9E8FE2BA 8B270770 +RefMD5=8E33AD20C31FEB61D7230FAD28846C5C + +[7496F1814AFBD1FC85FE76D6EBE9EA03] +GoodName=Killer Instinct Gold (U) (V1.0) [t1] +CRC=06CB44B7 3163DB94 +RefMD5=8E33AD20C31FEB61D7230FAD28846C5C + +[1C3B29CC7F362CA63AC1C26456737BB3] +GoodName=Killer Instinct Gold (U) (V1.0) [t2] +CRC=06CB44B7 3163DB94 +RefMD5=8E33AD20C31FEB61D7230FAD28846C5C + +[4C9B419DC583C0DF4AB908ADF83BFC65] +GoodName=Killer Instinct Gold (U) (V1.1) [!] +CRC=9E8FCDFA 49F5652B +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes + +[0CFF6A7C1B1334E07585F0C5CDB53B40] +GoodName=Killer Instinct Gold (U) (V1.1) [o1] +CRC=9E8FCDFA 49F5652B +RefMD5=4C9B419DC583C0DF4AB908ADF83BFC65 + +[DD0A82FCC10397AFB37F12BB7F94E67A] +GoodName=Killer Instinct Gold (U) (V1.2) [!] +CRC=F908CA4C 36464327 +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes + +[2D79C395765A601F967CD3EF7CBF439E] +GoodName=Killer Instinct Gold (U) (V1.2) [b1] +CRC=06CB44B7 3163DB94 +RefMD5=DD0A82FCC10397AFB37F12BB7F94E67A + +[3166BE5787BC30526E71277ECA3091DF] +GoodName=Killer Instinct Gold (U) (V1.2) [o1] +CRC=F908CA4C 36464327 +RefMD5=DD0A82FCC10397AFB37F12BB7F94E67A + +[CCA4E87EC206B5B65AEAB9531C0F275B] +GoodName=King Hill 64 - Extreme Snowboarding (J) [!] +CRC=519EA4E1 EB7584E8 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[CE9AE0AA6DBBF965B1F72BC3AA6A7CEF] +GoodName=King Hill 64 - Extreme Snowboarding (J) [b1] +CRC=519EA4E1 EB7584E8 +RefMD5=CCA4E87EC206B5B65AEAB9531C0F275B + +[18E741AAC72ECA5A9FEFEFE6F7A3E57A] +GoodName=King Hill 64 - Extreme Snowboarding (J) [b2] +CRC=519EA4E1 EB7584E8 +RefMD5=CCA4E87EC206B5B65AEAB9531C0F275B + +[32257BFFFD9B2D680F582E148E9B0611] +GoodName=Kira to Kaiketsu! 64 Tanteidan (J) [!] +CRC=75BC6AD6 78552BC9 +Players=4 +Mempak=Yes +Rumble=Yes + +[A44B7A612964A6D6139D0426E569D9C9] +GoodName=Kirby 64 - The Crystal Shards (E) [!] +CRC=0D93BA11 683868A6 +Players=4 +SaveType=Eeprom 16KB +Rumble=Yes + +[E3BFAF1AD4A58A3AB7FD7310C1F45D81] +GoodName=Kirby 64 - The Crystal Shards (E) [b1] +CRC=0D93BA11 683868A6 +RefMD5=A44B7A612964A6D6139D0426E569D9C9 + +[E32385ECE93DF2228FBEFE3113220A20] +GoodName=Kirby 64 - The Crystal Shards (E) [f1] +CRC=94593D97 846A278C +RefMD5=A44B7A612964A6D6139D0426E569D9C9 + +[D33E4254336383A17FF4728360562ADA] +GoodName=Kirby 64 - The Crystal Shards (U) [!] +CRC=46039FB4 0337822C +Players=4 +SaveType=Eeprom 16KB +Rumble=Yes + +[329C0A564D3B4477E2887097389AB7D6] +GoodName=Kirby 64 - The Crystal Shards (U) [b1] +CRC=80A2BBB5 828DFD3E +RefMD5=D33E4254336383A17FF4728360562ADA + +[0CBA02D6EA55809A1E8D9BA02D199B7D] +GoodName=Kirby 64 - The Crystal Shards (U) [b2] +CRC=22F301B6 D0A03C3C +RefMD5=D33E4254336383A17FF4728360562ADA + +[0A010DFFB20B9A4FB7BA2F962788F54F] +GoodName=Kirby 64 - The Crystal Shards (U) [f1] +CRC=D3F52BA5 1258EDFE +RefMD5=D33E4254336383A17FF4728360562ADA + +[99F4652FEFF7373576ED440E1D33DB24] +GoodName=Kirby 64 - The Crystal Shards (U) [t1] +CRC=CBF72BBD 5D1587B2 +RefMD5=D33E4254336383A17FF4728360562ADA + +[D31A94A5685A21A932CC886D64CC9B21] +GoodName=Knife Edge - Nose Gunner (E) [!] +CRC=4A997C74 E2087F99 +Players=4 +SaveType=None +Rumble=Yes + +[436BA873E9466AAB237D9429348A5F70] +GoodName=Knife Edge - Nose Gunner (J) [!] +CRC=931AEF3F EF196B90 +Players=4 +SaveType=None +Rumble=Yes + +[8043D829FCD4F8F72DD81E5C6DDE916F] +GoodName=Knife Edge - Nose Gunner (U) [!] +CRC=FCE0D799 65316C54 +Players=4 +SaveType=None +Rumble=Yes + +[ABFDAA35C995C839D0773D3601D59E67] +GoodName=Knife Edge - Nose Gunner (U) [b1][t1] +CRC=84F5C897 A870AC11 +RefMD5=8043D829FCD4F8F72DD81E5C6DDE916F + +[FCFBFD04A56400DE8B84297CF37CEE3D] +GoodName=Knife Edge - Nose Gunner (U) [hI] +CRC=84F5CF63 08EE7EDC +RefMD5=8043D829FCD4F8F72DD81E5C6DDE916F + +[760110BC5733A4AC31EE680A06F4F2A1] +GoodName=Knife Edge - Nose Gunner (U) [hI][t1] +CRC=84F5C897 A870AC11 +RefMD5=8043D829FCD4F8F72DD81E5C6DDE916F + +[2CA82F82284D2B3FE381999889350855] +GoodName=Knife Edge - Nose Gunner (U) [t1] +CRC=84F5C897 A870AC11 +RefMD5=8043D829FCD4F8F72DD81E5C6DDE916F + +[E95D73FF55FBB63E79AA9EAB14608584] +GoodName=Knockout Kings 2000 (E) [!] +CRC=E3D6A795 2A1C5D3C +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[008B473841CE4D9AC050D55F99B4B5D4] +GoodName=Knockout Kings 2000 (U) [!] +CRC=0894909C DAD4D82D +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[630400D4E2DCED3DDE56DFCCF39A512A] +GoodName=Knockout Kings 2000 (U) [f1] (PAL) +CRC=8D6F5219 D43B163C +RefMD5=008B473841CE4D9AC050D55F99B4B5D4 + +[C6B01C020FDFD2E5C037C5A330B161AD] +GoodName=Kobe Bryant in NBA Courtside (E) [!] +CRC=1739EFBA D0B43A68 +SaveType=Eeprom 16KB +Players=4 +Mempak=Yes +Rumble=Yes + +[54FD2659FCCE58FCC6EE544F95F8F7A3] +GoodName=Kobe Bryant in NBA Courtside (E) [f1] +CRC=D03F0CCB 11F19CDD +RefMD5=C6B01C020FDFD2E5C037C5A330B161AD + +[D37C79E4E4EABCB5DC6A07BD76688223] +GoodName=Kobe Bryant's NBA Courtside (U) [!] +CRC=616B8494 8A509210 +SaveType=Eeprom 16KB +Players=4 +Mempak=Yes +Rumble=Yes + +[EF9A84FBF0B4C31E581648F256E8ED81] +GoodName=Kobe Bryant's NBA Courtside (U) [f1] +CRC=5BC51145 D3A29FE7 +RefMD5=D37C79E4E4EABCB5DC6A07BD76688223 + +[AA0727F8F2B2C233F7BFD202194D41BC] +GoodName=Kobe Bryant's NBA Courtside (U) [h1C] +CRC=616B8494 8A509210 +RefMD5=D37C79E4E4EABCB5DC6A07BD76688223 + +[3E2AD600BD89B21531F59A84839FE732] +GoodName=Kuru Kuru Fever (Aleck64) +CRC=4248BA87 99BE605D +SaveType=Eeprom 4KB + +[6B53B94B64DD8ACAE1B43BDA2CAF23FC] +GoodName=Kyojin no Doshin 1 (J) [CART HACK] +CRC=0837F87A D1436FF8 + +[73FFACDB7F649154984A5957ED451257] +GoodName=Kyojin no Doshin 1 (J) (Kiosk Demo) [CART HACK] +CRC=E7BDA0BE ADA09CAC + +[C57C4DD678748C6ED7CBF498445DE247] +GoodName=Kyojin no Doshin: Kaihou Sensen Chibikko Chikko Daishuugou (J) [CART HACK] +CRC=8C47CE8B 06019FEF +Players=1 +Rumble=Yes + +[28803DC0D1CD120E5C0285F7291626B8] +GoodName=LCARS Demo by WT Riker (PD) +CRC=F828DF21 C5E83F66 + +[E7432C73FE47991B52EB4A44156A8D9D] +GoodName=LCARS Demo by WT Riker (PD) [b1] +CRC=F828DF21 C5E83F66 +RefMD5=28803DC0D1CD120E5C0285F7291626B8 + +[6310C7173385ED2B06020F3B90158E9E] +GoodName=LEGO Racers (E) (M10) [!] +CRC=F478D8B3 9716DD6D +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=3 + +[26B5EAA13DC5B5E35307FE8C0CF5B6BA] +GoodName=LEGO Racers (U) (M10) [!] +CRC=096A40EA 8ABE0A10 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=3 + +[97C4CAE584F427EC44266E9B98FBF7B6] +GoodName=LEGO Racers (U) (M10) [b1] +CRC=096A40EA 8ABE0A10 +RefMD5=26B5EAA13DC5B5E35307FE8C0CF5B6BA + +[E74404ED5A7076855CDE3832474751B6] +GoodName=LEGO Racers (U) (M10) [b1][f1] (PAL) +CRC=BB53C809 269594C6 +RefMD5=26B5EAA13DC5B5E35307FE8C0CF5B6BA + +[1221C67C46C77487D35F03D3D13A3022] +GoodName=LEGO Racers (U) (M10) [b1][t1] +CRC=B0AC4321 3F4DA1AF +RefMD5=26B5EAA13DC5B5E35307FE8C0CF5B6BA + +[050531139C082E35B101E0929B6E07EA] +GoodName=LaC's MOD Player - The Temple Gates (PD) +CRC=8E97A4A6 D1F31B33 +Status=3 +SaveType=None +Players=0 +Rumble=No + +[9602768EA88F4F5B53237E1AA20DE68A] +GoodName=LaC's Universal Bootemu V1.0 (PD) +CRC=EF623F50 ECBB509B + +[EB712F2E8A6A893141B82607B11DA8A2] +GoodName=LaC's Universal Bootemu V1.1 (PD) +CRC=BB752DA7 30D8BEF4 + +[15C2C37D4FFA1E2C5BC4D1029BC225AC] +GoodName=LaC's Universal Bootemu V1.2 (PD) +CRC=FF0AC362 F4EC09B3 + +[EB11FC0797AE1107201C4601FEE5471A] +GoodName=Last Legion UX (J) [!] +CRC=7F304099 52CF5276 +Players=2 +Rumble=Yes + +[8E55FD6990472A08568324309C2FD31F] +GoodName=Last Legion UX (J) [a1] +CRC=7F304099 52CF5276 +RefMD5=EB11FC0797AE1107201C4601FEE5471A + +[7B5988138A8ADCA592DE616260B2700D] +GoodName=Last Legion UX (J) [b1] +CRC=7F304099 52CF5276 +RefMD5=EB11FC0797AE1107201C4601FEE5471A + +[F8D705AD5EFF0DB9E3E17A7ECB6D2123] +GoodName=Last Legion UX (J) [b2] +CRC=7F304099 52CF5276 +RefMD5=EB11FC0797AE1107201C4601FEE5471A + +[0C13E0449A28EA5B925CDB8AF8D29768] +GoodName=Zelda no Densetsu - Toki no Ocarina - Zelda Collection Version (J) (GC) [!] +CRC=F7F52DB8 2195E636 +SaveType=SRAM +Status=4 +Rumble=Yes +Players=1 +; End Credits Fix +Cheat0=D109A814 0320,8109A814 0000,D109A816 F809,8109A816 0000 + +[33FB7852C180B18EA0B9620B630F413F] +GoodName=Zelda no Densetsu - Toki no Ocarina GC (J) (GC) [!] +CRC=F611F4BA C584135C +SaveType=SRAM +Status=4 +Rumble=Yes +Players=1 +; End Credits Fix +Cheat0=D109A834 0320,8109A834 0000,D109A836 F809,8109A836 0000 + +[69895C5C78442260F6EAFB2506DC482A] +GoodName=Zelda no Densetsu - Toki no Ocarina GC URA (J) (GC) [!] +CRC=F43B45BA 2F0E9B6F +SaveType=SRAM +Status=4 +Rumble=Yes +Players=1 +; End Credits Fix +Cheat0=D109A814 0320,8109A814 0000,D109A816 F809,8109A816 0000 + +[13FAB67E603B002CEAF0EEA84130E973] +GoodName=Legend of Zelda, The - Majora's Mask (E) (M4) (V1.0) [!] +CRC=E97955C6 BC338D38 +SaveType=Flash RAM +Status=4 +Rumble=Yes +Players=1 + +[5798E844953662880C5EB4134F886909] +GoodName=Legend of Zelda, The - Majora's Mask (E) (M4) (V1.0) [T+Ita1.0Beta_Vampire] +CRC=E97955C6 BC338D38 +RefMD5=13FAB67E603B002CEAF0EEA84130E973 + +[36759C85694A4CF5A1F089A4136DAE2B] +GoodName=Legend of Zelda, The - Majora's Mask (E) (M4) (V1.0) [T-Ita0.9M_Vampire] +CRC=E97955C6 BC338D38 +RefMD5=13FAB67E603B002CEAF0EEA84130E973 + +[6CBAC6E5B13A4A92347488DE1C806BC0] +GoodName=Legend of Zelda, The - Majora's Mask (E) (M4) (V1.0) [T-Ita0.9P1+G_Vampire] +CRC=E97955C6 BC338D38 +RefMD5=13FAB67E603B002CEAF0EEA84130E973 + +[44494CD5D6E3332F79465DE51C2EC636] +GoodName=Legend of Zelda, The - Majora's Mask (E) (M4) (V1.0) [T-Ita0.9Z3_Vampire] +CRC=E97955C6 BC338D38 +RefMD5=13FAB67E603B002CEAF0EEA84130E973 + +[585AA96CBB44DF3BBB3B294538B0605A] +GoodName=Legend of Zelda, The - Majora's Mask (E) (M4) (V1.0) [T-Ita0.9e_Vampire] +CRC=E97955C6 BC338D38 +RefMD5=13FAB67E603B002CEAF0EEA84130E973 + +[5FD0F1EE3F6E0C1E0BA9A91ED797A8B9] +GoodName=Legend of Zelda, The - Majora's Mask (E) (M4) (V1.0) [T-Ita0.9f_Vampire] +CRC=E97955C6 BC338D38 +RefMD5=13FAB67E603B002CEAF0EEA84130E973 + +[035239281994E1E254D7AFC79F5570FB] +GoodName=Legend of Zelda, The - Majora's Mask (E) (M4) (V1.0) [f1] +CRC=E7428718 97751A86 +RefMD5=13FAB67E603B002CEAF0EEA84130E973 + +[BECCFDED43A2F159D03555027462A950] +GoodName=Legend of Zelda, The - Majora's Mask (E) (M4) (V1.1) [!] +CRC=0A5D8F83 98C5371A +SaveType=Flash RAM +Status=4 +Rumble=Yes +Players=1 + +[71FBAE5D2B27926EA54E92CE2FC91622] +GoodName=Legend of Zelda, The - Majora's Mask (E) (M4) (V1.1) (Debug Version) +CRC=9FC385E5 3ECC05C7 +RefMD5=BECCFDED43A2F159D03555027462A950 + +[609B47B79DA21F3DF9B31D06C95C09A1] +GoodName=Legend of Zelda, The - Majora's Mask (E) (M4) (VC) [!] +CRC=0A5D8F83 98C5371A +SaveType=Flash RAM +Status=4 +Rumble=Yes +Players=1 + +[6DC88503DF78FE4FAA16BCF7AEC4D1E7] +GoodName=Legend of Zelda, The - Majora's Mask (E) (M4) (V1.1) [T+Ita1.0Beta_Vampire] +CRC=0A5D8F83 98C5371A +RefMD5=BECCFDED43A2F159D03555027462A950 + +[2A0A8ACB61538235BC1094D297FB6556] +GoodName=Legend of Zelda, The - Majora's Mask (U) [!] +CRC=5354631C 03A2DEF0 +SaveType=Flash RAM +Status=4 +Rumble=Yes +Players=1 + +[9C7D1B51ECBC9AC333D00273F96758B1] +GoodName=Legend of Zelda, The - Majora's Mask (U) [T+Pol1.0] +CRC=5354631C 03A2DEF0 +RefMD5=2A0A8ACB61538235BC1094D297FB6556 + +[B90B728E0643ABC582793B451444733E] +GoodName=Legend of Zelda, The - Majora's Mask (U) [T+Rus0.85_Alex] +CRC=5354631C 03A2DEF0 +RefMD5=2A0A8ACB61538235BC1094D297FB6556 + +[04150A63D1574673BEAB036E4EB5A249] +GoodName=Legend of Zelda, The - Majora's Mask (U) [T+RusPreAlpha_Alex&gottax] +CRC=5354631C 03A2DEF0 +RefMD5=2A0A8ACB61538235BC1094D297FB6556 + +[5D5DD380115ABF43958A710C7B597771] +GoodName=Legend of Zelda, The - Majora's Mask (U) [T-Rus0.1_Alex] +CRC=5354631C 03A2DEF0 +RefMD5=2A0A8ACB61538235BC1094D297FB6556 + +[7863ED3EE54F72BD59CF970C5C402FA2] +GoodName=Legend of Zelda, The - Majora's Mask (U) [T-Rus0.2_Alex] +CRC=5354631C 03A2DEF0 +RefMD5=2A0A8ACB61538235BC1094D297FB6556 + +[E684C672C2BF64717A10F1D104108998] +GoodName=Legend of Zelda, The - Majora's Mask (U) [T-Rus0.36Alex] +CRC=5354631C 03A2DEF0 +RefMD5=2A0A8ACB61538235BC1094D297FB6556 + +[BD26BC90750D6388972C7E29441039DF] +GoodName=Legend of Zelda, The - Majora's Mask (U) [T-Rus0.50_Alex] +CRC=5354631C 03A2DEF0 +RefMD5=2A0A8ACB61538235BC1094D297FB6556 + +[3DF7F2AF3E7B1F2FD55C2C02125F0130] +GoodName=Legend of Zelda, The - Majora's Mask (U) [f1] +CRC=696F2896 764F6D3F +RefMD5=2A0A8ACB61538235BC1094D297FB6556 + +[8F281800FBA5DDCB1D2B377731FC0215] +GoodName=Legend of Zelda, The - Majora's Mask - Preview Demo (U) [!] +CRC=BF799345 39FF7A02 + +[AC0751DBC23AB2EC0C3144203ACA0003] +GoodName=Legend of Zelda, The - Majora's Mask (U) (GC) +CRC=B443EB08 4DB31193 +SaveType=Flash RAM +Status=4 +Rumble=Yes +Players=1 + +[DBE9AF0DB46256E42B5C67902B696549] +GoodName=Legend of Zelda, The - Majora's Mask - Collector's Edition (E) (M4) (GC) [!] +CRC=6AECEC4F F0924814 +SaveType=Flash RAM +Status=4 +Rumble=Yes +Players=1 + +[9F04C8E68534B870F707C247FA4B50FC] +GoodName=Zelda no Densetsu - Toki no Ocarina (J) (V1.0) [!] +CRC=EC7011B7 7616D72B +SaveType=SRAM +Status=4 +Rumble=Yes +Players=1 + +[A04EBD753276C52E95E25AF7683DA32D] +GoodName=Zelda no Densetsu - Toki no Ocarina (J) (V1.0) [T+Chi.02_madcell] +CRC=EC7011B7 7616D72B +RefMD5=9F04C8E68534B870F707C247FA4B50FC + +[D48CFE3FBF77D5335731509BFDE10D47] +GoodName=Zelda no Densetsu - Toki no Ocarina (J) (V1.0) [T+Chi] +CRC=EC7011B7 7616D72B +RefMD5=9F04C8E68534B870F707C247FA4B50FC + +[BF0622C4C479E8FF5983DB3786F84293] +GoodName=Zelda no Densetsu - Toki no Ocarina (J) (V1.0) [f1] +CRC=9FD0987D 7EAE10D8 +RefMD5=9F04C8E68534B870F707C247FA4B50FC + +[1BF5F42B98C3E97948F01155F12E2D88] +GoodName=Zelda no Densetsu - Toki no Ocarina (J) (V1.1) [!] +CRC=D43DA81F 021E1E19 +SaveType=SRAM +Status=4 +Rumble=Yes +Players=1 + +[2258052847BDD056C8406A9EF6427F13] +GoodName=Zelda no Densetsu - Toki no Ocarina (J) (V1.2) [!] +CRC=693BA2AE B7F14E9F +RefMD5=1BF5F42B98C3E97948F01155F12E2D88 + +[E040DE91A74B61E3201DB0E2323F768A] +GoodName=Legend of Zelda, The - Ocarina of Time (E) (M3) (V1.0) [!] +CRC=B044B569 373C1985 +Status=4 +Players=1 +SaveType=SRAM +Rumble=Yes + +[2B60EF777F759B4F0E19DDF3CB84D9AB] +GoodName=Legend of Zelda, The - Ocarina of Time (E) (M3) (V1.0) [b1] +CRC=B044B569 373C1985 +RefMD5=E040DE91A74B61E3201DB0E2323F768A + +[20C68EAFDFCB1BA98B495E5BEED5E4B6] +GoodName=Legend of Zelda, The - Ocarina of Time (E) (M3) (V1.0) [f1] (zpfc) +CRC=EEE48FAF 6A92BAFF +RefMD5=E040DE91A74B61E3201DB0E2323F768A + +[175EDAB7F1A3DFBB5D23C4AA1B9D647E] +GoodName=Legend of Zelda, The - Ocarina of Time (E) (M3) (V1.0) [f2] (zpc1) +CRC=96961E83 B5DE0894 +RefMD5=E040DE91A74B61E3201DB0E2323F768A + +[D714580DD74C2C033F5E1B6DC0AEAC77] +GoodName=Legend of Zelda, The - Ocarina of Time (E) (M3) (V1.1) [!] +CRC=B2055FBD 0BAB4E0C +Status=4 +Players=1 +SaveType=SRAM +Rumble=Yes + +[5BD1FE107BF8106B2AB6650ABECD54D6] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [!] +CRC=EC7011B7 7616D72B +Status=4 +SaveType=SRAM +Players=1 +Rumble=Yes + +[A43A350385FA814EC9793B7ACD9E18F4] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) (Room121 Hack) +CRC=EBE8AA17 B1EF65E6 + +[640B928AD387B271094F64B9B93ABBFC] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T+Dut] +CRC=C7C3086D 93826E6E +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[6B3DB6AAA348F5721AFAF892E9B274DE] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T+Ita100] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[48CA89956120E0522D4B6B7E2810D04C] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T+Pol1.3] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[77BF20D3ECA19EBCFC5FED35F5CF65DC] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T+Por1.0] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[7FD3BA9B095C244367E84A6E4493349B] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T+Por1.5BetaFinal] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[7037DF7E0050A6D8B9B338C774A1CEB0] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T+Rus1.0beta2_Sergey Anton] +CRC=F8B1C7C7 1EFCA431 +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[B0BB6CAB395C93C966F1CA485FC1BFBC] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T+Rus101b2] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[10A2E08708E25195E063D2E05231AB66] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T+Spa01b_toruzz] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[BBCCE848679F3D0722CBA622505FB206] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T+Spa097b2] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[51778E50CE70466796F8D51C686224C4] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T+Spa1.0] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[44E6921A257E913977088B9B6BA9D25B] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T+Spa2.0_eduardo_a2j] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[AAEB5ACA09291E8F5FEDFA1F576D9F0A] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T-Pol1.2] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[1746D1CC38C42F08F0CD12D170C046B8] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T-Por.09] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[0D6331C2FA062F20272CC1A7F80F7271] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T-Por.14] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[FF7C6D9909D36D3A11D4C9052EAFB2E8] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T-Por.22] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[D4718E7EA75847646025D07626A1DF69] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T-Por.26] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[E784353B07DAFCB66690193B03CC3E1F] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T-Por.28] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[E6A5B9A18BB8D0508FBB703EB90703B7] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T-Por.30] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[79BE4EEEB2DD94E542516DFC189B099E] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T-Por.33] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[65AC7755CB41E937A1DC5C58902A4222] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T-Por.35] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[7B3AD8B6FE2D8F0602ED1006FD673970] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T-Por.37] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[F85FC5CE4451C1E9F3EE00B814489A51] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T-Por.42] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[92AED3D84A1AA0082B128E2CFD84C4AA] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T-Rus.01] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[5DF98AE5EAC2797555587D3391222FE4] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T-Rus.06] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[A1F18DE7D5570A502C7C93B7BF27E868] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T-Rus.82] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[A5A8A0249E14A052227B3ED71A98F0B4] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T-Rus099bfix] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[3FE076D5992C53DE6E095E53E53D9BC5] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T-Rus099wip] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[40F4A3A5FE703527E03C5747BC0A2FD6] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [T-Spa1.0_eduardo] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[EE38A903556C24520CD162FD046748A2] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [b1] +CRC=EC7011B7 7616D72B +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[8C1348872D9AC31FF9D22C07D7186CCB] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [f1] +CRC=9FD0987D 7EAE10D8 +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[DB2D737DE0F117D419B3A48442B6DB22] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [f2] +CRC=9FD0987D 7EAE10D8 +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[4472B1F6B9D594B6361DFA396F8CFB2C] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.0) [f3] +CRC=9FD0987D 7EAE10D8 +RefMD5=5BD1FE107BF8106B2AB6650ABECD54D6 + +[721FDCC6F5F34BE55C43A807F2A16AF4] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.1) [!] +CRC=D43DA81F 021E1E19 +Status=4 +SaveType=SRAM +Players=1 +Rumble=Yes + +[92C842FC8CF706FF290044D40A64D346] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.1) [T+Ita100] +CRC=D43DA81F 021E1E19 +RefMD5=721FDCC6F5F34BE55C43A807F2A16AF4 + +[F5B33DC7DC76BB308801CB518B1515F3] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.1) [T+Por1.0] +CRC=D43DA81F 021E1E19 +RefMD5=721FDCC6F5F34BE55C43A807F2A16AF4 + +[C949E4929A001B339DAE000A3DA9E0A8] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.1) [T+Por100%] +CRC=D43DA81F 021E1E19 +RefMD5=721FDCC6F5F34BE55C43A807F2A16AF4 + +[53E09E6B72F114440B389FA8549E8F97] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.1) [T+Spa01b_toruzz] +CRC=D43DA81F 021E1E19 +RefMD5=721FDCC6F5F34BE55C43A807F2A16AF4 + +[EA4FA94072849F88CAC96E60C1EDD41D] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.1) [T-Spa1.0_eduardo] +CRC=D43DA81F 021E1E19 +RefMD5=721FDCC6F5F34BE55C43A807F2A16AF4 + +[B3E1D1B92626BA86E5BDF0F18409A25B] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.1) [T-Spa1.0_eduardo][b1] +CRC=D43DA81F 021E1E19 +RefMD5=721FDCC6F5F34BE55C43A807F2A16AF4 + +[468F7EAA4B94B831AEED8B83C062B5CB] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.1) [b1] +CRC=D43DA81F 021E1E19 +RefMD5=721FDCC6F5F34BE55C43A807F2A16AF4 + +[DD824A8E1A6778FA5229433109AFAEFF] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.1) [b2] +CRC=CF8EC901 7EC2C48D +RefMD5=721FDCC6F5F34BE55C43A807F2A16AF4 + +[57A9719AD547C516342E1A15D5C28C3D] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (V1.2) [!] +CRC=693BA2AE B7F14E9F +Players=1 +SaveType=SRAM +Rumble=Yes + +[CD09029EDCFB7C097AC01986A0F83D3F] +GoodName=Legend of Zelda, The - Ocarina of Time (U) (GC) [!] +CRC=F3DD35BA 4152E075 +Status=4 +Players=1 +SaveType=SRAM +Rumble=Yes +; End Credits Fix +Cheat0=D109A814 0320,8109A814 0000,D109A816 F809,8109A816 0000 + +[2C27B4E000E85FD78DBCA551F1B1C965] +GoodName=Legend of Zelda, The - Ocarina of Time (E) (GC) [!] +CRC=09465AC3 F8CB501B +Status=4 +Players=1 +SaveType=SRAM +Rumble=Yes +; End Credits Fix +Cheat0=D109A8E4 0320,8109A8E4 0000,D109A8E6 F809,8109A8E6 0000 + +[77314FE3C3EDD472D0554C12FEDB38F4] +GoodName=Legend of Zelda, The - Ocarina of Time (E) (GC) [f1] +CRC=A3271D83 05B533A5 +RefMD5=2C27B4E000E85FD78DBCA551F1B1C965 + +[1618403427E4344A57833043DB5CE3C3] +GoodName=Legend of Zelda, The - Ocarina of Time - Master Quest (E) (GC) [!] +CRC=1D4136F3 AF63EEA9 +Status=4 +Players=1 +SaveType=SRAM +Rumble=Yes +; End Credits Fix +Cheat0=D109A8C4 0320,8109A8C4 0000,D109A8C6 F809,8109A8C6 0000 + +[BC2ECBE96B04EDC56B08347DF7C7FECD] +GoodName=Legend of Zelda, The - Ocarina of Time - Master Quest (E) (GC) [T+Ita70%_Rulesless] +CRC=1D4136F3 AF63EEA9 +RefMD5=1618403427E4344A57833043DB5CE3C3 + +[83673D0A0EF4705C624043788EBF11EE] +GoodName=Legend of Zelda, The - Ocarina of Time - Master Quest (E) (GC) [T+Pol1.0] +CRC=1D4136F3 AF63EEA9 +RefMD5=1618403427E4344A57833043DB5CE3C3 + +[A34093AC2B038A92CCF525CAB4CE346E] +GoodName=Legend of Zelda, The - Ocarina of Time - Master Quest (E) (GC) [f1] (NTSC) +CRC=27A3831D B505A533 +RefMD5=1618403427E4344A57833043DB5CE3C3 + +[2DE4D0F0788871CC4BB6D30B60F72184] +GoodName=Legend of Zelda, The - Ocarina of Time - Master Quest (E) (GC) [h1C] +CRC=1D4136F3 AF63EEA9 +RefMD5=1618403427E4344A57833043DB5CE3C3 + +[DA35577FE54579F6A266931CC75F512D] +GoodName=Legend of Zelda, The - Ocarina of Time - Master Quest (U) (GC) [!] +CRC=F034001A AE47ED06 +Status=4 +Players=1 +SaveType=SRAM +Rumble=Yes +; End Credits Fix +Cheat0=D109A7F4 0320,8109A7F4 0000,D109A7F6 F809,8109A7F6 0000 + +[26A1616667EEC82288534C47B6927D45] +GoodName=Legend of Zelda, The - Ocarina of Time - Master Quest (U) (Debug Version) [f1] +CRC=917D1B16 831F9BE1 +RefMD5=DA35577FE54579F6A266931CC75F512D + +[8AD8D24EA38B68DFAB154C2585FB550C] +GoodName=Legend of Zelda, The - Ocarina of Time - Master Quest (U) (Debug Version) [f2] +CRC=917D18F6 69BC5453 +RefMD5=DA35577FE54579F6A266931CC75F512D + +[8CA71E87DE4CE5E9F6EC916202A623E9] +GoodName=Legend of Zelda, The - Ocarina of Time - Master Quest (U) (Debug Version) +CRC=917D18F6 69BC5453 +RefMD5=DA35577FE54579F6A266931CC75F512D + +[0AB48B2D44A74B3BB2D384F6170C2742] +GoodName=Legend of Zelda, The - Ocarina of Time (Ch) (iQue) [!] +CRC=B1E1E07B 051269DD +Players=1 + +[9729A68F40F197D4D040FA641FF099E7] +GoodName=Legend of Zelda, The - Ocarina of Time (Ch) (V2) (iQue) (Manual) [!] + +[912628118E67FEA670ED2C63F7A7B003] +GoodName=Legend of Zelda, The - Ocarina of Time (Ch) (V4) (iQue) (Manual) [!] + +[A475E9F8615513666A265C464708AE8F] +GoodName=Legend of Zelda, The - Ocarina of Time (Ch) (Traditional) (iQue) [!] +CRC=3D81FB3E BD843E34 +Players=1 + +[55685D6324EFDE5BC9D26C98706B0B8A] +GoodName=Les Razmoket - La Chasse Aux Tresors (F) [!] +CRC=2B696CB4 7B93DCD8 +Players=4 +Rumble=Yes + +[AEE5016E6D60D12AD768E9F6D10ADDE8] +GoodName=Let's Smash Tennis (J) [!] +CRC=3D67C62B 31D03150 +Players=4 +Mempak=Yes + +[EF878DFACF5CD5C00BA3297B0DC888D2] +GoodName=Light Force First N64 Demo by Fractal (PD) +CRC=7D292963 D5277C1F + +[9656C4A5251F054704E35134006CFFC7] +GoodName=Liner V1.00 by Colin Phillipps of Memir (PD) +CRC=8A8E474B 6458BF2B +Status=1 +SaveType=None +Players=4 + +[AF701EE852ECD13F5F9F3284EBE60561] +GoodName=Liner V1.00 by Colin Phillipps of Memir (PD) [b1] +CRC=8A8E474B 6458BF2B +RefMD5=9656C4A5251F054704E35134006CFFC7 + +[500AFE6D6732E0888D108410D135B78E] +GoodName=Liner V1.00 by Colin Phillipps of Memir (PD) [b2] +CRC=8A8E474B 6458BF2B +RefMD5=9656C4A5251F054704E35134006CFFC7 + +[99380A8ED84C89E54DE53E0B1FB423C9] +GoodName=Liner V1.02 by Colin Phillipps of Memir (PD) +CRC=F7B1C8E8 70536D3E +Status=1 +SaveType=None +Players=4 + +[E62F4FDCC82C244BA9709E40756D9B62] +GoodName=Lode Runner 3-D (E) (M5) [!] +CRC=60460680 305F0E72 +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes +Status=3 + +[6B1E294A9199E6F22DBC6ABC59BD7568] +GoodName=Lode Runner 3-D (E) (M5) [b1] +CRC=E378B28A 0CA18BCC +RefMD5=E62F4FDCC82C244BA9709E40756D9B62 + +[D2BD8DD8C3BE1E8F0B8AE49206DBD7E5] +GoodName=Lode Runner 3-D (J) [!] +CRC=964ADD0B B29213DB +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes +Status=3 + +[D038813541589F0B3F1F900F4FD22C9B] +GoodName=Lode Runner 3-D (U) [!] +CRC=255018DF 57D6AE3A +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes +Status=3 + +[5FBA92D908B9962F26D389C85F6E88CF] +GoodName=Lode Runner 3-D (U) [b1][f1] (PAL) +CRC=275A4533 ACD94796 +RefMD5=D038813541589F0B3F1F900F4FD22C9B + +[3F5CA81183EA0E69F35417F6BBD7C5AC] +GoodName=Lode Runner 3-D (U) [f1] (PAL) +CRC=275A4533 ACD94796 +RefMD5=D038813541589F0B3F1F900F4FD22C9B + +[789482B7931419FCE7FC2472026E1C65] +GoodName=Lode Runner 3-D (U) [t1] +CRC=BD13F636 02079573 +RefMD5=D038813541589F0B3F1F900F4FD22C9B + +[1408FCF68B60D845F090107EF355A7E5] +GoodName=Looney Tunes - Duck Dodgers (E) (M6) [!] +CRC=0AA0055B 7637DF65 +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[4CCFF861AD2CFD65CC660F496C1D1664] +GoodName=Lt. Duck Dodgers (Prototype) +CRC=FBB9F1FA 6BF88689 +Players=1 +Rumble=Yes +CountPerOp=1 + +[7A99628EDF0A6602D0C408F31B701435] +GoodName=Lylat Wars (A) (M3) [!] +CRC=2483F22B 136E025E +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes + +[B182BBBC8CE22BD3F44BB6ED91F6ACD4] +GoodName=Lylat Wars (A) (M3) [f1] +CRC=2483F22B 136E025E +RefMD5=7A99628EDF0A6602D0C408F31B701435 + +[1E03884F7017230E96F741085E5817F8] +GoodName=Lylat Wars (A) (M3) [t1] (Boost) +CRC=AF13E2C2 2D502822 +RefMD5=7A99628EDF0A6602D0C408F31B701435 + +[A2957C46E62CEC7B10EDE4547F70425F] +GoodName=Lylat Wars (A) (M3) [t2] (No Damage-Unbreakable Wings) +CRC=8B31F4AD F366CBFA +RefMD5=7A99628EDF0A6602D0C408F31B701435 + +[884CCCA35CBEEDB8ED288326F9662100] +GoodName=Lylat Wars (E) (M3) [!] +CRC=F4CBE92C B392ED12 +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes + +[F0FF28B0D26CDEFC11F22FE73148A6DC] +GoodName=Lylat Wars (E) (M3) [f1] +CRC=F4CBE92C B392ED12 +RefMD5=884CCCA35CBEEDB8ED288326F9662100 + +[37F7F2F2CFB488E48A2706FC8C4B2DD5] +GoodName=Lylat Wars (E) (M3) [f1][h1C] +CRC=F4CBE92C B392ED12 +RefMD5=884CCCA35CBEEDB8ED288326F9662100 + +[499013DA36AD50C94B2CE6B794CC9983] +GoodName=Lylat Wars (E) (M3) [f2] (NTSC) +CRC=F667DC04 86510A81 +RefMD5=884CCCA35CBEEDB8ED288326F9662100 + +[12F0671C66D25622C4C9CD71C678A1F6] +GoodName=Lylat Wars (E) (M3) [t1] (Boost) +CRC=834C19FF 8A93F7D4 +RefMD5=884CCCA35CBEEDB8ED288326F9662100 + +[281E754123EC0CC688C4AA7C853DE303] +GoodName=Lylat Wars (E) (M3) [t2] (No Damage-Unbreakable Wings) +CRC=58B5EA62 27177133 +RefMD5=884CCCA35CBEEDB8ED288326F9662100 + +[41FE06C68915666E5F8FEF81B8FFF59F] +GoodName=MAME 64 Beta 3 (PD) +CRC=D5CA46C2 F8555155 + +[3803F70982907C7C24713A7F9742B6CD] +GoodName=MAME 64 Demo (PD) [b1] +CRC=9CCE5B1D 6351E283 + +[0E2516C65B94214C891B2D07C3D92AEC] +GoodName=MAME 64 Demo (PD) [b2] +CRC=9CCE5B1D 6351E283 + +[42AC30399688F98E58BE6AD1D2217E56] +GoodName=MAME 64 Demo (PD) +CRC=9CCE5B1D 6351E283 + +[C9319D97DABE9E842401433A27E00DAC] +GoodName=MAME 64 V1.0 (PD) [b1] +CRC=9CCE5B1D 6351E283 + +[6591A5FCFFF8879382C966906C3186E0] +GoodName=MAME 64 V1.0 (PD) +CRC=9CCE5B1D 6351E283 + +[D63FAF99E7876C39A9ACA2659596342F] +GoodName=MMR by Count0 (PD) [b1] +CRC=9E6581AB 57CC8CED + +[65B71F404DC3CF9A135D3229FFEA3C15] +GoodName=MMR by Count0 (PD) +CRC=9E6581AB 57CC8CED + +[9C6CF9D3CB5852439DE4EF4A399253B9] +GoodName=Mini Racers (U) (Prototype) +CRC=21548CA9 9059F32C + +[0054B7FC0C2ACBED650EFE727CDBA472] +GoodName=MRC - Multi Racing Championship (E) (M3) [!] +CRC=B8F0BD03 4479189E +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[362D10C7D270AE48D83D1D7BB78BF527] +GoodName=MRC - Multi Racing Championship (E) (M3) [b1] +CRC=B8F0BD03 4479189E +RefMD5=0054B7FC0C2ACBED650EFE727CDBA472 + +[25E39A8B45FDDFA1989CE6662F87EF23] +GoodName=MRC - Multi Racing Championship (E) (M3) [b2] +CRC=B8F0BD03 4479189E +RefMD5=0054B7FC0C2ACBED650EFE727CDBA472 + +[F5723C4CCFB9A1CE28426962D59CC85F] +GoodName=MRC - Multi Racing Championship (E) (M3) [b3] +CRC=B8F0BD03 4479189E +RefMD5=0054B7FC0C2ACBED650EFE727CDBA472 + +[FEA06F46F61DEB721CF905C785299994] +GoodName=MRC - Multi Racing Championship (E) (M3) [h1C] +CRC=B8F0BD03 4479189E +RefMD5=0054B7FC0C2ACBED650EFE727CDBA472 + +[74904F302A25620D7F63C0CB5333D464] +GoodName=MRC - Multi Racing Championship (E) (M3) [o1] +CRC=B8F0BD03 4479189E +RefMD5=0054B7FC0C2ACBED650EFE727CDBA472 + +[8E18064A2C4B3EC15A20C3D676644B3A] +GoodName=MRC - Multi Racing Championship (J) [!] +CRC=A6B6B413 15D113CC +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[C306C80A07743F75B0C69AF2B484E957] +GoodName=MRC - Multi Racing Championship (J) [b1] +CRC=A6B6B413 15D113CC +RefMD5=8E18064A2C4B3EC15A20C3D676644B3A + +[CBA2CCCD3C3772B96CDA7128090C1FD7] +GoodName=MRC - Multi Racing Championship (J) [b2] +CRC=A6B6B413 15D113CC +RefMD5=8E18064A2C4B3EC15A20C3D676644B3A + +[8F33FE36837198B3F21CC1F37FC67CC8] +GoodName=MRC - Multi Racing Championship (J) [b3] +CRC=A6B6B413 15D113CC +RefMD5=8E18064A2C4B3EC15A20C3D676644B3A + +[6073174A8DA1305CF91B59369FAEFDDF] +GoodName=MRC - Multi Racing Championship (J) [b4] +CRC=A6B6B413 15D113CC +RefMD5=8E18064A2C4B3EC15A20C3D676644B3A + +[BB82ADC51562F8CDDCDF4F6FAD2479BA] +GoodName=MRC - Multi Racing Championship (J) [b5] +CRC=A6B6B413 15D113CC +RefMD5=8E18064A2C4B3EC15A20C3D676644B3A + +[FC61D60F2C6FE4610F70CE4949A7A062] +GoodName=MRC - Multi Racing Championship (U) [!] +CRC=2AF9B65C 85E2A2D7 +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[E38F1DAE2A2023A529B47A26E4666759] +GoodName=MRC - Multi Racing Championship (U) [b1] +CRC=2AF9B65C 85E2A2D7 +RefMD5=FC61D60F2C6FE4610F70CE4949A7A062 + +[535995506105D0EABA796E371660CBF2] +GoodName=MRC - Multi Racing Championship (U) [b2] +CRC=2AF9B65C 85E2A2D7 +RefMD5=FC61D60F2C6FE4610F70CE4949A7A062 + +[7E8F028411746CF816848384B788B624] +GoodName=MRC - Multi Racing Championship (U) [b3] +CRC=2AF9B65C 85E2A2D7 +RefMD5=FC61D60F2C6FE4610F70CE4949A7A062 + +[677356691E55A9061772585CDDFD7F76] +GoodName=MRC - Multi Racing Championship (U) [o1] +CRC=2AF9B65C 85E2A2D7 +RefMD5=FC61D60F2C6FE4610F70CE4949A7A062 + +[72F324B7E115618771C506AF3F604F8F] +GoodName=MSFTUG Intro #1 by LaC (PD) +CRC=94D3D5CB E8808606 + +[523883A766C662E8377CD256755B27B4] +GoodName=Mace - The Dark Age (E) [!] +CRC=1145443D 11610EDB +Players=2 +SaveType=None + +[9CF16783687686C8FE2ABE0B71316C3D] +GoodName=Mace - The Dark Age (E) [b1] +CRC=1145443D 11610EDB +RefMD5=523883A766C662E8377CD256755B27B4 + +[2249D931B5D2D4544EEB75E5B4136709] +GoodName=Mace - The Dark Age (E) [b2] +CRC=1145443D 11610EDB +RefMD5=523883A766C662E8377CD256755B27B4 + +[87BD533084ACB4DC6C3E01B32F26357C] +GoodName=Mace - The Dark Age (E) [o1] +CRC=1145443D 11610EDB +RefMD5=523883A766C662E8377CD256755B27B4 + +[8E2B951678785DB1F54A31F778BFA491] +GoodName=Mace - The Dark Age (E) [o2] +CRC=1145443D 11610EDB +RefMD5=523883A766C662E8377CD256755B27B4 + +[39A2BCA1C17CD4CF1A9F3AE2B725B5C6] +GoodName=Mace - The Dark Age (U) [!] +CRC=6B700750 29D621FE +Players=2 +SaveType=None + +[DF342B032ED1ED15C24448EC6BE9F34E] +GoodName=Mace - The Dark Age (U) [b1] +CRC=6B700750 29D621FE +RefMD5=39A2BCA1C17CD4CF1A9F3AE2B725B5C6 + +[57CB2D2F6C87F520016AACF7E2785222] +GoodName=Mace - The Dark Age (U) [b2] +CRC=6B700750 29D621FE +RefMD5=39A2BCA1C17CD4CF1A9F3AE2B725B5C6 + +[D1CE0FA3D46CA27F1C15E782ACEC49DA] +GoodName=Mace - The Dark Age (U) [b3] +CRC=022E6456 75BBB3C7 +RefMD5=39A2BCA1C17CD4CF1A9F3AE2B725B5C6 + +[243F8C4067D50D994C1E883968DE8C61] +GoodName=Mace - The Dark Age (U) [b4] +CRC=022E6456 75BBB3C7 +RefMD5=39A2BCA1C17CD4CF1A9F3AE2B725B5C6 + +[88B638825A16E46837FB521EDA328C5A] +GoodName=Mace - The Dark Age (U) [b5] +CRC=6B700750 29D621FE +RefMD5=39A2BCA1C17CD4CF1A9F3AE2B725B5C6 + +[62A0CE9A58273811E34CC73BE8E6F8C4] +GoodName=Mace - The Dark Age (U) [b6] +CRC=6B700750 29D621FE +RefMD5=39A2BCA1C17CD4CF1A9F3AE2B725B5C6 + +[B96ABFBD746BC25243D607613297D769] +GoodName=Mace - The Dark Age (U) [b7] +CRC=6B700750 29D621FE +RefMD5=39A2BCA1C17CD4CF1A9F3AE2B725B5C6 + +[1D4BD885DB0C0C5365698526077E10F4] +GoodName=Mace - The Dark Age (U) [b8] +CRC=6B700750 29D621FE +RefMD5=39A2BCA1C17CD4CF1A9F3AE2B725B5C6 + +[1C897EC059C6C34C8ED57E1965410F2E] +GoodName=Mace - The Dark Age (U) [b9] +CRC=6B700750 29D621FE +RefMD5=39A2BCA1C17CD4CF1A9F3AE2B725B5C6 + +[64D508C5E0F1050048BE429E20EF4B07] +GoodName=Mace - The Dark Age (U) [o1] +CRC=6B700750 29D621FE +RefMD5=39A2BCA1C17CD4CF1A9F3AE2B725B5C6 + +[67C96076459EB5F71733F39D7FCC76A3] +GoodName=Madden Football 64 (E) [!] +CRC=A197CB52 7520DE0E +SaveType=None +Players=4 +Mempak=Yes +Rumble=Yes + +[5CBF54627693F800524038127BBF46BF] +GoodName=Madden Football 64 (E) [b1] +CRC=A197CB52 7520DE0E +RefMD5=67C96076459EB5F71733F39D7FCC76A3 + +[903B912CE88626900221731224E9DBE8] +GoodName=Madden Football 64 (U) [!] +CRC=13836389 265B3C76 +SaveType=None +Players=4 +Mempak=Yes +Rumble=Yes + +[5CA2A7F712B6C5737D0B46E67C8DDA44] +GoodName=Madden Football 64 (U) [b1] +CRC=13836389 265B3C76 +RefMD5=903B912CE88626900221731224E9DBE8 + +[9AE941A12974B7B56CFA8B5EA1E670D7] +GoodName=Madden Football 64 (U) [b2] +CRC=13836389 265B3C76 +RefMD5=903B912CE88626900221731224E9DBE8 + +[CA7161F298DF38BC8182B21BB754DB4B] +GoodName=Madden Football 64 (U) [h1C] +CRC=13836389 265B3C76 +RefMD5=903B912CE88626900221731224E9DBE8 + +[732167D19C627CAF7384C780C64AB80A] +GoodName=Madden Football 64 (U) [o1] +CRC=13836389 265B3C76 +RefMD5=903B912CE88626900221731224E9DBE8 + +[E979BF2E2B43CCB5E2E0A2798AD7770C] +GoodName=Madden Football 64 (U) [o1][h1C] +CRC=13836389 265B3C76 +RefMD5=903B912CE88626900221731224E9DBE8 + +[0966CB688D6A5F1B22B4FAB5A393C0E2] +GoodName=Madden Football 64 (U) [o2] +CRC=13836389 265B3C76 +RefMD5=903B912CE88626900221731224E9DBE8 + +[DB24A5DBA68F21D4513A37F7A7B0CF60] +GoodName=Madden Football 64 (U) [o3] +CRC=13836389 265B3C76 +RefMD5=903B912CE88626900221731224E9DBE8 + +[955D19E26B4BA7CC941F86A54A0FC13D] +GoodName=Madden NFL 2000 (U) [!] +CRC=0CB81686 5FD85A81 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[441FA65FAA5C12339F89A0BB7DB43C8F] +GoodName=Madden NFL 2001 (U) [!] +CRC=EB38F792 190EA246 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[AD0F2EC565D7575FB37512BC8DF8A092] +GoodName=Madden NFL 2002 (U) [!] +CRC=D7134F8D C11A00B5 +SaveType=None +Mempak=Yes +Rumble=Yes +Players=4 +CountPerOp=1 + +[E7BF80861A0AB2A788959463D953B5D5] +GoodName=Madden NFL 99 (E) [!] +CRC=3925D625 8C83C75E +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[9CB5F5CD6AB141454D645C92FD9BF67C] +GoodName=Madden NFL 99 (E) [h1C] +CRC=3925D625 8C83C75E +RefMD5=E7BF80861A0AB2A788959463D953B5D5 + +[507CEAB72EF2A1BF145BF190F5CE1C80] +GoodName=Madden NFL 99 (U) [!] +CRC=DEB78BBA 52F6BD9D +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[C049FCD4CB185A553D8122CFE6C30139] +GoodName=Madden NFL 99 (U) [o1] +CRC=DEB78BBA 52F6BD9D +RefMD5=507CEAB72EF2A1BF145BF190F5CE1C80 + +[5AD80A8EF44DEE1FDC456D66104165B4] +GoodName=Madden NFL 99 (U) (V1.1) [!] +CRC=DF09D625 1791C87D +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[5F3D42D5F96191F3CE50D70E0E42127A] +GoodName=Madden NFL 99 (Beta) (1998-08-05) [!] +CRC=76F8FB3 509A2054 +RefMD5=507CEAB72EF2A1BF145BF190F5CE1C80 + +[20E51B27E8098A9D101B44689014C281] +GoodName=Magical Tetris Challenge (E) [!] +CRC=E4906679 9F243F05 +Players=2 +SaveType=None +Rumble=Yes + +[20D02EECFA887DC5A31948B18B4BB18D] +GoodName=Magical Tetris Challenge (E) [b1] +CRC=E4906679 9F243F05 +RefMD5=20E51B27E8098A9D101B44689014C281 + +[5BDE53960AD95F4C25C76C0F70C35244] +GoodName=Magical Tetris Challenge (E) [f1] (NTSC) +CRC=70BF6C4C 6F365E21 +RefMD5=20E51B27E8098A9D101B44689014C281 + +[E0992A90191BE4F1B2BA02258599334E] +GoodName=Magical Tetris Challenge (G) [!] +CRC=E1EF93F7 14908B0B +Players=2 +SaveType=None +Rumble=Yes + +[79FCC98002D1F4C79DEAF55784222DF8] +GoodName=Magical Tetris Challenge (U) [!] +CRC=75B61647 7ADABF78 +Players=2 +SaveType=None +Rumble=Yes + +[BD5BB4CE1FACE911F9D8C777E2594998] +GoodName=Magical Tetris Challenge (U) [b1][hI] +CRC=CDCCFF87 1D76A49E +RefMD5=79FCC98002D1F4C79DEAF55784222DF8 + +[36BEDFD15CB70478916BAA469491D80D] +GoodName=Magical Tetris Challenge (U) [hI] +CRC=CDCCFF87 1D76A49E +RefMD5=79FCC98002D1F4C79DEAF55784222DF8 + +[F1FF1F364C459701F42BEB8989675D44] +GoodName=Magical Tetris Challenge Featuring Mickey (J) [!] +CRC=80C8564A 929C65AB +Players=2 +SaveType=None +Rumble=Yes + +[9F6DB67262220C62536CEBE0AF3C8E73] +GoodName=Magical Tetris Challenge Featuring Mickey (J) [b1] +CRC=E6FCB468 CFAC7528 +RefMD5=F1FF1F364C459701F42BEB8989675D44 + +[8AE2E8F0C356FEE638C8D908DCBB3381] +GoodName=Mahjong 64 (J) [!] +CRC=C53EDC41 ECE19359 +Players=1 +Mempak=Yes + +[E67651E58A4B864765A752E3BEB5F4E4] +GoodName=Mahjong 64 (J) [o1] +CRC=C53EDC41 ECE19359 +RefMD5=8AE2E8F0C356FEE638C8D908DCBB3381 + +[F931E1DF9524BACEF6B731D50D7DC10F] +GoodName=Mahjong 64 (J) [o2] +CRC=C53EDC41 ECE19359 +RefMD5=8AE2E8F0C356FEE638C8D908DCBB3381 + +[E942A3EEB1EB572BADD6F705EB12A22C] +GoodName=Mahjong Hourouki Classic (J) [!] +CRC=CCCC821E 96E88A83 +Players=1 + +[50A8B47E5F8FE5BF955AFA70FE3893AC] +GoodName=Mahjong Hourouki Classic (J) [b1] +CRC=CCCC821E 96E88A83 +RefMD5=E942A3EEB1EB572BADD6F705EB12A22C + +[D2CB04B88E565170D820E3CF78B54863] +GoodName=Mahjong Hourouki Classic (J) [b2] +CRC=CCCC821E 96E88A83 +RefMD5=E942A3EEB1EB572BADD6F705EB12A22C + +[D1855B19BA0D65C103FE9318F14F5D7D] +GoodName=Mahjong Hourouki Classic (J) [b3] +CRC=CCCC821E 96E88A83 +RefMD5=E942A3EEB1EB572BADD6F705EB12A22C + +[CF0D228E8EFDF823A227979BB352DD5B] +GoodName=Mahjong Master (J) [!] +CRC=0FC42C70 8754F1CD +Players=1 +Mempak=Yes + +[AD1AD9FE15C4565FF88B9B48AF6F300C] +GoodName=Mahjong Master (J) [b1] +CRC=0FC42C70 8754F1CD +RefMD5=CF0D228E8EFDF823A227979BB352DD5B + +[E0D1170D521B49E3A5EDACA3A6F579AB] +GoodName=Mahjong Master (J) [b2] +CRC=0FC42C70 8754F1CD +RefMD5=CF0D228E8EFDF823A227979BB352DD5B + +[3BD16F3DDB0DD890412BFE1E59CA5463] +GoodName=Mahjong Master (J) [o1] +CRC=0FC42C70 8754F1CD +RefMD5=CF0D228E8EFDF823A227979BB352DD5B + +[152B9939A5F50734D5401980028856B4] +GoodName=Major League Baseball Featuring Ken Griffey Jr. (E) [!] +CRC=CDB998BE 1024A5C8 +Players=2 +SaveType=SRAM +Mempak=Yes +Rumble=Yes + +[62CD83FC8FC8E8CF8899320BF25474CE] +GoodName=Major League Baseball Featuring Ken Griffey Jr. (E) [b1] +CRC=59F34558 0C3130E4 +RefMD5=152B9939A5F50734D5401980028856B4 + +[D5696CB5A4F2185BD8469DF018B7856B] +GoodName=Major League Baseball Featuring Ken Griffey Jr. (E) [f1] +CRC=59F34558 0C3130E4 +RefMD5=152B9939A5F50734D5401980028856B4 + +[764F22AD3D0F59667A7F083D2F789B31] +GoodName=Major League Baseball Featuring Ken Griffey Jr. (U) [!] +CRC=80C1C05C EA065EF4 +Players=2 +SaveType=SRAM +Mempak=Yes +Rumble=Yes + +[97FE61E8719CF0A4747301E97C759CBF] +GoodName=Major League Baseball Featuring Ken Griffey Jr. (U) [b1] +CRC=B1CF1114 5E59B81D +RefMD5=764F22AD3D0F59667A7F083D2F789B31 + +[E1BD016961EDEB895F12676AD4B77FB5] +GoodName=Major League Baseball Featuring Ken Griffey Jr. (U) [b2] +CRC=0BFC12D9 1B377DA7 +RefMD5=764F22AD3D0F59667A7F083D2F789B31 + +[16F2644156AC9DD15CA8CC01DEAE5E7E] +GoodName=Major League Baseball Featuring Ken Griffey Jr. (U) [b3] +CRC=80C1C05C EA065EF4 +RefMD5=764F22AD3D0F59667A7F083D2F789B31 + +[257057553D60C1DD1B7FDC5814CB21D9] +GoodName=Major League Baseball Featuring Ken Griffey Jr. (U) [f1] +CRC=B1CF1114 5E59B81D +RefMD5=764F22AD3D0F59667A7F083D2F789B31 + +[30B2E1F7F3AFDC5D8E6A42C8885AAD93] +GoodName=Mandelbrot Zoomer by RedBox (PD) +CRC=30E6FE79 3EEA5386 +Status=3 +Players=0 +SaveType=None + +[4E054610A872E1313228637C815E514C] +GoodName=Manic Miner - Hidden Levels by RedboX (PD) +CRC=A47D4AD4 F5B0C6CB +Players=1 +SaveType=None +Status=1 +Rumble=No + +[B18BC60EA6B9C72048FD84A2B8F182D4] +GoodName=Manic Miner by RedboX (PD) +CRC=A47D4AD4 8BFA81F9 +Players=1 +SaveType=None +Status=1 +Rumble=No + +[59F0839CAE935F8B06BAEC434CB29318] +GoodName=Mario Artist: Communication Kit (J) [CART HACK] +CRC=AB9EB27D 5F05605F + +[6A2B060606CFC20E0EE0A26759FE001B] +GoodName=Mario Artist: Polygon Studio (J) [CART HACK] +CRC=2D5EFCC5 98CF79D2 + +[9C1E3D607B1CC5FB90AD62D3F02A50ED] +GoodName=Mario Artist: Paint Studio (J) [CART HACK] +CRC=3A3EB7FB 0DDD515C +Players=4 +Transferpak=Yes + +[E811554E6C6A61BE750A1ED315909840] +GoodName=Mario Artist: Paint Studio (J) [CART HACK] [T+Eng0.2_LuigiBlood] +CRC=DD16F47C A8B748C7 +Players=4 +Transferpak=Yes + +[ED1CBFC5D3756A1520CD2D57F6998BDF] +GoodName=Mario Artist: Talent Studio (J) [CART HACK] +CRC=4CBC3B56 FDB69B1C +Players=1 +Transferpak=Yes + +[336AE63BD1EBACC64D9D92370B555537] +GoodName=Mario Artist: Talent Studio (J) [CART HACK] [T+Eng0.1_LuigiBlood] +CRC=73C0403D E821D951 +Players=1 +Transferpak=Yes + +[55634FF90EE997790781F79A5B0097EE] +GoodName=Mario Golf (E) [!] +CRC=62E957D0 7FC15A5D +Players=4 +SaveType=SRAM +Rumble=Yes +Transferpak=Yes + +[4D010AE1AF4B04D6B70B799C56F05993] +GoodName=Mario Golf (E) [b1] +CRC=62E957D0 7FC15A5D +RefMD5=55634FF90EE997790781F79A5B0097EE + +[CF6BD6E20B40635B0E6DED5BB5114875] +GoodName=Mario Golf (E) [f1] (Z64-Save) +CRC=1D82BE21 7EF19C9A +RefMD5=55634FF90EE997790781F79A5B0097EE + +[02C8E8FD7EB19BFEB325E2DB0380506A] +GoodName=Mario Golf (E) [f2] (Z64-Save) +CRC=1D82BE21 7EF19C9A +RefMD5=55634FF90EE997790781F79A5B0097EE + +[18E09C0650FA3F83A90089DADD96A213] +GoodName=Mario Golf (E) [h1C] +CRC=62E957D0 7FC15A5D +RefMD5=55634FF90EE997790781F79A5B0097EE + +[78BB5B9A279156BD61BE132817A9B2C8] +GoodName=Mario Golf (E) [o1][h1C] +CRC=62E957D0 7FC15A5D +RefMD5=55634FF90EE997790781F79A5B0097EE + +[903E6929666531D72D05D1E4C522E305] +GoodName=Mario Golf (U) [!] +CRC=664BA3D4 678A80B7 +Players=4 +SaveType=SRAM +Rumble=Yes +Transferpak=Yes + +[D31466B4B14B03387FE52FBBBCD25A5C] +GoodName=Mario Golf (U) [b1] +CRC=E8761702 26AD5DBE +RefMD5=903E6929666531D72D05D1E4C522E305 + +[11FED930D4C4DD0CA7CB03B5F1BF0A12] +GoodName=Mario Golf (U) [b1][f1] (PAL) +CRC=84CDFB72 9CA8D544 +RefMD5=903E6929666531D72D05D1E4C522E305 + +[374FD81C3E8E858EEB2226501659B333] +GoodName=Mario Golf (U) [b2] +CRC=84CDFB72 9CA8D544 +RefMD5=903E6929666531D72D05D1E4C522E305 + +[7A5D0D77A462B5A7C372FB19EFDE1A5F] +GoodName=Mario Golf (U) [b3] +CRC=664BA3D4 678A80B7 +RefMD5=903E6929666531D72D05D1E4C522E305 + +[BE28EF71E1EE0092EEC4AA395ACFEEFF] +GoodName=Mario Golf (U) [f1] (PAL) +CRC=84CDFB72 9CA8D544 +RefMD5=903E6929666531D72D05D1E4C522E305 + +[2FACDF2F3E52EE8A603DE79348E441E6] +GoodName=Mario Golf (U) [f2] (Z64-Save) +CRC=A19FA3D0 E06B2D11 +RefMD5=903E6929666531D72D05D1E4C522E305 + +[12569B4FA5239A3AD53DE5D2E0243488] +GoodName=Mario Golf (U) [t1] +CRC=26647A17 8D3980C3 +RefMD5=903E6929666531D72D05D1E4C522E305 + +[CD87BA2998D63C13B4366EB2C54E1EB6] +GoodName=Mario Golf 64 (J) (V1.0) [!] +CRC=D48944D1 B0D93A0E +Players=4 +SaveType=SRAM +Rumble=Yes +Transferpak=Yes + +[B5A98CED4B9A10682988CCB219A5C9A7] +GoodName=Mario Golf 64 (J) (V1.0) [b1] +CRC=D48944D1 B0D93A0E +RefMD5=CD87BA2998D63C13B4366EB2C54E1EB6 + +[334D4E8443A67E964649B28428C8F1AE] +GoodName=Mario Golf 64 (J) (V1.0) [b1][f1] (PAL) +CRC=B771E0A9 7B4A96E6 +RefMD5=CD87BA2998D63C13B4366EB2C54E1EB6 + +[6D84657C9A145E67B2A8A61CD31A7218] +GoodName=Mario Golf 64 (J) (V1.0) [b2] +CRC=D48944D1 B0D93A0E +RefMD5=CD87BA2998D63C13B4366EB2C54E1EB6 + +[E5A041B1B7C8E3B4C2E8178E5A138E2D] +GoodName=Mario Golf 64 (J) (V1.0) [b3] +CRC=D48944D1 B0D93A0E +RefMD5=CD87BA2998D63C13B4366EB2C54E1EB6 + +[C14090CD5CF313A471B5CD3D55EC0B53] +GoodName=Mario Golf 64 (J) (V1.0) [f1] (PAL) +CRC=B771E0A9 7B4A96E6 +RefMD5=CD87BA2998D63C13B4366EB2C54E1EB6 + +[570B4F55A3005B709E6ED5D625981B90] +GoodName=Mario Golf 64 (J) (V1.1) [!] +CRC=734F816B C6A6EB67 +Players=4 +SaveType=SRAM +Rumble=Yes +Transferpak=Yes + +[78771BEB349D481E69BAA9225B36D63A] +GoodName=Mario Kart 64 (Ch) (V4) (iQue) [!] + +[5EA0ED74CF1DDAAA964D728A129E7CF9] +GoodName=Mario Kart 64 (Ch) (V5) (iQue) [!] + +[C70AF6197E67B310F316C34CCED64C19] +GoodName=Mario Kart 64 (Ch) (V2) (iQue) (Manual) [!] + +[76176B237D4F60E59F98D247283D9365] +GoodName=Mario Kart 64 (Ch) (V6) (iQue) (Manual) [!] + +[8FAD1E4FA7BAF1443B7F21AD1947B429] +GoodName=Mario Kart 64 (E) (V1.0) [!] +CRC=C3B6DE9D 65D2DE76 +Status=3 +SaveType=Eeprom 4KB +Players=4 +Mempak=Yes +; Multiplayer Timing Fix +Cheat0=81001A1C 2409,81001A1E 0002,81001C74 240A,81001C76 0002 + +[EC0FAE8002AC6356E0470CE21BFEFA4F] +GoodName=Mario Kart 64 (E) (V1.0) (Super W00ting Hack) +CRC=E470469D E105C984 +RefMD5=8FAD1E4FA7BAF1443B7F21AD1947B429 + +[B97FC8B1D00B9D673C229CA7FAE453D4] +GoodName=Mario Kart 64 (E) (V1.0) [T+Ita_Cattivik66] +CRC=C3B6DE9D 65D2DE76 +RefMD5=8FAD1E4FA7BAF1443B7F21AD1947B429 + +[E292551471766D7F51907F2BC65079AA] +GoodName=Mario Kart 64 (E) (V1.0) [b1] +CRC=C3B6DE9D 65D2DE76 +RefMD5=8FAD1E4FA7BAF1443B7F21AD1947B429 + +[8E632F2AFF9AEF3F5C1AE2FEBD482D9D] +GoodName=Mario Kart 64 (E) (V1.0) [b2] +CRC=C3B6DE9D 65D2DE76 +RefMD5=8FAD1E4FA7BAF1443B7F21AD1947B429 + +[2BB149A583FDEFEA96805F628FE42FD9] +GoodName=Mario Kart 64 (E) (V1.1) [!] +CRC=2577C7D4 D18FAAAE +Status=3 +SaveType=Eeprom 4KB +Players=4 +Mempak=Yes +; Multiplayer Timing Fix +Cheat0=81001A1C 2409,81001A1E 0002,81001C74 240A,81001C76 0002 + +[2A64632C71FFB90DF3AE83836DEDD7A6] +GoodName=Mario Kart 64 (E) (V1.1) [T+Ita_Cattivik66][b1] +CRC=2577C7D4 D18FAAAE +RefMD5=2BB149A583FDEFEA96805F628FE42FD9 + +[A30CFA60CCCE25F1324D4AD98C26AF5D] +GoodName=Mario Kart 64 (E) (V1.1) [o1] +CRC=2577C7D4 D18FAAAE +RefMD5=2BB149A583FDEFEA96805F628FE42FD9 + +[BF964CECA78A13A82055EBDA80B95CCA] +GoodName=Mario Kart 64 (J) (V1.0) [!] +CRC=6BFF4758 E5FF5D5E +Status=3 +SaveType=Eeprom 4KB +Players=4 +Mempak=Yes +; Multiplayer Timing Fix +Cheat0=81001A1C 2409,81001A1E 0002,81001C74 240A,81001C76 0002 + +[8FD3C06ED13CD27BB3D664C92A455AA8] +GoodName=Mario Kart 64 (J) (V1.0) [T+Ita_Cattivik66][b1] +CRC=6BFF4758 E5FF5D5E +RefMD5=BF964CECA78A13A82055EBDA80B95CCA + +[37AA3A354FBE508F5449E0C515083128] +GoodName=Mario Kart 64 (J) (V1.0) [b1] +CRC=6BFF4758 E5FF5D5E +RefMD5=BF964CECA78A13A82055EBDA80B95CCA + +[80B4F92970CBB13344F57E827C60959B] +GoodName=Mario Kart 64 (J) (V1.0) [b2] +CRC=6BFF4758 E5FF5D5E +RefMD5=BF964CECA78A13A82055EBDA80B95CCA + +[36295982651A9974EB7342B1DD5245E1] +GoodName=Mario Kart 64 (J) (V1.0) [o1] +CRC=6BFF4758 E5FF5D5E +RefMD5=BF964CECA78A13A82055EBDA80B95CCA + +[60535265BAE43DDFCBDB0D71594B1693] +GoodName=Mario Kart 64 (J) (V1.1) [!] +CRC=C9C3A987 5810344C +Status=3 +SaveType=Eeprom 4KB +Players=4 +Mempak=Yes +; Multiplayer Timing Fix +Cheat0=81001A1C 2409,81001A1E 0002,81001C74 240A,81001C76 0002 + +[231F0134D2899C08930F6E34682D2C0B] +GoodName=Mario Kart 64 (J) (V1.1) [b1] +CRC=C9C3A987 5810344C +RefMD5=60535265BAE43DDFCBDB0D71594B1693 + +[84F11CACB9608E2E595FA5FBB8C91CE9] +GoodName=Mario Kart 64 (J) (V1.1) [b1][T+Ita_Cattivik66] +CRC=C9C3A987 5810344C +RefMD5=60535265BAE43DDFCBDB0D71594B1693 + +[B5D68FF8E5A982400556C530409263DB] +GoodName=Mario Kart 64 (J) (V1.1) [b1][f1] (PAL) +CRC=B6F68615 F4E26039 +RefMD5=60535265BAE43DDFCBDB0D71594B1693 + +[3A67D9986F54EB282924FCA4CD5F6DFF] +GoodName=Mario Kart 64 (U) [!] +CRC=3E5055B6 2E92DA52 +Status=3 +SaveType=Eeprom 4KB +Players=4 +Mempak=Yes +; Multiplayer Timing Fix +Cheat0=81001A38 2409,81001A3A 0002,81001A3C 2409,81001A3E 0002,81001C90 240A,81001C92 0002,81001C94 240A,81001C96 0002 + +[B63346465FE70DA3B1E7493CE5A15A31] +GoodName=Mario Kart 64 (U) (Super W00ting Hack) +CRC=4D9C55B6 85E58D87 +RefMD5=3A67D9986F54EB282924FCA4CD5F6DFF + +[D1958141566ECC4942C71D1E97171639] +GoodName=Mario Kart 64 (U) [T+Ita0.01_Cattivik66] +CRC=3E5055B6 2E92DA52 +RefMD5=3A67D9986F54EB282924FCA4CD5F6DFF + +[65CBD8DCEC6B7CE61E1CB233EFA4A317] +GoodName=Mario Kart 64 (U) [T+Por1.0_Dr_X] +CRC=3E5055B6 2E92DA52 +RefMD5=3A67D9986F54EB282924FCA4CD5F6DFF + +[4A5E85A3E7118A742E3678F8F7E82B0E] +GoodName=Mario Kart 64 (U) [b1] +CRC=3E5055B6 2E92DA52 +RefMD5=3A67D9986F54EB282924FCA4CD5F6DFF + +[ABDB8D8C53E1F938853EC80742C8AF77] +GoodName=Mario Kart 64 (U) [b2] +CRC=3E5055B6 2E92DA52 +RefMD5=3A67D9986F54EB282924FCA4CD5F6DFF + +[FE75ABB3934F88429E138019146E8393] +GoodName=Mario Kart 64 (U) [b3] +CRC=3E5055B6 2E92DA52 +RefMD5=3A67D9986F54EB282924FCA4CD5F6DFF + +[C3565B1C983B83C6C965BB88E24135B2] +GoodName=Mario Kart 64 (U) [b4] +CRC=3E5055B6 2E92DA52 +RefMD5=3A67D9986F54EB282924FCA4CD5F6DFF + +[7D54D888964A3B0D058EB80886C44C88] +GoodName=Mario Kart 64 (U) [h1C] +CRC=3E5055B6 2E92DA52 +RefMD5=3A67D9986F54EB282924FCA4CD5F6DFF + +[7C5E794E856311403FEF548DAE98A183] +GoodName=Mario Kart 64 (U) [o1] +CRC=3E5055B6 2E92DA52 +RefMD5=3A67D9986F54EB282924FCA4CD5F6DFF + +[6C634D0CE7CD99CCCBB4CE8EB837EDB4] +GoodName=Mario Kart 64 (U) [o2] +CRC=3E5055B6 2E92DA52 +RefMD5=3A67D9986F54EB282924FCA4CD5F6DFF + +[3AA8C8C023F6AB8384CBDD412DECF977] +GoodName=Mario Kart 64 (U) [t1] +CRC=465035CA C6DE1A09 +RefMD5=3A67D9986F54EB282924FCA4CD5F6DFF + +[22E183BD8AF57A79DEB6679CA919B61E] +GoodName=Mario Kart 64 (U) [t2] (Course Cheat) +CRC=085055B6 5346ED7B +RefMD5=3A67D9986F54EB282924FCA4CD5F6DFF + +[9F85F64C6DD30CA67EB355EF0332F102] +GoodName=Mario Kart 64 (U) [t3] (Star Cheat) +CRC=0B623F24 F8D4F434 +RefMD5=3A67D9986F54EB282924FCA4CD5F6DFF + +[0B2B6CC62CFEEB7C4642A3643A3ED3C8] +GoodName=Mario Kart 64 (U) [t4] +CRC=465035CA C6DE1A09 +RefMD5=3A67D9986F54EB282924FCA4CD5F6DFF + +[9773150709BD804B8E57E35F1D6B0EED] +GoodName=Mario Party (E) (M3) [!] +CRC=9C663069 80F24A80 +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes +CountPerOp=1 + +[2608A4D7A695D0B1A1BBC47695EACE0E] +GoodName=Mario Party (E) (M3) [b1] +CRC=9C663069 80F24A80 +RefMD5=9773150709BD804B8E57E35F1D6B0EED + +[37EB3D60A2E85BE5077F73A5DF651F05] +GoodName=Mario Party (E) (M3) [h1C] +CRC=9C663069 80F24A80 +RefMD5=9773150709BD804B8E57E35F1D6B0EED + +[3F556CC3B3A996CD2F471FA0D992D529] +GoodName=Mario Party (J) [!] +CRC=ADA815BE 6028622F +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes +CountPerOp=1 + +[8BC2712139FBF0C56C8EA835802C52DC] +GoodName=Mario Party (U) [!] +CRC=2829657E A0621877 +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes +CountPerOp=1 + +[D072DDBCC5961AE85E6FA9BF50241370] +GoodName=Mario Party (U) [f1] (PAL) +CRC=5B904BAE 4CA06CC9 +RefMD5=8BC2712139FBF0C56C8EA835802C52DC + +[F70112B652B0EE4856AF83F4E8005C31] +GoodName=Mario Party 2 (E) (M5) [!] +CRC=82380387 DFC744D9 +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes +CountPerOp=1 + +[F23E4CD437465F3E725262253CF3EA59] +GoodName=Mario Party 2 (J) [!] +CRC=ED567D0F 38B08915 +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes +CountPerOp=1 + +[04840612A35ECE222AFDB2DFBF926409] +GoodName=Mario Party 2 (U) [!] +CRC=9EA95858 AF72B618 +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes +CountPerOp=1 + +[F253C5A0FB69AB56A1548D435AF84D0F] +GoodName=Mario Party 2 (U) [f1] (PAL) +CRC=C6C71B88 6422C633 +RefMD5=04840612A35ECE222AFDB2DFBF926409 + +[CD75CCD32EB435713EA54DFF313FA50C] +GoodName=Mario Party 2 (U) [f2] (PAL) +CRC=C63B1ADA 9CEAEB08 +RefMD5=04840612A35ECE222AFDB2DFBF926409 + +[8E62EC6FBE3CC9FF6284191C9C88E68F] +GoodName=Mario Party 3 (E) (M4) [!] +CRC=C5674160 0F5F453C +SaveType=Eeprom 16KB +Players=4 +Rumble=Yes +CountPerOp=1 + +[ED99F330CE7A2638AB13351012EEB86B] +GoodName=Mario Party 3 (J) [!] +CRC=0B0AB4CD 7B158937 +SaveType=Eeprom 16KB +Players=4 +Rumble=Yes +CountPerOp=1 + +[76A8BBC81BC2060EC99C9645867237CC] +GoodName=Mario Party 3 (U) [!] +CRC=7C3829D9 6E8247CE +SaveType=Eeprom 16KB +Players=4 +Rumble=Yes +CountPerOp=1 + +[BDD79F498F37D01B8958F56EC6FFA097] +GoodName=Mario Party 3 (U) [f1] +CRC=65DB63E3 64357A65 +RefMD5=76A8BBC81BC2060EC99C9645867237CC + +[F8F9116279FBAFD511748542994598B2] +GoodName=Mario Party 3 (U) [f2] (PAL) +CRC=822E0915 0338FD50 +RefMD5=76A8BBC81BC2060EC99C9645867237CC + +[5C3D2699C01EBD30D42C6F52491EA7F0] +GoodName=Mario Party 3 (U) [f3] +CRC=DF0C666A 1F52B368 +RefMD5=76A8BBC81BC2060EC99C9645867237CC + +[DF54F17FB84FB5B5BCF6AA9AF65B0942] +GoodName=Mario Story (J) [!] +CRC=3BA7CDDC 464E52A0 +Status=2 +Players=1 +SaveType=Flash RAM +Rumble=Yes +CountPerOp=1 + +[FFF9B3E22ABB9B60215DAFB13AD5A4DE] +GoodName=Mario Tennis (E) [!] +CRC=839F3AD5 406D15FA +SaveType=Eeprom 16KB +Players=4 +Rumble=Yes +Transferpak=Yes + +[759358FAD1ED5AE31DCB2001A07F2FE5] +GoodName=Mario Tennis (U) [!] +CRC=5001CF4F F30CB3BD +SaveType=Eeprom 16KB +Players=4 +Rumble=Yes +Transferpak=Yes + +[7FB25633FDB226F35A222B4EA17BD2DC] +GoodName=Mario Tennis (U) [f1] (Save) +CRC=BC47A8BF 5529DE0F +RefMD5=759358FAD1ED5AE31DCB2001A07F2FE5 + +[8EB1C2443D0B2E6EDA52A4EEA66D6C35] +GoodName=Mario Tennis 64 (J) [!] +CRC=3A6C42B5 1ACADA1B +SaveType=Eeprom 16KB +Players=4 +Rumble=Yes +Transferpak=Yes + +[DD4A580E27D82BCCA6A229BA17C69368] +GoodName=Mario Tennis 64 (J) [f1] (Country Check) +CRC=3A3FA519 9595CD82 +RefMD5=8EB1C2443D0B2E6EDA52A4EEA66D6C35 + +[7F4ED2AAF94A2197B0AD63C6ECE9DEA9] +GoodName=Mario no Photopie (J) [!] +CRC=9A9890AC F0C313DF +Players=1 + +[6BAB5F2A62A4BABAF456D5DA2976871D] +GoodName=Mario no Photopie (J) [a1] +CRC=9A9890AC F0C313DF +RefMD5=7F4ED2AAF94A2197B0AD63C6ECE9DEA9 + +[DD65E5F4B192A12966BBDD6718B694E6] +GoodName=MeeTING Demo by Renderman (PD) +CRC=A806749B 1F521F45 + +[2202B39B9017BB061822552AF83FD331] +GoodName=MeeTING Demo by Renderman (PD) [b1] +CRC=A806749B 1F521F45 +RefMD5=DD65E5F4B192A12966BBDD6718B694E6 + +[3620674ACB51E436D5150738AC1C0969] +GoodName=Mega Man 64 (U) [!] +CRC=0EC158F5 FB3E6896 +Players=1 +SaveType=Flash RAM +Rumble=Yes + +[CD0824E9405185AF434837BA1C8C0CD5] +GoodName=Mega Man 64 (U) (Beta) [!] +CRC=27C985A8 ED7CE5C6 + +[01A1304D98A58E2D5069079A4F4441F9] +GoodName=Mega Man 64 (U) [t1][f1] (PAL-NTSC) +CRC=B63200D4 E36CF5AA +RefMD5=3620674ACB51E436D5150738AC1C0969 + +[2F4C29DD26B6D5311F3D46063A393687] +GoodName=Memory Manager V1.0b by R. Bubba Magillicutty (PD) +CRC=4DEC9986 A8904450 + +[C77AC9BC65EEEA761FC8B081AF728CDB] +GoodName=Mempack Manager for Jr 0.9 by deas (PD) +CRC=81A3F478 B6965E3E + +[E1A9CBDB3C066E4BC0A4FB71ADA70CB2] +GoodName=Mempack Manager for Jr 0.9b by deas (PD) +CRC=1EC6C03C B0954ADA + +[9CF33B5F0D677C7BCE85CB877B0942CD] +GoodName=Mempack Manager for Jr 0.9c by deas (PD) +CRC=D2015E56 A9FE0CE6 + +[BAD7C9731029AD4880FF4B92E5569065] +GoodName=Mempack to N64 Uploader by Destop V1.0 (PD) +CRC=6A097D8B F999048C + +[A4039368E0472C68E3072C02C7A80F94] +GoodName=Mia Hamm Soccer 64 (U) (M2) [!] +CRC=1001F10C 3D51D8C1 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[892222CC4BAF9958405D20BC492175BF] +GoodName=Michael Owens WLS 2000 (E) [!] +CRC=E36166C2 8613A2E5 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[6A814E33BB6D449BE23FBBCAC7606C0B] +GoodName=Michael Owens WLS 2000 (E) [b1] +CRC=E36166C2 8613A2E5 +RefMD5=892222CC4BAF9958405D20BC492175BF + +[EC700909D09C081DA0E4BAE454C657F0] +GoodName=Michael Owens WLS 2000 (E) [b2] +CRC=9ABC592A 2AA5DEE2 +RefMD5=892222CC4BAF9958405D20BC492175BF + +[BD5D214BED53C4682E9FF8B8E9919CD4] +GoodName=Michael Owens WLS 2000 (E) [f1] (NTSC) +CRC=9ABC592A 2AA5DEE2 +RefMD5=892222CC4BAF9958405D20BC492175BF + +[288A514E98972BF9D329167AA29E66B6] +GoodName=Mickey no Racing Challenge USA (J) [!] +CRC=736AE6AF 4117E9C7 +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes + +[5BA3DC37860C08A209F24286B8DFEC8C] +GoodName=Mickey's Speedway USA (E) (M5) [!] +CRC=DED0DD9A E78225A7 +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes +Transferpak=Yes + +[0BF64427CF68E49C70E9EC2C9D815209] +GoodName=Mickey's Speedway USA (U) [!] +CRC=FA8C4571 BBE7F9C0 +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes +Transferpak=Yes + +[B025F0E20FB41A0AAE280847329CB919] +GoodName=Mickey's Speedway USA (U) [t1] +CRC=38112EC7 E91410C3 +RefMD5=0BF64427CF68E49C70E9EC2C9D815209 + +[9A8465E302263D635557A14AA197FE3C] +GoodName=Micro Machines 64 Turbo (E) (M5) [!] +CRC=2A49018D D0034A02 +SaveType=None +Mempak=Yes +Rumble=Yes + +[68246CF0AB9DE7B6F84751FCC86A959A] +GoodName=Micro Machines 64 Turbo (E) (M5) [b1] +CRC=2A49018D D0034A02 +RefMD5=9A8465E302263D635557A14AA197FE3C + +[7D61BB9D25BAF9A608139592DC4E28DC] +GoodName=Micro Machines 64 Turbo (E) (M5) [b1][f1] (NTSC) +CRC=700F6DD9 E2EB805F +RefMD5=9A8465E302263D635557A14AA197FE3C + +[E48559E990DE24458F8A3ACDF3AEE901] +GoodName=Micro Machines 64 Turbo (E) (M5) [t1] +CRC=ADCDEC69 D0179F38 +RefMD5=9A8465E302263D635557A14AA197FE3C + +[74EB415E16C333B252847A8E09432FD9] +GoodName=Micro Machines 64 Turbo (U) [!] +CRC=F1850C35 ACE07912 +SaveType=None +Mempak=Yes +Rumble=Yes + +[BB9F2E48015D9DFB347B4BE4C2DFB334] +GoodName=Micro Machines 64 Turbo (U) [a1][!] +CRC=F1850C35 ACE07912 +RefMD5=74EB415E16C333B252847A8E09432FD9 + +[656B1442015CF95D4D1E01713309F71D] +GoodName=Micro Machines 64 Turbo (U) [b1] +CRC=F1850C35 ACE07912 +RefMD5=74EB415E16C333B252847A8E09432FD9 + +[C44D99D0437142211DACA4826F8ECB88] +GoodName=Micro Machines 64 Turbo (U) [t1] +CRC=A986ECC1 50AC924B +RefMD5=74EB415E16C333B252847A8E09432FD9 + +[2B86775EA4D848202E4F4A39C33571CA] +GoodName=Midway's Greatest Arcade Hits Volume 1 (U) [!] +CRC=E4B35E4C 1AC45CC9 +SaveType=None +Mempak=Yes +Players=2 + +[47EA6F037B093381CA88A41FBB6C4199] +GoodName=Midway's Greatest Arcade Hits Volume 1 (U) [b1] +CRC=E4B35E4C 1AC45CC9 +RefMD5=2B86775EA4D848202E4F4A39C33571CA + +[1FE59964EC1A5899F3C7D97590F676EB] +GoodName=Midway's Greatest Arcade Hits Volume 1 (U) [b2] +CRC=3F462D42 93AE9238 +RefMD5=2B86775EA4D848202E4F4A39C33571CA + +[B07FF4F972B269F2BDC69713B4B701A7] +GoodName=Midway's Greatest Arcade Hits Volume 1 (U) [o1] +CRC=E4B35E4C 1AC45CC9 +RefMD5=2B86775EA4D848202E4F4A39C33571CA + +[24467B76A192DFB67069C5A87B8606D0] +GoodName=Midway's Greatest Arcade Hits Volume 1 (U) [o1][t1] +CRC=3F462D42 93AE9238 +RefMD5=2B86775EA4D848202E4F4A39C33571CA + +[D30A4723E266D57D86BDC52F932D0DF1] +GoodName=Midway's Greatest Arcade Hits Volume 1 (U) [t1] +CRC=3F462D42 93AE9238 +RefMD5=2B86775EA4D848202E4F4A39C33571CA + +[EB357505EFC9D17A08ADBA5590896C4D] +GoodName=Midway's Greatest Arcade Hits Volume 1 (U) [t2] +CRC=3F462D42 93AE9238 +RefMD5=2B86775EA4D848202E4F4A39C33571CA + +[9D401FA1A1DDDF5C8995278E09E2210D] +GoodName=Midway's Greatest Arcade Hits Volume 1 (U) [t2][b1] +CRC=3F462D42 93AE9238 +RefMD5=2B86775EA4D848202E4F4A39C33571CA + +[EB1908E51C8D10AF8B9CAF77797BFE00] +GoodName=Mike Piazza's Strike Zone (U) [!] +CRC=09D53E16 3AB268B9 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[F5978A54BB22E3BC4D46C0C3E9597B12] +GoodName=Mike Piazza's Strike Zone (U) [h1C] +CRC=09D53E16 3AB268B9 +RefMD5=EB1908E51C8D10AF8B9CAF77797BFE00 + +[1B41A885CBAA693714575383DB4C05BE] +GoodName=Mike Piazza's Strike Zone (U) [h2C] +CRC=09D53E16 3AB268B9 +RefMD5=EB1908E51C8D10AF8B9CAF77797BFE00 + +[83C51E3CD82A0D86CACE6D852990814F] +GoodName=Mike Piazza's Strike Zone (U) [h3C] +CRC=09D53E16 3AB268B9 +RefMD5=EB1908E51C8D10AF8B9CAF77797BFE00 + +[43B02AF2789990A14F77CE020E6F135C] +GoodName=Milo's Astro Lanes (E) [!] +CRC=9A490D9D 8F013ADC +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[988B490C2AEBF7DE3C274B7EAEEF0999] +GoodName=Milo's Astro Lanes (E) [o1] +CRC=9A490D9D 8F013ADC +RefMD5=43B02AF2789990A14F77CE020E6F135C + +[F152C4A90B33D0D2BFAF782F56B202DF] +GoodName=Milo's Astro Lanes (E) [o2] +CRC=9A490D9D 8F013ADC +RefMD5=43B02AF2789990A14F77CE020E6F135C + +[4F256146BAC4A3DDE5AD0D5F9C909251] +GoodName=Milo's Astro Lanes (U) [!] +CRC=2E955ECD F3000884 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[AC004667AB4578BAA9A1C0A7771E8B17] +GoodName=Milo's Astro Lanes (U) [b1] +CRC=2E955ECD F3000884 +RefMD5=4F256146BAC4A3DDE5AD0D5F9C909251 + +[BE83566E7C7B9249FAC73DD2F1121424] +GoodName=Milo's Astro Lanes (U) [h1C] +CRC=2E955ECD F3000884 +RefMD5=4F256146BAC4A3DDE5AD0D5F9C909251 + +[0FE31A113EF389F8F95460D340C7D922] +GoodName=Milo's Astro Lanes (U) [h2C] +CRC=2E955ECD F3000884 +RefMD5=4F256146BAC4A3DDE5AD0D5F9C909251 + +[3D5F017D75679CEFCE2127CACC46C9F2] +GoodName=Milo's Astro Lanes (U) [o1] +CRC=2E955ECD F3000884 +RefMD5=4F256146BAC4A3DDE5AD0D5F9C909251 + +[FD85E6B20A9099F670C3CFBD13AEE719] +GoodName=Milo's Astro Lanes (U) [o1][b1] +CRC=2E955ECD F3000884 +RefMD5=4F256146BAC4A3DDE5AD0D5F9C909251 + +[C0513AE9494462433CDC83870320DA4E] +GoodName=Mind Present Demo 0 by Widget and Immortal (POM '98) (PD) [b1] +CRC=C811CBB1 8FB7617C + +[589DD744C7B07EC4DA91568CFBAC09EF] +GoodName=Mind Present Demo 0 by Widget and Immortal (POM '98) (PD) +CRC=C811CBB1 8FB7617C + +[4D1243D71F5536A416F3664A02FDF8E2] +GoodName=Mind Present Demo Readme by Widget and Immortal (POM '98) (PD) +CRC=139A06BC 416B0055 + +[EB3B078A74D4DC827E1E79791004DFBB] +GoodName=Mischief Makers (E) [!] +CRC=418BDA98 248A0F58 +Players=1 +SaveType=Eeprom 4KB +CountPerOp=1 + +[5690D74157C6623E2928A6F0353EF4AF] +GoodName=Mischief Makers (E) [b1] +CRC=418BDA98 248A0F58 +RefMD5=EB3B078A74D4DC827E1E79791004DFBB + +[495A9BFFD6620BE43225DB7133373FC5] +GoodName=Mischief Makers (U) (V1.0) [!] +CRC=0B93051B 603D81F9 +Players=1 +SaveType=Eeprom 4KB +CountPerOp=1 + +[CCF012DF82022D4797CE4CC5405E084F] +GoodName=Mischief Makers (U) (V1.0) [b1] +CRC=0B93051B 603D81F9 +RefMD5=495A9BFFD6620BE43225DB7133373FC5 + +[B3A172FE81F7BB47519D8E19E5F08154] +GoodName=Mischief Makers (U) (V1.0) [o1] +CRC=0B93051B 603D81F9 +RefMD5=495A9BFFD6620BE43225DB7133373FC5 + +[2EE917366F64A06472D7622A2A05990E] +GoodName=Mischief Makers (U) (V1.1) [!] +CRC=BFA526B4 0691E430 +Players=1 +SaveType=Eeprom 4KB +CountPerOp=1 + +[599B5D40B51F53C2C9A909E0139702FC] +GoodName=Mission Impossible (E) [!] +CRC=2256ECDA 71AB1B9C +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[5CDC052C88A5CADCC3C73B165163E8C7] +GoodName=Mission Impossible (E) [b1] +CRC=2256ECDA 71AB1B9C +RefMD5=599B5D40B51F53C2C9A909E0139702FC + +[FD0C0E8C523437F9B6B630E369FDFC69] +GoodName=Mission Impossible (F) [!] +CRC=20095B34 343D9E87 +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[FF9CC9E03993DD15F1436AF3874F94CF] +GoodName=Mission Impossible (F) [b1] +CRC=20095B34 343D9E87 +RefMD5=FD0C0E8C523437F9B6B630E369FDFC69 + +[D2442969E039254CF1B9B059DBB6311C] +GoodName=Mission Impossible (F) [b2] +CRC=20095B34 343D9E87 +RefMD5=FD0C0E8C523437F9B6B630E369FDFC69 + +[4111482C92EE806484AAA2C210893A52] +GoodName=Mission Impossible (G) [!] +CRC=93EB3F7E 81675E44 +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[66C7EB8148E0714B5A71F5717DFF8642] +GoodName=Mission Impossible (I) [!] +CRC=EBA949DC 39BAECBD +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[CA60967822CCCEFE22299691B453D893] +GoodName=Mission Impossible (I) [f1] (NTSC) +CRC=C76B18F6 AAB1BDF3 +RefMD5=66C7EB8148E0714B5A71F5717DFF8642 + +[D1BA3B1899576A4B67908ABB6544D75A] +GoodName=Mission Impossible (S) [!] +CRC=5F6A04E2 D4FA070D +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[217B0E4723DBACDA40B70B26E610F5F9] +GoodName=Mission Impossible (S) [f1] (NTSC) +CRC=635CB5C6 E9192BFF +RefMD5=D1BA3B1899576A4B67908ABB6544D75A + +[16A3143DC0E5FE6639F49DB7A51D24D4] +GoodName=Mission Impossible (S) (V1.1) [!] +CRC=5F6DDEA2 4DD9E759 +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[EEBDFBD7CB57202D70CFFFCAAF55E93E] +GoodName=Mission Impossible (U) [!] +CRC=26035CF8 802B9135 +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[550F4C177942FC0DF00B646C42EB4A90] +GoodName=Mission Impossible (U) [b1] +CRC=26035CF8 802B9135 +RefMD5=EEBDFBD7CB57202D70CFFFCAAF55E93E + +[0D97158C3408F8E3E6D38A17223AC881] +GoodName=Mission Impossible (U) [b2] +CRC=09D4D757 F2775DBD +RefMD5=EEBDFBD7CB57202D70CFFFCAAF55E93E + +[FA31743C3FC0236D6CEC0BD514DFB053] +GoodName=Mission Impossible (U) [f1] (PAL) +CRC=09D4D757 F2775DBD +RefMD5=EEBDFBD7CB57202D70CFFFCAAF55E93E + +[5320608C729C9F5B32581F81604D75E6] +GoodName=Mission Impossible (U) [t1] +CRC=B0105C85 6E5094B9 +RefMD5=EEBDFBD7CB57202D70CFFFCAAF55E93E + +[4FF9589A3224AAA46E9877D6B25E68E3] +GoodName=Monaco Grand Prix (U) [!] +CRC=28768D6D B379976C +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[9BF4D7FBE8157C9D6866A90269DCA7CB] +GoodName=Monaco Grand Prix (U) [f1] (PAL) +CRC=DA233397 FF46DF64 +RefMD5=4FF9589A3224AAA46E9877D6B25E68E3 + +[C93A17D130B96FBA27A0E959CAB2A450] +GoodName=Monaco Grand Prix - Racing Simulation 2 (E) (M4) [!] +CRC=28705FA5 B509690E +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[F81580C9C480DDF1B8F7E6A56D1B9CD5] +GoodName=Money Creates Taste Demo by Count0 (POM '99) (PD) [f1] +CRC=97E57686 F271C12F + +[A74DBAA3BF59DE13B6A191A6675C85D7] +GoodName=Money Creates Taste Demo by Count0 (POM '99) (PD) +CRC=282A4262 58B47E76 + +[D51506EDB0A941A00EB45850703B32CB] +GoodName=Monopoly (U) [!] +CRC=5AC383E1 D712E387 +Players=4 +SaveType=Eeprom 4KB +CountPerOp=1 + +[26C3654D20B8718A75B5FE8DA5B3284A] +GoodName=Monopoly (U) [f1] (PAL) +CRC=B9D36858 559A8241 +RefMD5=D51506EDB0A941A00EB45850703B32CB + +[E3B408997D7DB91F8219F168C6D57D26] +GoodName=Monster Truck Madness 64 (E) (M5) [!] +CRC=D3D806FC B43AA2A8 +Players=4 +SaveType=None +Rumble=Yes +CountPerOp=3 + +[12534DAB32DBFC6CA4F66D05729102E6] +GoodName=Monster Truck Madness 64 (E) (M5) [f1] (NTSC) +CRC=AE5E467C D7194A71 +RefMD5=E3B408997D7DB91F8219F168C6D57D26 + +[514D61D3B3D5E6326869783EB2E84A00] +GoodName=Monster Truck Madness 64 (U) [!] +CRC=B19AD999 7E585118 +Players=4 +SaveType=None +Rumble=Yes +CountPerOp=3 + +[3C9F329D5E0C7FE57355B8DC68F79331] +GoodName=Monster Truck Madness 64 (U) [t1] +CRC=29A9E7F6 1B90CFCE +RefMD5=514D61D3B3D5E6326869783EB2E84A00 + +[462B9C4F38758C2E558312AC60DF2B91] +GoodName=Morita Shougi 64 (J) [!] +CRC=E8E8DD70 415DD198 +Players=4 +Mempak=Yes + +[264B82F0FC2431D6EEFDE9C9F3ED7596] +GoodName=Mortal Kombat 4 (E) [!] +CRC=73036F3B CE0D69E9 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[58EFAF3D7D0985BC426245EFA5418CC2] +GoodName=Mortal Kombat 4 (E) [h1C] +CRC=73036F3B CE0D69E9 +RefMD5=264B82F0FC2431D6EEFDE9C9F3ED7596 + +[619B1F196B70260DCE89B21E66D10934] +GoodName=Mortal Kombat 4 (E) [t1] (Hit Anywhere) +CRC=72836ECB 75D15FAE +RefMD5=264B82F0FC2431D6EEFDE9C9F3ED7596 + +[C70B91430866300CE38B49098019EF9D] +GoodName=Mortal Kombat 4 (U) [!] +CRC=417DD4F4 1B482FE2 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[CCD5A3B82976D65B3B42E8E2B2B43B48] +GoodName=Mortal Kombat 4 (U) [b1] +CRC=F96E28F7 421A4285 +RefMD5=C70B91430866300CE38B49098019EF9D + +[4C7092585CF64BBE7F26ECA720AE8941] +GoodName=Mortal Kombat 4 (U) [b2] +CRC=DB6E353B 205B0C53 +RefMD5=C70B91430866300CE38B49098019EF9D + +[480855E2348D6B85721C620AE9FEF138] +GoodName=Mortal Kombat 4 (U) [b3] +CRC=417DD4F4 1B482FE2 +RefMD5=C70B91430866300CE38B49098019EF9D + +[F972B634F638CC54AD6DCBFDC661CC02] +GoodName=Mortal Kombat 4 (U) [h1C] +CRC=417DD4F4 1B482FE2 +RefMD5=C70B91430866300CE38B49098019EF9D + +[A5F7C9F5B711ECA7C2A2923EEA6CF762] +GoodName=Mortal Kombat 4 (U) [t1] +CRC=DB6E353B 205B0C53 +RefMD5=C70B91430866300CE38B49098019EF9D + +[24E39D47A0D1AFA138B1F39AA2DAA648] +GoodName=Mortal Kombat 4 (U) [t1][f1] (PAL) +CRC=DB6E353B 205B0C53 +RefMD5=C70B91430866300CE38B49098019EF9D + +[18E1CA4BE7D8E56AC940852EC5E3ED22] +GoodName=Mortal Kombat 4 (U) [t2] (Hit Anywhere) +CRC=417DD7F4 C95B6E9E +RefMD5=C70B91430866300CE38B49098019EF9D + +[38A82A56AE61A4D354C6A26E64D25E1C] +GoodName=Mortal Kombat Mythologies - Sub-Zero (E) [!] +CRC=FF44EDC4 1AAE9213 +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes + +[DAFEE0C1FC99882A2C6A340BF0E58A08] +GoodName=Mortal Kombat Mythologies - Sub-Zero (E) [h1C] +CRC=FF44EDC4 1AAE9213 +RefMD5=38A82A56AE61A4D354C6A26E64D25E1C + +[528445FB76D0F060DF5CBE71AEEDA20F] +GoodName=Mortal Kombat Mythologies - Sub-Zero (E) [t1] (Endless Ice) +CRC=6DF2CB25 4D4821F8 +RefMD5=38A82A56AE61A4D354C6A26E64D25E1C + +[DEEC4FAEC416F4E02D934C2E42C0CAAD] +GoodName=Mortal Kombat Mythologies - Sub-Zero (U) [!] +CRC=C34304AC 2D79C021 +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes + +[8F2544F095EF7D9A5096E3D52472D699] +GoodName=Mortal Kombat Mythologies - Sub-Zero (U) [b1] +CRC=834304AE 5845CD3A +RefMD5=DEEC4FAEC416F4E02D934C2E42C0CAAD + +[1793B45C4797D9418685946A002B5D15] +GoodName=Mortal Kombat Mythologies - Sub-Zero (U) [b2] +CRC=C34304AC 2D79C021 +RefMD5=DEEC4FAEC416F4E02D934C2E42C0CAAD + +[5443BFB72D91D0DFD72FC1C6FA03A113] +GoodName=Mortal Kombat Mythologies - Sub-Zero (U) [b3] +CRC=C34304AC 2D79C021 +RefMD5=DEEC4FAEC416F4E02D934C2E42C0CAAD + +[7CCC138882A64267AD58449F309FC1D1] +GoodName=Mortal Kombat Mythologies - Sub-Zero (U) [f1] +CRC=834304AE 5845CD3A +RefMD5=DEEC4FAEC416F4E02D934C2E42C0CAAD + +[A6C51954EE5DF373E159E0E55DEAE239] +GoodName=Mortal Kombat Mythologies - Sub-Zero (U) [f3] (PAL) +CRC=834304AE 5845CD3A +RefMD5=DEEC4FAEC416F4E02D934C2E42C0CAAD + +[FFF4E1455C03F71272063C309D9F9102] +GoodName=Mortal Kombat Mythologies - Sub-Zero (U) [h1C] +CRC=C34304AC 2D79C021 +RefMD5=DEEC4FAEC416F4E02D934C2E42C0CAAD + +[FCD0BFF90306B13EB8E5007E5B4C2CB7] +GoodName=Mortal Kombat Mythologies - Sub-Zero (U) [h2C] +CRC=834304AE 5845CD3A +RefMD5=DEEC4FAEC416F4E02D934C2E42C0CAAD + +[5583527ED4AA49CF713FAE400E77F9A2] +GoodName=Mortal Kombat Mythologies - Sub-Zero (U) [o1] +CRC=C34304AC 2D79C021 +RefMD5=DEEC4FAEC416F4E02D934C2E42C0CAAD + +[AB06E6D777AE710F9B5A4DC4E7A295C8] +GoodName=Mortal Kombat Mythologies - Sub-Zero (U) [t1] +CRC=5972E751 228381B3 +RefMD5=DEEC4FAEC416F4E02D934C2E42C0CAAD + +[85B99F3D09C4070EEA7669A09D20243F] +GoodName=Mortal Kombat Mythologies - Sub-Zero (U) [t2] (Endless Ice) +CRC=ADDD6241 AA79B2F2 +RefMD5=DEEC4FAEC416F4E02D934C2E42C0CAAD + +[B278DDD3FB63F70B8B6EFEF445D81595] +GoodName=Mortal Kombat SRAM Loader (PD) +CRC=947A4B47 90BFECA6 + +[7A558BBAD8CE8828414A9CF3B044A87D] +GoodName=Mortal Kombat Trilogy (E) [!] +CRC=8C3D1192 BEF172E1 +SaveType=None +Players=2 + +[1C6FE6A40AAC4BD515373B6ED8D25DBF] +GoodName=Mortal Kombat Trilogy (E) [b1] +CRC=8C3D1192 BEF172E1 +RefMD5=7A558BBAD8CE8828414A9CF3B044A87D + +[0F9B89C903BEFEDCFD107E5B5ADE687F] +GoodName=Mortal Kombat Trilogy (E) [h1C] +CRC=8C3D1192 BEF172E1 +RefMD5=7A558BBAD8CE8828414A9CF3B044A87D + +[B05DEC10CDEFACF4153E345940410477] +GoodName=Mortal Kombat Trilogy (E) [o1] +CRC=8C3D1192 BEF172E1 +RefMD5=7A558BBAD8CE8828414A9CF3B044A87D + +[AB72CB8971FA37176D3219B5F49AF442] +GoodName=Mortal Kombat Trilogy (E) [t1] (Hit Anywhere) +CRC=8C3D1192 B5096A18 +RefMD5=7A558BBAD8CE8828414A9CF3B044A87D + +[CFC196103E355B12A50605AB268992FA] +GoodName=Mortal Kombat Trilogy (E) [t2] (All Attacks Hurt P1) +CRC=833D11B6 1848E72B +RefMD5=7A558BBAD8CE8828414A9CF3B044A87D + +[9CC60D046372D2C9A529ED225E3CDB08] +GoodName=Mortal Kombat Trilogy (E) [t3] (All Attacks Hurt P2) +CRC=833D1192 D3C58762 +RefMD5=7A558BBAD8CE8828414A9CF3B044A87D + +[EBF2AC190EBB2FE6D75AD0ACAA2A82CD] +GoodName=Mortal Kombat Trilogy (E) [t4] (Hyper Mode) +CRC=93ED1192 2B2C6244 +RefMD5=7A558BBAD8CE8828414A9CF3B044A87D + +[ED7773988BCC03D06E2330A8E77BEC6F] +GoodName=Mortal Kombat Trilogy (E) [t5] (2x Aggressor) +CRC=8C352E50 6B93F13B +RefMD5=7A558BBAD8CE8828414A9CF3B044A87D + +[DF00C698E2B18A6CA94C09CCD82CACEB] +GoodName=Mortal Kombat Trilogy (E) [t6] (P1 Invincible) +CRC=8C3511AE 57115A86 +RefMD5=7A558BBAD8CE8828414A9CF3B044A87D + +[9B7F29AAB911D6753F2011C48DA752BF] +GoodName=Mortal Kombat Trilogy (U) (V1.0) [!] +CRC=D9F75C12 A8859B59 +Players=2 +SaveType=None + +[7CD386C8D2E69DBBF55F02A564BD6A9A] +GoodName=Mortal Kombat Trilogy (U) (V1.0) [b1] +CRC=D9F75C12 A8859B59 +RefMD5=9B7F29AAB911D6753F2011C48DA752BF + +[77CE01C32E172C7DD812C4F1179FBA2E] +GoodName=Mortal Kombat Trilogy (U) (V1.0) [b2] +CRC=D9F75C12 A8859B59 +RefMD5=9B7F29AAB911D6753F2011C48DA752BF + +[9DA1E143FF580834FE485D08C21B6D01] +GoodName=Mortal Kombat Trilogy (U) (V1.0) [b3] +CRC=D9F75C12 A8859B59 +RefMD5=9B7F29AAB911D6753F2011C48DA752BF + +[ED4414B512CF22DA64B080D34B5E2F4F] +GoodName=Mortal Kombat Trilogy (U) (V1.0) [b4] +CRC=D9F75C12 A8859B59 +RefMD5=9B7F29AAB911D6753F2011C48DA752BF + +[57464801A058B97E056766DDFCF93A69] +GoodName=Mortal Kombat Trilogy (U) (V1.0) [b5] +CRC=D9F75C12 A8859B59 +RefMD5=9B7F29AAB911D6753F2011C48DA752BF + +[8CE0A41CB29C14300B482E0E9897EBBF] +GoodName=Mortal Kombat Trilogy (U) (V1.0) [h1C] +CRC=D9F75C12 A8859B59 +RefMD5=9B7F29AAB911D6753F2011C48DA752BF + +[4DBAD6B0E2F30A63F974A85513B668E0] +GoodName=Mortal Kombat Trilogy (U) (V1.0) [h2C] +CRC=D9F75C12 A8859B59 +RefMD5=9B7F29AAB911D6753F2011C48DA752BF + +[976825DAB07E6F5D69BFD5B46337DE85] +GoodName=Mortal Kombat Trilogy (U) (V1.0) [o1] +CRC=D9F75C12 A8859B59 +RefMD5=9B7F29AAB911D6753F2011C48DA752BF + +[EE052C69FFA67DB3544872AB0E745DDF] +GoodName=Mortal Kombat Trilogy (U) (V1.0) [o1][h1C] +CRC=D9F75C12 A8859B59 +RefMD5=9B7F29AAB911D6753F2011C48DA752BF + +[10774BFBC9D815194AD904F898CBE96F] +GoodName=Mortal Kombat Trilogy (U) (V1.0) [o1][h2C] +CRC=D9F75C12 A8859B59 +RefMD5=9B7F29AAB911D6753F2011C48DA752BF + +[04A3F6D2A30FEDE6CADC5C2FCBCFBD12] +GoodName=Mortal Kombat Trilogy (U) (V1.0) [t1] (Hit Anywhere) +CRC=F9F75B92 AFEC042B +RefMD5=9B7F29AAB911D6753F2011C48DA752BF + +[CCD0BA9C220D1EE91B39747A6E5065EE] +GoodName=Mortal Kombat Trilogy (U) (V1.0) [t2] (All Attacks Hurt P1) +CRC=F2F75C36 36637257 +RefMD5=9B7F29AAB911D6753F2011C48DA752BF + +[548C444FB604CA179EAD4115FFB070FC] +GoodName=Mortal Kombat Trilogy (U) (V1.0) [t3] (All Attacks Hurt P2) +CRC=D2F75C12 E89EB415 +RefMD5=9B7F29AAB911D6753F2011C48DA752BF + +[4DED9381CD0D396AE6C9634D575DD93C] +GoodName=Mortal Kombat Trilogy (U) (V1.0) [t4] (Hyper Mode) +CRC=A2015C11 C317ECAB +RefMD5=9B7F29AAB911D6753F2011C48DA752BF + +[F5509B1EA83A49D01E5E4EF475B87278] +GoodName=Mortal Kombat Trilogy (U) (V1.0) [t5] (2x Aggressor) +CRC=D9FECC50 D3AA8423 +RefMD5=9B7F29AAB911D6753F2011C48DA752BF + +[D68FC4D8568B7D02EFD47F32B9C091D7] +GoodName=Mortal Kombat Trilogy (U) (V1.0) [t6] (P1 Invincible) +CRC=A1815C2E C6806731 +RefMD5=9B7F29AAB911D6753F2011C48DA752BF + +[26129419799DB01BFE79F279EC43B334] +GoodName=Mortal Kombat Trilogy (U) (V1.1) [!] +CRC=19F55D46 73A27B34 +Players=2 +SaveType=None + +[3DCB15043063BD656A0223C519218CFB] +GoodName=Mortal Kombat Trilogy (U) (V1.2) [!] +CRC=83F33AA9 A901D40D +Players=2 +SaveType=None + +[27F761B7DD73E12BB311772780D6B9F4] +GoodName=Mortal Kombat Trilogy (U) (V1.2) [t1] (Hit Anywhere) +CRC=83F33AA9 2649847A +RefMD5=3DCB15043063BD656A0223C519218CFB + +[8A7B5A6AB0E815DBDFFD1FC99939CE9F] +GoodName=Mortal Kombat Trilogy (U) (V1.2) [t2] (All Attacks Hurt P1) +CRC=BCF33AAD BF3C37EC +RefMD5=3DCB15043063BD656A0223C519218CFB + +[37FEB7178712980DD0953D195187C35D] +GoodName=Mortal Kombat Trilogy (U) (V1.2) [t3] (All Attacks Hurt P2) +CRC=9CF33AA9 3F05381F +RefMD5=3DCB15043063BD656A0223C519218CFB + +[D3B28E1E154C5B58A40E3D71D8599CE2] +GoodName=Mortal Kombat Trilogy (U) (V1.2) [t4] (Hyper Mode) +CRC=9C013AA8 EB3267A7 +RefMD5=3DCB15043063BD656A0223C519218CFB + +[0D708DDE7EC6B67E705F1D865D70AFDA] +GoodName=Mortal Kombat Trilogy (U) (V1.2) [t5] (2x Aggressor) +CRC=83FB2B69 7A5D2980 +RefMD5=3DCB15043063BD656A0223C519218CFB + +[68EBC8C849459FE30E7162D48EBAC0BD] +GoodName=Mortal Kombat Trilogy (U) (V1.2) [t6] (P1 Invincible) +CRC=83F33AA9 A901D40D +RefMD5=3DCB15043063BD656A0223C519218CFB + +[B6A7B85C123DF4E0B9CC118578DBC9A2] +GoodName=Mortal Kombat Trilogy (U) (Beta) (1996-05-13) [!] +RefMD5=9B7F29AAB911D6753F2011C48DA752BF + +[08BEA3310E778A6584EB64CD3F15F86E] +GoodName=Ms. Pac-Man - Maze Madness (U) [!] +CRC=1938525C 586E9656 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[F905CA22CC030BBED516F3D1B6C2153A] +GoodName=My Angel Demo (PD) +CRC=9865799F 006F908C + +[E6B5C17B7BBBB7C432B3506C085D16C4] +GoodName=Mystical Ninja 2 Starring Goemon (E) (M3) [!] +CRC=7F9345D3 841ECADE +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[75AD771425CBE2B1E8C7B4D94E67B1CA] +GoodName=Mystical Ninja 2 Starring Goemon (E) (M3) [hI] +CRC=C27F7CEC 85E0806F +RefMD5=E6B5C17B7BBBB7C432B3506C085D16C4 + +[004EA34EE12CBABDC053419714E66DD4] +GoodName=Mystical Ninja 2 Starring Goemon (E) (M3) [t1] +CRC=C27F7CEC 85E0806F +RefMD5=E6B5C17B7BBBB7C432B3506C085D16C4 + +[698930C7CCD844673D77FFECCB3DD66E] +GoodName=Mystical Ninja Starring Goemon (E) [!] +CRC=F5360FBE 2BF1691D +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[DBD2BC43FCDADACD234AEFC8130A5413] +GoodName=Mystical Ninja Starring Goemon (E) [b1] +CRC=F5360FBE 2BF1691D +RefMD5=698930C7CCD844673D77FFECCB3DD66E + +[8F1C1FEAAF0D053E230361E3F81B0269] +GoodName=Mystical Ninja Starring Goemon (E) [h1C] +CRC=F5360FBE 2BF1691D +RefMD5=698930C7CCD844673D77FFECCB3DD66E + +[1FFBDAB727C9D634D4F4DDBD9F358445] +GoodName=Mystical Ninja Starring Goemon (E) [t1] +CRC=835B97A2 FF6C0060 +RefMD5=698930C7CCD844673D77FFECCB3DD66E + +[643CCE1AB06F97E9590241D27E5C2363] +GoodName=Mystical Ninja Starring Goemon (U) [!] +CRC=FCBCCB21 72903C6B +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[42E282A3F208C4BDE50A4A4301181B16] +GoodName=Mystical Ninja Starring Goemon (U) [h1C] +CRC=FCBCCB21 72903C6B +RefMD5=643CCE1AB06F97E9590241D27E5C2363 + +[07A7D3DB5B64A6CCF9D44B321472CC21] +GoodName=Mystical Ninja Starring Goemon (U) [t1] +CRC=7AADA8DD 94DAB468 +RefMD5=643CCE1AB06F97E9590241D27E5C2363 + +[55F99A3F3402491E9517980BE636E3FE] +GoodName=Mystical Ninja Starring Goemon (U) [t1][h2C] +CRC=7AADA8DD 94DAB468 +RefMD5=643CCE1AB06F97E9590241D27E5C2363 + +[4D1821886352EAA2F663CFF63ED17DD8] +GoodName=Mystical Ninja Starring Goemon (U) [t2] +CRC=7AADA8DD 94DAB468 +RefMD5=643CCE1AB06F97E9590241D27E5C2363 + +[17B839B8E72A6287A5BB3CEFCBC035E9] +GoodName=N64 Scene Gallery by CALi (PD) +CRC=6D2C07F1 C884F0D0 + +[882B30625B722B5C29D0D94E70D9302E] +GoodName=N64 Seminar Demo - CPU by ZoRAXE (PD) +CRC=FD61BB45 FBB51EB2 + +[8B7816E975DB27B4BF591BFC73C43944] +GoodName=N64 Seminar Demo - RSP by ZoRAXE (PD) +CRC=6D03673A 1D63C191 + +[023175B6C809704F00A317ABCD25A8F9] +GoodName=N64 Stars Demo (PD) [b1] +CRC=71255651 C6AE0EA6 + +[67836FE63901319874E0754BC918AF7D] +GoodName=N64 Stars Demo (PD) +CRC=71255651 C6AE0EA6 + +[F4B5863F550BC83C7924E423B01E1C5A] +GoodName=N64probe (Button Test) by MooglyGuy (PD) +CRC=44410533 0C61FA96 + +[45FEB0FBBEC6CB48FF21DEAE176E9B6B] +GoodName=NASCAR 2000 (U) [!] +CRC=DF331A18 5FD4E044 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[DB3A918FA61E1FB3110CFE6E9DA33E97] +GoodName=NASCAR 2000 (U) [f1] (PAL) +CRC=651F2792 E40CC56B +RefMD5=45FEB0FBBEC6CB48FF21DEAE176E9B6B + +[15A87A6D01DBA1A7C4375FFBC1214BB8] +GoodName=NASCAR 99 (E) (M3) [!] +CRC=AE4992C9 9253B253 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[A31AD7E7E6177BED7345635FDA563FCA] +GoodName=NASCAR 99 (E) (M3) [h1C] +CRC=AE4992C9 9253B253 +RefMD5=15A87A6D01DBA1A7C4375FFBC1214BB8 + +[DC5F1A814C8423B4B43F71C229D65A84] +GoodName=NASCAR 99 (U) [!] +CRC=23749578 80DC58FD +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[AC88A7D81FF0B712EA3A302419F3A927] +GoodName=NASCAR 99 (U) [b1] +CRC=23749578 80DC58FD +RefMD5=DC5F1A814C8423B4B43F71C229D65A84 + +[DA77C8AB76E6209550D56FED1817AFBD] +GoodName=NASCAR 99 (U) [b2] +CRC=FCB2955B B302626D +RefMD5=DC5F1A814C8423B4B43F71C229D65A84 + +[A267D8C94031678DD395FE4667C4A76A] +GoodName=NASCAR 99 (U) [b3] +CRC=23E39896 73AB48DC +RefMD5=DC5F1A814C8423B4B43F71C229D65A84 + +[71BE7A48778737FDDD3CDE7849502C5B] +GoodName=NASCAR 99 (U) [f1] (PAL) +CRC=FCB2955B B302626D +RefMD5=DC5F1A814C8423B4B43F71C229D65A84 + +[DB644859C4DCE5418010A2427E3904C0] +GoodName=NASCAR 99 (U) [o1] +CRC=23749578 80DC58FD +RefMD5=DC5F1A814C8423B4B43F71C229D65A84 + +[73BB54FFD3C0FC71F941D9A8CC57E2A1] +GoodName=NBA Courtside 2 - Featuring Kobe Bryant (U) [!] +CRC=916852D8 73DBEAEF +Players=4 +SaveType=Flash RAM +Rumble=Yes + +[EE4DCAED6759CE013BC7B5E8E815B343] +GoodName=NBA Courtside 2 - Featuring Kobe Bryant (U) [f1] (PAL) +CRC=3F16568F 37D93603 +RefMD5=73BB54FFD3C0FC71F941D9A8CC57E2A1 + +[F734667EF21DA97092F54D2547E11E51] +GoodName=NBA Courtside 2 - Featuring Kobe Bryant (U) [f2] +CRC=2816D957 A59FF70A +RefMD5=73BB54FFD3C0FC71F941D9A8CC57E2A1 + +[032ADEEF1C2D0B4387FAC099334F72E3] +GoodName=NBA Courtside 2 - Featuring Kobe Bryant (U) [hI] +CRC=24F7EB57 74B3F9F4 +RefMD5=73BB54FFD3C0FC71F941D9A8CC57E2A1 + +[94E3F2ACE3EB74150F036B217FF50370] +GoodName=NBA Courtside 2 - Featuring Kobe Bryant (U) [hI][f1] (PAL) +CRC=26211297 97DB4DFC +RefMD5=73BB54FFD3C0FC71F941D9A8CC57E2A1 + +[62365463743857CFC823978E0E590D84] +GoodName=NBA Hangtime (E) [!] +CRC=C788DCAE BD03000A +Players=4 +SaveType=None +Mempak=Yes + +[0057A561D7034392D4267A4134DA41B0] +GoodName=NBA Hangtime (E) [h1C] +CRC=C788DCAE BD03000A +RefMD5=62365463743857CFC823978E0E590D84 + +[DC15FCBEAE0F1FEF7BEE141D77BB25A0] +GoodName=NBA Hangtime (U) [!] +CRC=4E69B487 FE18E290 +Players=4 +SaveType=None +Mempak=Yes + +[9C595E5A5F027385A340ADDF609852DD] +GoodName=NBA Hangtime (U) [b1] +CRC=4E69B487 FE18E290 +RefMD5=DC15FCBEAE0F1FEF7BEE141D77BB25A0 + +[4955DEA9356D1506D6DE8BD8DA10E938] +GoodName=NBA Hangtime (U) [b2] +CRC=4E69B487 FE18E290 +RefMD5=DC15FCBEAE0F1FEF7BEE141D77BB25A0 + +[C8D6A414505595C13C7DA4D07A172343] +GoodName=NBA Hangtime (U) [b3] +CRC=4E69B487 FE18E290 +RefMD5=DC15FCBEAE0F1FEF7BEE141D77BB25A0 + +[C2D094778DA53C7A84466130EC5C65B0] +GoodName=NBA Hangtime (U) [f1] (PAL) +CRC=4E69B487 FE18E290 +RefMD5=DC15FCBEAE0F1FEF7BEE141D77BB25A0 + +[80F918D90DF42C9841AE998A89223C1E] +GoodName=NBA Hangtime (U) [o1] +CRC=4E69B487 FE18E290 +RefMD5=DC15FCBEAE0F1FEF7BEE141D77BB25A0 + +[62E182D019DCE0C0EEAA3BE2023A327A] +GoodName=NBA Hangtime (U) [o1][f1] +CRC=4E69B487 FE18E290 +RefMD5=DC15FCBEAE0F1FEF7BEE141D77BB25A0 + +[4C7A2F4881EACA75DC2FC36673AE2A20] +GoodName=NBA In the Zone '98 (J) [!] +CRC=36ACBA9B F28D4D94 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[4151ED80568EFCCA34F8831D957EB7A6] +GoodName=NBA In the Zone '98 (J) [o1] +CRC=36ACBA9B F28D4D94 +RefMD5=4C7A2F4881EACA75DC2FC36673AE2A20 + +[23215642F5FAAAD0761166EA018963F0] +GoodName=NBA In the Zone '98 (J) [o2] +CRC=36ACBA9B F28D4D94 +RefMD5=4C7A2F4881EACA75DC2FC36673AE2A20 + +[BBB48BE198089A26050C84FE5B7B8BD5] +GoodName=NBA In the Zone '98 (U) [!] +CRC=6A121930 665CC274 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[EE43F010F2E87BC68535D333FE64C516] +GoodName=NBA In the Zone '98 (U) [b1] +CRC=6A121930 665CC274 +RefMD5=BBB48BE198089A26050C84FE5B7B8BD5 + +[49B49E6DD528E896DE9BCE3DCCF3442E] +GoodName=NBA In the Zone '98 (U) [b2] +CRC=6A121930 665CC274 +RefMD5=BBB48BE198089A26050C84FE5B7B8BD5 + +[42F3A177F54C86F2C8EE6AFDB892A5A9] +GoodName=NBA In the Zone '98 (U) [b3] +CRC=36ACBA9B F28D4D94 +RefMD5=BBB48BE198089A26050C84FE5B7B8BD5 + +[BF33C371BF396A5F6E72627A34AEDAF5] +GoodName=NBA In the Zone '98 (U) [h1C] +CRC=6A121930 665CC274 +RefMD5=BBB48BE198089A26050C84FE5B7B8BD5 + +[62DFA8A5906E973A2C923A165EBE00A1] +GoodName=NBA In the Zone '98 (U) [h2C] +CRC=6A121930 665CC274 +RefMD5=BBB48BE198089A26050C84FE5B7B8BD5 + +[92D2BD868B17B3CA8A19116ADDB963B0] +GoodName=NBA In the Zone '98 (U) [o1] +CRC=6A121930 665CC274 +RefMD5=BBB48BE198089A26050C84FE5B7B8BD5 + +[6CBF4014C053E16852A3DB80AEB4C853] +GoodName=NBA In the Zone '99 (U) [!] +CRC=A292524F 3D6C2A49 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[F8F87AEB2C537C9CB2E9913050BFC928] +GoodName=NBA In the Zone 2 (J) [!] +CRC=AAE11F01 2625A045 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[4244CC48674C26BD848718C05688F821] +GoodName=NBA In the Zone 2000 (E) [!] +CRC=B3054F9F 96B69EB5 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[AF6521E33FDE918B9A2298FA0BD3AA90] +GoodName=NBA In the Zone 2000 (E) [h1C] +CRC=B3054F9F 96B69EB5 +RefMD5=4244CC48674C26BD848718C05688F821 + +[1942833AC1A71BE8BAE74BBDFD6DE278] +GoodName=NBA In the Zone 2000 (U) [!] +CRC=8DF95B18 ECDA497B +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[F4401BCC9DD25254503E32B482EB3FAA] +GoodName=NBA In the Zone 2000 (U) [f1] (PAL) +CRC=4F8AA5EC 1E6E72DE +RefMD5=1942833AC1A71BE8BAE74BBDFD6DE278 + +[604FEB17258044A3E6C3AA9D2C5B62F9] +GoodName=NBA Jam 2000 (E) [!] +CRC=B6D0CAA0 E3F493C8 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[AFECC9A2DF7B1A66A6B7AB3AA8B4BD2E] +GoodName=NBA Jam 2000 (U) [!] +CRC=EBEEA8DB F2ECB23C +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[E25F3A1136C9C81702E0827040C5A115] +GoodName=NBA Jam 2000 (U) [f1] (PAL) +CRC=F3996B67 3A3030FA +RefMD5=AFECC9A2DF7B1A66A6B7AB3AA8B4BD2E + +[BE72BE370BC0A76D403FF2B9ED2A9173] +GoodName=NBA Jam 99 (E) [!] +CRC=E600831E 59F422A8 +Players=4 +SaveType=None +Mempak=Yes + +[0A9D53EF71A0C6F2AE3A0435E3D58747] +GoodName=NBA Jam 99 (E) [h1C] +CRC=E600831E 59F422A8 +RefMD5=BE72BE370BC0A76D403FF2B9ED2A9173 + +[ADBE5CA10F659AF2BE712038E8522704] +GoodName=NBA Jam 99 (U) [!] +CRC=810729F6 E03FCFC1 +Players=4 +SaveType=None +Mempak=Yes + +[7344483130995CA211B5B9FF9891A9DE] +GoodName=NBA Jam 99 (U) [b1] +CRC=810729F6 E03FCFC1 +RefMD5=ADBE5CA10F659AF2BE712038E8522704 + +[5382AD48844A3473D4CBA87C85F2BAC2] +GoodName=NBA Jam 99 (U) [f1] (PAL) +CRC=61079876 32DB765E +RefMD5=ADBE5CA10F659AF2BE712038E8522704 + +[7FEC099D1A989D5222D3F9E1A7770404] +GoodName=NBA Live 2000 (E) (M4) [!] +CRC=EB499C8F CD4567B6 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[FC47F85CC501C8C5BD9D0CA4DB48258F] +GoodName=NBA Live 2000 (U) (M4) [!] +CRC=5F25B0EE 6227C1DB +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[226C19C8759314AC740420DDC3A34EB4] +GoodName=NBA Live 99 (E) (M5) [!] +CRC=CF84F45F 00E4F6EB +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[DBE79AE6531B491B8F8EE8B2B814D665] +GoodName=NBA Live 99 (U) (M5) [!] +CRC=57F81C9B 1133FA35 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[7044E135E702B32DFCF13E688461967F] +GoodName=NBA Live 99 (U) (M5) [b1] +CRC=57F81C9B 1133FA35 +RefMD5=DBE79AE6531B491B8F8EE8B2B814D665 + +[4DD6A2CF6091A92C43CE1B4A1B6F1556] +GoodName=NBA Live 99 (U) (M5) [b2] +CRC=57F81C9B 1133FA35 +RefMD5=DBE79AE6531B491B8F8EE8B2B814D665 + +[5F46FC3780A50D5BB8FCB0F1C95686B0] +GoodName=NBA Live 99 (U) (M5) [b3] +CRC=57F81C9B 1133FA35 +RefMD5=DBE79AE6531B491B8F8EE8B2B814D665 + +[A4111A6CDDBDE0A45489106F0DF0CA2B] +GoodName=NBA Pro 98 (E) [!] +CRC=ACDE962F B2CBF87F +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[C5EBBDD41EAEA8BD02CF520640CCCCDF] +GoodName=NBA Pro 99 (E) [!] +CRC=8D1780B6 57B3B976 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[9A203506DB213F97FE28210AAF56F820] +GoodName=NBA Pro 99 (E) [f1] (NTSC) +CRC=356130AD 29367E56 +RefMD5=C5EBBDD41EAEA8BD02CF520640CCCCDF + +[881E98B47F32093C330A8B0DAD6BB65D] +GoodName=NBA Showtime - NBA on NBC (U) [!] +CRC=3FFE80F4 A7C15F7E +Players=4 +SaveType=None +Mempak=Yes +CountPerOp=1 + +[76DB89759121710C416ECFB1736B5E39] +GoodName=NBA Showtime - NBA on NBC (U) [f1] (Country Check) +CRC=E78F66E6 754ABDF5 +RefMD5=881E98B47F32093C330A8B0DAD6BB65D + +[760D5F0A578D65E68F5B4E8F64271C88] +GoodName=NBA Showtime - NBA on NBC (U) [f1] (PAL) +CRC=9CEED5BA 62A146D5 +RefMD5=881E98B47F32093C330A8B0DAD6BB65D + +[A05D4FF483AF3F1C55BEDC455E7EDBBE] +GoodName=NBC First Intro by CALi (PD) +CRC=15DB95D4 77BC52D8 + +[325B9DCD5D23F269017C16E2BA62DEA3] +GoodName=NBC-LFC Kings of Porn Vol 01 (PD) [a1] +CRC=DD95F49D 2A9B8893 + +[88095C9BD22232383AF82235F03B2658] +GoodName=NBC-LFC Kings of Porn Vol 01 (PD) +CRC=AB9F8D97 95EAA766 +RefMD5=325B9DCD5D23F269017C16E2BA62DEA3 + +[CE915D72FEA86AA99D9C015661A3D768] +GoodName=NBCG Special Edition (PD) +CRC=011F98B2 1E1C8263 + +[8CE55DA21D0FA7B41646A1F3F45F57A1] +GoodName=NBCG's Kings of Porn Demo (PD) +CRC=61A5FCEE B59FD8D3 + +[C0ABE398CBC45EC90D03C5ADC26C1065] +GoodName=NBCG's Tag Gallery 01 by CALi (PD) +CRC=15AA9AF2 FF33D333 + +[F27300E1883EA849A69567D3AEDC5F56] +GoodName=NBCrew 2 Demo (PD) +CRC=84067BAC 87FBA623 + +[4CF0249345388BB098F79DDCD7A00798] +GoodName=NEO Myth N64 Menu Demo V0.1 (PD) +CRC=6539E529 1FE8CE01 + +[7F6C5E71711DEC81E77CCF71060F67CA] +GoodName=NFL Blitz (U) [!] +CRC=D094B170 D7C4B5CC +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[F0A1CC3D1D99A60F35D37DDCCF43CABB] +GoodName=NFL Blitz (U) [f1] (PAL) +CRC=3D6044AB 46768D77 +RefMD5=7F6C5E71711DEC81E77CCF71060F67CA + +[7E856FA8F743900FEBA5A4E28C234AF7] +GoodName=NFL Blitz - Special Edition (U) [!] +CRC=30EAD54F 31620BF6 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[BA49514441023722F02D41C62612F6C3] +GoodName=NFL Blitz 2000 (U) (V1.0) [!] +CRC=15A00969 34E5A285 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[DDBE4248EA34E11C091A975776042670] +GoodName=NFL Blitz 2000 (U) (V1.0) [f1] (PAL) +CRC=FEB72E1D 5BD2C925 +RefMD5=BA49514441023722F02D41C62612F6C3 + +[DD96BB80E652CD1CF23CA4B8294BA7B5] +GoodName=NFL Blitz 2000 (U) (V1.1) [!] +CRC=5B755842 6CA39C7A +RefMD5=BA49514441023722F02D41C62612F6C3 + +[E4EDD73CB036C6B143CEE9AEEED60341] +GoodName=NFL Blitz 2001 (U) [!] +CRC=36FA35EB E85E2E36 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[D13A38B9639CF1944FE7024E4C58739D] +GoodName=NFL Blitz 2001 (U) [f1] (PAL-NTSC) +CRC=EB7709E2 27A91031 +RefMD5=E4EDD73CB036C6B143CEE9AEEED60341 + +[75C0121D84915BF5C1FBD389CF9F9C17] +GoodName=NFL Quarterback Club 2000 (E) [!] +CRC=88BD5A9E E81FDFBF +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[EC18E3131040842E32EBAB66C7496EBD] +GoodName=NFL Quarterback Club 2000 (U) [!] +CRC=E3AB4ED0 83040DD2 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[55224F1148F873A689604F2DC6432682] +GoodName=NFL Quarterback Club 2000 (U) [b1] +CRC=E3AB4ED0 83040DD2 +RefMD5=EC18E3131040842E32EBAB66C7496EBD + +[604E2FB5AC9A26A81883A4C19037862A] +GoodName=NFL Quarterback Club 2000 (U) [b2] +CRC=E3AB4ED0 83040DD2 +RefMD5=EC18E3131040842E32EBAB66C7496EBD + +[FD2CBDEA0992452B52E2803224232D12] +GoodName=NFL Quarterback Club 2001 (U) [!] +CRC=28784622 FFB22985 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[A18CA5DBC85668667AA467ADD6A62B39] +GoodName=NFL Quarterback Club 98 (E) [!] +CRC=4B629EF4 99B21D9B +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[37954BA9067840FAFF851092043F0435] +GoodName=NFL Quarterback Club 98 (E) [o1] +CRC=4B629EF4 99B21D9B +RefMD5=A18CA5DBC85668667AA467ADD6A62B39 + +[709F966C30CE6DF1833E95740A5A2AB2] +GoodName=NFL Quarterback Club 98 (U) [!] +CRC=D89BE2F8 99C97ADF +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[B39D12910D12498605A9F793C29866BE] +GoodName=NFL Quarterback Club 98 (U) [b1] +CRC=D89BE2F8 99C97ADF +RefMD5=709F966C30CE6DF1833E95740A5A2AB2 + +[8A47091F443117BFA629B0B29D4450C6] +GoodName=NFL Quarterback Club 98 (U) [o1] +CRC=D89BE2F8 99C97ADF +RefMD5=709F966C30CE6DF1833E95740A5A2AB2 + +[7EC0484C2BA6AA9F0A45D7AC1F4117DA] +GoodName=NFL Quarterback Club 99 (E) [!] +CRC=52A3CF47 4EC13BFC +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[EBDC155D7462F8C73DB4730C6BF4010D] +GoodName=NFL Quarterback Club 99 (E) [b1] +CRC=52A3CF47 4EC13BFC +RefMD5=7EC0484C2BA6AA9F0A45D7AC1F4117DA + +[928869D1CE001B813BA908DFE18D7F94] +GoodName=NFL Quarterback Club 99 (U) [!] +CRC=BE76EDFF 20452D09 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[B7E41D34D209B6CFA92E3D622F911C4E] +GoodName=NHL 99 (E) [!] +CRC=287D601E ABF4F8AE +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[A62FA044BCB5507D358424ABDA6419DB] +GoodName=NHL 99 (U) [!] +CRC=591A806E A5E6921D +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[349F61F9747F2D2098F305924C97A1BF] +GoodName=NHL Blades of Steel '99 (U) [!] +CRC=82EFDC30 806A2461 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[9FF8AFF664781384A5FC01449DC5AD8D] +GoodName=NHL Blades of Steel '99 (U) [f1] (PAL) +CRC=82EFDC30 806A2461 +RefMD5=349F61F9747F2D2098F305924C97A1BF + +[46476A5626CD99B3749AC1EE1E234FAC] +GoodName=NHL Breakaway 98 (E) [!] +CRC=29CE7692 71C58579 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[43D788E7CAEA1146228B763C13E8E740] +GoodName=NHL Breakaway 98 (E) [f1] (NTSC) +CRC=C5F020F3 27B2CA73 +RefMD5=46476A5626CD99B3749AC1EE1E234FAC + +[5CB521B928FB94E84F4E0E49B6E25CD4] +GoodName=NHL Breakaway 98 (E) [h1C] +CRC=29CE7692 71C58579 +RefMD5=46476A5626CD99B3749AC1EE1E234FAC + +[75F197DEF1D084534857493582D84E73] +GoodName=NHL Breakaway 98 (E) [o1] +CRC=29CE7692 71C58579 +RefMD5=46476A5626CD99B3749AC1EE1E234FAC + +[9EA99ED5E27E35976E8266FACF5064CD] +GoodName=NHL Breakaway 98 (E) [o1][h1C] +CRC=29CE7692 71C58579 +RefMD5=46476A5626CD99B3749AC1EE1E234FAC + +[B62076FA1421B8E7FDEC2B4F8A910EA3] +GoodName=NHL Breakaway 98 (U) [!] +CRC=6DFDCDC3 4DE701C8 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[1D178B74A163711CA9C06327F3B709CF] +GoodName=NHL Breakaway 98 (U) [h1C] +CRC=6DFDCDC3 4DE701C8 +RefMD5=B62076FA1421B8E7FDEC2B4F8A910EA3 + +[BA863554222E503BAC7F01FA4888BE8A] +GoodName=NHL Breakaway 98 (U) [o1] +CRC=6DFDCDC3 4DE701C8 +RefMD5=B62076FA1421B8E7FDEC2B4F8A910EA3 + +[5DFB0200B6698CEF2BA2A1775BA252A8] +GoodName=NHL Breakaway 98 (U) [o1][h1C] +CRC=6DFDCDC3 4DE701C8 +RefMD5=B62076FA1421B8E7FDEC2B4F8A910EA3 + +[4BA95AA97ECFEE36051EBE0A9024EEE8] +GoodName=NHL Breakaway 99 (E) [!] +CRC=874621CB 0031C127 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[417AFE49BF73F3663C5F5F0AF897FC79] +GoodName=NHL Breakaway 99 (E) [b1] +CRC=874621CB 0031C127 +RefMD5=4BA95AA97ECFEE36051EBE0A9024EEE8 + +[AF1D07679014760B88923A4827658CAF] +GoodName=NHL Breakaway 99 (U) [!] +CRC=441768D0 7D73F24F +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[07C102E1ADF6190E05EF3C897090DFD3] +GoodName=NHL Breakaway 99 (U) [b1] +CRC=441768D0 7D73F24F +RefMD5=AF1D07679014760B88923A4827658CAF + +[1614E1C0BEBFAA0855DA9990EF859A68] +GoodName=NHL Breakaway 99 (U) [b2] +CRC=F0C5F320 B22773CA +RefMD5=AF1D07679014760B88923A4827658CAF + +[A61854CF27E536C8513174FAEF08DFCB] +GoodName=NHL Pro 99 (E) [!] +CRC=A9895CD9 7020016C +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[BCEE33DC37C872A188A72EEAF41369F4] +GoodName=NHL Pro 99 (E) [o1] +CRC=A9895CD9 7020016C +RefMD5=A61854CF27E536C8513174FAEF08DFCB + +[3E217E9C70608E56DA20FEAC9A458EFC] +GoodName=NUTS - Nintendo Ultra64 Test Suite by MooglyGuy (PD) +CRC=EFDAFEA4 E38D6A80 + +[B935B87F3DCCA8AEEB6A9365124846DC] +GoodName=Nagano Winter Olympics '98 (E) [!] +CRC=6D452016 713C09EE +Players=4 +SaveType=None +Mempak=Yes + +[D5CE3A477104213499FFEA3A0BCB1555] +GoodName=Nagano Winter Olympics '98 (E) [h1C] +CRC=6D452016 713C09EE +RefMD5=B935B87F3DCCA8AEEB6A9365124846DC + +[D4D046F74BE40E067875701751647178] +GoodName=Nagano Winter Olympics '98 (E) [o1] +CRC=6D452016 713C09EE +RefMD5=B935B87F3DCCA8AEEB6A9365124846DC + +[C17F78A103D99B21533F0C1566378EF6] +GoodName=Nagano Winter Olympics '98 (U) [!] +CRC=8D2BAE98 D73725BF +Players=4 +SaveType=None +Mempak=Yes + +[48782BC5728F38099B21E8B281ADC1CA] +GoodName=Nagano Winter Olympics '98 (U) [T+Ita_HRG] +CRC=8D2BAE98 D73725BF +RefMD5=C17F78A103D99B21533F0C1566378EF6 + +[63C2A327F7195FF43229738D315CF51C] +GoodName=Nagano Winter Olympics '98 (U) [b1] +CRC=8D2BAE98 D73725BF +RefMD5=C17F78A103D99B21533F0C1566378EF6 + +[2131A0AE317D243618A1E90E2153215C] +GoodName=Nagano Winter Olympics '98 (U) [b2] +CRC=8D2BAE98 D73725BF +RefMD5=C17F78A103D99B21533F0C1566378EF6 + +[96F8B3E6F6B91923462B02554025C403] +GoodName=Nagano Winter Olympics '98 (U) [h1C] +CRC=8D2BAE98 D73725BF +RefMD5=C17F78A103D99B21533F0C1566378EF6 + +[C9F607002F051F087F4FD68B8B77B4D3] +GoodName=Nagano Winter Olympics '98 (U) [o1] +CRC=8D2BAE98 D73725BF +RefMD5=C17F78A103D99B21533F0C1566378EF6 + +[A8CDD4C61604B9C279861289ED7C4542] +GoodName=Nagano Winter Olympics '98 (U) [o2] +CRC=8D2BAE98 D73725BF +RefMD5=C17F78A103D99B21533F0C1566378EF6 + +[E61251D2819E3BF3A9C0B95329F60F70] +GoodName=Namco Museum 64 (U) [!] +CRC=5129B6DA 9DEF3C8C +Players=2 +SaveType=None +Mempak=Yes + +[EAD417FF24EAB32E2BF45CEA9200D425] +GoodName=Namco Museum 64 (U) [f1] (PAL) +CRC=A896AB1D 27E73688 +RefMD5=E61251D2819E3BF3A9C0B95329F60F70 + +[1F455908263C2745E4100C0319B0F4C0] +GoodName=Namco Museum 64 (U) [o1] +CRC=5129B6DA 9DEF3C8C +RefMD5=E61251D2819E3BF3A9C0B95329F60F70 + +[98C0A62FE977A8202F558E5F2E2A5A60] +GoodName=Namco Museum 64 (U) [o1][f1] (PAL) +CRC=AE21569D 5A5BC572 +RefMD5=E61251D2819E3BF3A9C0B95329F60F70 + +[E001B32D05D36EDB7E8A99B7C7E4C789] +GoodName=Namco Museum 64 (U) [t1] +CRC=A864A921 99082CD0 +RefMD5=E61251D2819E3BF3A9C0B95329F60F70 + +[CB7C26C00AB065F372DDA9950260BCBA] +GoodName=Namp64 - N64 MP3-Player by Obsidian (PD) +CRC=C4855DA2 83BBA182 + +[5E1940CA1236A76E8F2D15DE0414AE55] +GoodName=Neon Genesis Evangelion (J) [!] +CRC=147E0EDB 36C5B12C +Players=1 +SaveType=Eeprom 16KB +Rumble=Yes + +[34F5F402064F76B375771EBF80DBE734] +GoodName=Neon Genesis Evangelion (J) [b1] +CRC=147E0EDB 36C5B12C +RefMD5=5E1940CA1236A76E8F2D15DE0414AE55 + +[4374A8342E612951148136194053967C] +GoodName=Neon Genesis Evangelion (J) [b2] +CRC=147E0EDB 36C5B12C +RefMD5=5E1940CA1236A76E8F2D15DE0414AE55 + +[DB2A3682451F1A6CEAFBF44792D4A5A7] +GoodName=Neon Genesis Evangelion (J) [b3] +CRC=147E0EDB 36C5B12C +RefMD5=5E1940CA1236A76E8F2D15DE0414AE55 + +[7FE719DDE2CF1C9227BB9650AFA21A4B] +GoodName=Neon Genesis Evangelion (J) [f1] (PAL) +CRC=AC000A2B 38E3A55C +RefMD5=5E1940CA1236A76E8F2D15DE0414AE55 + +[4723E4599E37DB86B9BBD2FD18BFDB8F] +GoodName=Neon64 First Public Beta Release V2 by Halley's Comet Software (PD) +CRC=3B18F6F9 8C4BE567 + +[B7A1D8B4BD19C710E4B9DAAC5590E301] +GoodName=Neon64 First Public Beta Release V3 by Halley's Comet Software (PD) +CRC=4F707583 2D6326AA + +[E062DD1E3C8B7A266FA018C6FBC17455] +GoodName=Neon64 First Public Beta Release by Halley's Comet Software (PD) +CRC=3B18F4F7 82BFB2B3 + +[5E4DABADB17439A1F2122F5E2C141FD1] +GoodName=Neon64 V1.0 by Halley's Comet Software (PD) +CRC=E87D098B 4C70341C + +[83CB0CE82555FE733A121C052BDF3662] +GoodName=Neon64 V1.1 by Halley's Comet Software (PD) [o2] +CRC=AE809DD0 0A99B360 + +[CA02C44E41D6A7CD51785DB0981C54C7] +GoodName=Neon64 V1.1 by Halley's Comet Software (PD) +CRC=ED42A2D4 7A71CD91 + +[08EBE38D2EA9BCACED94805BBBCE7192] +GoodName=Neon64 V1.2 by Halley's Comet Software (PD) [o1] +CRC=7040B082 1BE98D03 + +[D54FB5A78A2A9189D01ACF20A6043F4B] +GoodName=Neon64 V1.2 by Halley's Comet Software (PD) +CRC=ED42A2D4 7A71CD91 + +[43475AA0D793806C23D8645F49F6656D] +GoodName=Neon64 V1.2a by Halley's Comet Software (PD) [b1] +CRC=A9F7BB48 D63C5F56 + +[38D04A1C192D591940437B6BAF628119] +GoodName=Neon64 V1.2a by Halley's Comet Software (PD) [o1] +CRC=5AAD4E36 6625D1D2 + +[9FFA642B02C27D8E01EAB17B0F0F4251] +GoodName=Neon64 V1.2a by Halley's Comet Software (PD) +CRC=ED42A2D4 7A71CD91 + +[C4ECFEC66ECEEA23F39632AB6753300F] +GoodName=New Tetris, The (E) [!] +CRC=E61CFF0A CE1C0D71 +Players=4 +SaveType=SRAM +Mempak=Yes + +[7A28179B00734C9AA0F0609FAFAAFD5F] +GoodName=New Tetris, The (U) [!] +CRC=2153143F 992D6351 +Players=4 +SaveType=SRAM +Mempak=Yes + +[0B13983A634732FDE9D2D638C0A14C51] +GoodName=New Tetris, The (U) [f1] (PAL) +CRC=208A0427 DF465260 +RefMD5=7A28179B00734C9AA0F0609FAFAAFD5F + +[99B35D7833DAEBCE199CDCC240E29FDF] +GoodName=New Tetris, The (U) [f2] (PAL) +CRC=208A0437 0E53FF5F +RefMD5=7A28179B00734C9AA0F0609FAFAAFD5F + +[E2304DF5FF6B40E74FD5BF62655D3E57] +GoodName=New Tetris, The (U) [f3] (PAL) +CRC=43D67345 A60D5D3D +RefMD5=7A28179B00734C9AA0F0609FAFAAFD5F + +[4116CF435DB315A2481AF8D1E9352FEB] +GoodName=Nightmare Creatures (U) [!] +CRC=2857674D CC4337DA +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes + +[60A2CFF1515D4C7902DDE32A6E01D411] +GoodName=Nightmare Creatures (U) [b1] +CRC=2857674D CC4337DA +RefMD5=4116CF435DB315A2481AF8D1E9352FEB + +[68B478C274812450369DBF153CAD185D] +GoodName=Nightmare Creatures (U) [b2] +CRC=2857674D CC4337DA +RefMD5=4116CF435DB315A2481AF8D1E9352FEB + +[FF02FE6A6FE7F6C31BCA6962E53A63CA] +GoodName=Nightmare Creatures (U) [t1] +CRC=AFDCF850 5CCD80DE +RefMD5=4116CF435DB315A2481AF8D1E9352FEB + +[49198056DDEBB41B1A820A09289A2E3F] +GoodName=Nightmare Creatures (U) [t2] +CRC=AFDCF850 5CCD80DE +RefMD5=4116CF435DB315A2481AF8D1E9352FEB + +[B04957D052EF850C5EDECE69DB7377B3] +GoodName=Nintama Rantarou 64 Game Gallery (J) [!] +CRC=CD3C3CDF 317793FA +Players=4 +CountPerOp=1 + +[66DB457B130D31A286A23D6E4DD9726E] +GoodName=Nintendo All-Star! Dairantou Smash Brothers (J) [!] +CRC=67D20729 F696774C +Status=3 +Players=4 +SaveType=SRAM +Rumble=Yes +CountPerOp=1 + +[B2DF29627E0219A9C14605F46803C94C] +GoodName=Nintendo All-Star! Dairantou Smash Brothers (J) [b1] +CRC=67D20729 F696774C +RefMD5=66DB457B130D31A286A23D6E4DD9726E + +[57CBADB75429AAFC0D7040DE69DC8D70] +GoodName=Nintendo All-Star! Dairantou Smash Brothers (J) [b2] +CRC=88FFAB7D 298294A2 +RefMD5=66DB457B130D31A286A23D6E4DD9726E + +[3D78B907657918C8C58EA002FEEE1D0F] +GoodName=Nintendo All-Star! Dairantou Smash Brothers (J) [b3] +CRC=67D20729 F696774C +RefMD5=66DB457B130D31A286A23D6E4DD9726E + +[4CFAED7DAD4EE592572964BA03D8C07E] +GoodName=Nintendo All-Star! Dairantou Smash Brothers (J) [f1] +CRC=308BC746 A229B775 +RefMD5=66DB457B130D31A286A23D6E4DD9726E + +[9C0E454CFFE65835AED12B39A8D9D6EC] +GoodName=Nintendo All-Star! Dairantou Smash Brothers (J) [f2] +CRC=88FFAB7D 298294A2 +RefMD5=66DB457B130D31A286A23D6E4DD9726E + +[9A27D420B43A908ECF4F28F859E1C541] +GoodName=Nintendo All-Star! Dairantou Smash Brothers (J) [f3] +CRC=88FFAB7D 298294A2 +RefMD5=66DB457B130D31A286A23D6E4DD9726E + +[053C515BEBE73391B4479A90A8EE93F9] +GoodName=Nintendo All-Star! Dairantou Smash Brothers (J) [f4] (PAL) +CRC=58886DD0 AD93BCB1 +RefMD5=66DB457B130D31A286A23D6E4DD9726E + +[0AEE21A365F9450C258A59556F77EDB8] +GoodName=Nintendo Family by CALi (PD) +CRC=60E528A6 9500D4D3 + +[C10B51EEAC9F520419F23F95228C719A] +GoodName=Nintendo On My Mind Demo by Kid Stardust (PD) +CRC=6B2AFCC7 EEB27A34 + +[F79F17353DC5683AB60257462BE9D2FD] +GoodName=Nintendo WideBoy 64 by SonCrap (PD) +CRC=D1C6C55D F010EF52 + +[9EB9A0A45C2DD35DCB5A4A8A7FC4B151] +GoodName=Nintro64 Demo by Lem (POM '98) (PD) [b1] +CRC=4E01B4A6 C884D085 + +[497D1E0677395A921B6006BBF41EED04] +GoodName=Nintro64 Demo by Lem (POM '98) (PD) +CRC=4E01B4A6 C884D085 + +[898362D1F6E207818E8CDF88225017B6] +GoodName=NuFan Demo by Kid Stardust (PD) [b1] +CRC=FA7D3935 97AC54FC + +[9ED82C5E9B6BF204276B434C8B0F6892] +GoodName=NuFan Demo by Kid Stardust (PD) +CRC=FA7D3935 97AC54FC + +[710BA49EBD5C9A2B26653FAE93BD667A] +GoodName=Nuclear Strike 64 (E) (M2) [!] +CRC=8A97A197 272DF6C1 +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[59C28E02BAF4065051C63EA51736892A] +GoodName=Nuclear Strike 64 (E) (M2) [h1C] +CRC=8A97A197 272DF6C1 +RefMD5=710BA49EBD5C9A2B26653FAE93BD667A + +[D43C2E1938534363E56A22413B91D051] +GoodName=Nuclear Strike 64 (G) [!] +CRC=8F50B845 D729D22F +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[FFC584040D0D052FBAB4CB6C19245449] +GoodName=Nuclear Strike 64 (U) [!] +CRC=4998DDBB F7B7AEBC +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[76C8EFDD11F6D2E553055B801A022653] +GoodName=Nuclear Strike 64 (U) [b1] +CRC=4998DDBB F7B7AEBC +RefMD5=FFC584040D0D052FBAB4CB6C19245449 + +[A3134DAE771ADDB83191422615DF8551] +GoodName=Nuclear Strike 64 (U) [f1] (PAL) +CRC=E6B339F6 22AE6901 +RefMD5=FFC584040D0D052FBAB4CB6C19245449 + +[2B7370E6880F83C808A2CB9E7F33DC46] +GoodName=Nuclear Strike 64 (U) [t1] +CRC=FE5DC5D4 E1815BE5 +RefMD5=FFC584040D0D052FBAB4CB6C19245449 + +[50C10082D0C077FDB5658EF5A6E3F54F] +GoodName=Nushi Tsuri 64 (J) (V1.0) [!] +CRC=D83BB920 CC406416 +Players=1 +Mempak=Yes +Rumble=Yes +Transferpak=Yes +CountPerOp=1 + +[7412417C50A42427637575A3CD2E652E] +GoodName=Nushi Tsuri 64 (J) (V1.0) [b1] +CRC=24081000 AD880000 +RefMD5=50C10082D0C077FDB5658EF5A6E3F54F + +[EEFD695B00354C5199DF348ECF404A0F] +GoodName=Nushi Tsuri 64 (J) (V1.0) [b2] +CRC=9ADD5DE5 451F0A65 +RefMD5=50C10082D0C077FDB5658EF5A6E3F54F + +[C187BD285BA0E2D0EF5CFFEE44B367EE] +GoodName=Nushi Tsuri 64 (J) (V1.0) [b3] +CRC=D83BB920 CC406416 +RefMD5=50C10082D0C077FDB5658EF5A6E3F54F + +[0B281D478B1B4FF9329B45EEB80D53F2] +GoodName=Nushi Tsuri 64 (J) (V1.0) [b4] +CRC=D83BB920 CC406416 +RefMD5=50C10082D0C077FDB5658EF5A6E3F54F + +[FABCB3078EDE955C04A00479EE11C43F] +GoodName=Nushi Tsuri 64 (J) (V1.0) [b5] +CRC=49D83BB9 20CC4064 +RefMD5=50C10082D0C077FDB5658EF5A6E3F54F + +[D2AF6993E4D657D00520C2CCE741480E] +GoodName=Nushi Tsuri 64 (J) (V1.1) [!] +CRC=C5F1DE79 5D4BEB6E +Players=1 +Mempak=Yes +Rumble=Yes +Transferpak=Yes +CountPerOp=1 + +[828E0C399C0AA7E3B047859F4FAD3550] +GoodName=Nushi Tsuri 64 - Shiokaze ni Notte (J) [b1] +CRC=5B9A9618 4B86828E +RefMD5=EEB69597E42E2F5D2914070ACF161B4F + +[A366BCBF8FF44D23A9450ECD8C71223C] +GoodName=Nushi Tsuri 64 - Shiokaze ni Notte (J) [b2] +CRC=5B9B1618 1B43C649 +RefMD5=EEB69597E42E2F5D2914070ACF161B4F + +[EEB69597E42E2F5D2914070ACF161B4F] +GoodName=Nushi Tsuri 64 - Shiokaze ni Notte (J) [!] +CRC=5B9B1618 1B43C649 +Players=1 +Rumble=Yes +Transferpak=Yes +CountPerOp=1 + +[E2FB4F16A039A0E302D28ACA94D5D928] +GoodName=O.D.T. (E) (M5) [!] +CRC=E86415A6 98395B53 +Players=1 +Mempak=Yes +Rumble=Yes + +[4116E492168AAFFF1BD3100C7B0AA28F] +GoodName=O.D.T. (U) (M3) [!] +CRC=2655BB70 667D9925 +Players=1 +Mempak=Yes +Rumble=Yes + +[09BA01C6EC8B178A27FBEE3A9DEE8EB6] +GoodName=Oerjan Intro by Oerjan (POM '99) (PD) +CRC=7F2D025D 2B7DA4AD + +[E96FECBA52905DB14ADDAD7CFD61091F] +GoodName=Off Road Challenge (E) [!] +CRC=812289D0 C2E53296 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[F30DFECB19DBD82A2FD334A8A37B8D38] +GoodName=Off Road Challenge (E) [b1] +CRC=24081000 AD880000 +RefMD5=E96FECBA52905DB14ADDAD7CFD61091F + +[1538A4235FDED9D65B98C25EDF6F9C0E] +GoodName=Off Road Challenge (E) [b2] +CRC=812289D0 C2E53296 +RefMD5=E96FECBA52905DB14ADDAD7CFD61091F + +[AF7083FC0ABCFD5A2C6A5E971453D831] +GoodName=Off Road Challenge (U) [!] +CRC=319093EC 0FC209EF +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[DC34F5AA26488352B4D025EDBF47FE39] +GoodName=Off Road Challenge (U) [b1] +CRC=319093EC 0FC209EF +RefMD5=AF7083FC0ABCFD5A2C6A5E971453D831 + +[6F378FFB873C217675F4CDD00A0318D4] +GoodName=Off Road Challenge (U) [b2] +CRC=319093EC 0FC209EF +RefMD5=AF7083FC0ABCFD5A2C6A5E971453D831 + +[D3BDAA50D6C0EFFF9D696C521B704376] +GoodName=Off Road Challenge (U) [t1] +CRC=698FE5E8 1D57B278 +RefMD5=AF7083FC0ABCFD5A2C6A5E971453D831 + +[A45C39767D33AC21956A3D4E6C03CFA1] +GoodName=Ogre Battle 64 - Person of Lordly Caliber (J) (V1.1) [!] +CRC=0375CF67 56A93FAA +Players=1 +SaveType=SRAM + +[55CD360F12BE8063C9E7B6F59F268170 ] +GoodName=Ogre Battle 64 - Person of Lordly Caliber (J) (V1.1) (VC) [!] +CRC=0375CF67 56A93FAA +Players=1 +SaveType=SRAM + +[A3F64D34614A0B01B6A49AE4031ACBDF] +GoodName=Ogre Battle 64 - Person of Lordly Caliber (J) (V1.1) [b1] +CRC=0375CF67 56A93FAA +RefMD5=A45C39767D33AC21956A3D4E6C03CFA1 + +[5468A2AC2E93AD3F49E9B271C8341CAC] +GoodName=Ogre Battle 64 - Person of Lordly Caliber (J) (V1.1) [b1][o1] +CRC=0375CF67 56A93FAA +RefMD5=A45C39767D33AC21956A3D4E6C03CFA1 + +[7AF70073E7CFD8945E087A7FFD6D8348] +GoodName=Ogre Battle 64 - Person of Lordly Caliber (J) (V1.1) [b2] +CRC=0375CF67 56A93FAA +RefMD5=A45C39767D33AC21956A3D4E6C03CFA1 + +[F666E020218392E52662FDDFA1EA4F21] +GoodName=Ogre Battle 64 - Person of Lordly Caliber (U) (V1.0) [!] +CRC=E6419BC5 69011DE3 +Players=1 +SaveType=SRAM +Mempak=Yes + +[EBB4B4D2808DF427AAA3085A41B8A954] +GoodName=Ogre Battle 64 - Person of Lordly Caliber (U) (V1.1) [!] +CRC=0ADAECA7 B17F9795 +Players=1 +SaveType=SRAM +Mempak=Yes + +[465DFD27DDAB4F5488F4DADC09B7F938] +GoodName=Olympic Hockey Nagano '98 (E) (M4) [!] +CRC=AE2D3A35 24F0D41A +Players=4 +SaveType=None +Mempak=Yes + +[02AA0C059EC36145927353C8E617AA41] +GoodName=Olympic Hockey Nagano '98 (E) (M4) [h1C] +CRC=AE2D3A35 24F0D41A +RefMD5=465DFD27DDAB4F5488F4DADC09B7F938 + +[8A964671C5A4F4FC62787F1F25EDD70D] +GoodName=Olympic Hockey Nagano '98 (J) [!] +CRC=90F43037 5C5370F5 +Players=4 +SaveType=None +Mempak=Yes + +[9C99C6D9EA98A960056C531CB78EB35B] +GoodName=Olympic Hockey Nagano '98 (U) [!] +CRC=7EC22587 EF1AE323 +Players=4 +SaveType=None +Mempak=Yes + +[8F9810383B86E86EC447F65D47CA74A7] +GoodName=Olympic Hockey Nagano '98 (U) [T+Ita_cattivik66] +CRC=7EC22587 EF1AE323 +RefMD5=9C99C6D9EA98A960056C531CB78EB35B + +[7BD97D75D09E38996F82C6190780D447] +GoodName=Olympic Hockey Nagano '98 (U) [b1] +CRC=7EC22587 EF1AE323 +RefMD5=9C99C6D9EA98A960056C531CB78EB35B + +[3A314CE9388E4178FD6FC9C74D5E7137] +GoodName=Olympic Hockey Nagano '98 (U) [b2] +CRC=7EC22587 EF1AE323 +RefMD5=9C99C6D9EA98A960056C531CB78EB35B + +[CFCB20EACFCEAA43FDDBE05FB0D170D1] +GoodName=Olympic Hockey Nagano '98 (U) [b3] +CRC=7EC22587 EF1AE323 +RefMD5=9C99C6D9EA98A960056C531CB78EB35B + +[3E973B5BBEF8B24A4C4D7C326955E71F] +GoodName=Olympic Hockey Nagano '98 (U) [h1C] +CRC=7EC22587 EF1AE323 +RefMD5=9C99C6D9EA98A960056C531CB78EB35B + +[3796829F54958CE103DCF5E3E8EB80B4] +GoodName=Onegai Monsters (J) [!] +CRC=DC649466 572FF0D9 +Players=4 +Mempak=Yes + +[B19805B3DFECF85FEA7E04614362DC28] +GoodName=Onegai Monsters (J) [b1] +CRC=DC649466 572FF0D9 +RefMD5=3796829F54958CE103DCF5E3E8EB80B4 + +[91CF1982F309BD73822165087DAD4371] +GoodName=Operation WinBack (E) (M5) [!] +CRC=D5898CAF 6007B65B +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[F2DF4577D3749345F93BA0606BECA8DD] +GoodName=PC-Engine 64 (POM '99) (PD) [t1] +CRC=4B548E10 BB510803 + +[70FD44B722B55956BE86B660F153713D] +GoodName=PC-Engine 64 (POM '99) (PD) +CRC=9118F1B8 987DAC8C + +[52F4F3320607F3E8DD1A16A2F1BFBDB0] +GoodName=PD Ultraman Battle Collection 64 (J) [!] +CRC=F468118C E32EE44E +Players=2 +SaveType=Eeprom 16KB +Mempak=Yes +Transferpak=Yes + +[4FD424DF60F80EE7E362A9572049BA11] +GoodName=PD Ultraman Battle Collection 64 (J) [b1] +CRC=F468118C E32EE44E +RefMD5=52F4F3320607F3E8DD1A16A2F1BFBDB0 + +[2755152E6168516F2224ADC6737B96F0] +GoodName=PD Ultraman Battle Collection 64 (J) [f1] (PAL) +CRC=37B52113 3A77A655 +RefMD5=52F4F3320607F3E8DD1A16A2F1BFBDB0 + +[826AE85B4E74354EE378E8DC2AD33271] +GoodName=PD Ultraman Battle Collection 64 (J) [f2] (PAL) +CRC=170D4973 8FA23F51 +RefMD5=52F4F3320607F3E8DD1A16A2F1BFBDB0 + +[0112FFAADA116D172ABCE136E9043A93] +GoodName=PGA European Tour (E) (M5) [!] +CRC=EE08C602 6BC2D5A6 +Players=4 +SaveType=Eeprom 4KB + +[2F6B0ACB7270F78C972F5E6D4C75B02B] +GoodName=PGA European Tour (E) (M5) [f1] (NTSC) +CRC=5243B915 BE7743B1 +RefMD5=0112FFAADA116D172ABCE136E9043A93 + +[7DBA0D5D4279274AF07B0EF3EC3A84AD] +GoodName=PGA European Tour (E) (M5) [f2] (NTSC) +CRC=76515D11 42BF7875 +RefMD5=0112FFAADA116D172ABCE136E9043A93 + +[617CECA1D2BEFFCE943EF832326898BF] +GoodName=PGA European Tour (U) [!] +CRC=B54CE881 BCCB6126 +Players=4 +SaveType=Eeprom 4KB + +[8E79EC6D9F8DB1C50100860BF4437462] +GoodName=POMbaer Demo by Kid Stardust (POM '99) (PD) +CRC=9D63C653 C26B460F + +[0BBE17EC2271DC293F1D2F4A7B0D61D4] +GoodName=POMolizer Demo by Renderman (POM '99) (PD) +CRC=EDAFD3C0 39EF3599 + +[D60046C23400BFEBD5B051F89E7F2F07] +GoodName=Pachinko 365 Nichi (J) [!] +CRC=74554B3B F4AEBCB5 +Players=1 +Mempak=Yes + +[2002438491F94C468CB487032AC4AA33] +GoodName=Pachinko 365 Nichi (J) [b1] +CRC=74554B3B F4AEBCB5 +RefMD5=D60046C23400BFEBD5B051F89E7F2F07 + +[F38ECA581BF6944EA35E3A816AD472DF] +GoodName=Pachinko 365 Nichi (J) [b2] +CRC=74554B3B F4AEBCB5 +RefMD5=D60046C23400BFEBD5B051F89E7F2F07 + +[FE38BB1EAA1C74BAF01847BDE64E7F9D] +GoodName=Pamela Demo (PD) +CRC=26AD85C5 F908A36B + +[3AAF74D7E6D560C9CB1331209AD00F22] +GoodName=Pamela Demo - Resized (PD) +CRC=26AD85C5 F908A36B + +[8F8F50AB00C4089AE32C6B9FEFD69543] +GoodName=Paper Mario (Ch) (iQue) [!] + +[C4D652425AA4F2FC1D12564DF01F8A04] +GoodName=Paper Mario (Ch) (V2) (iQue) (Manual) [!] + +[D9597922207298A87FA46878C017E6DA] +GoodName=Paper Mario (Ch) (V4) (iQue) (Manual) [!] + +[A9BE6A493A680642D840F859A65816CA] +GoodName=Paper Mario (E) (M4) [!] +CRC=19AB29AF C71BCD28 +Status=2 +Players=1 +SaveType=Flash RAM +Rumble=Yes +CountPerOp=1 + +[A722F8161FF489943191330BF8416496] +GoodName=Paper Mario (U) [!] +CRC=65EEE53A ED7D733C +Status=2 +Players=1 +SaveType=Flash RAM +Rumble=Yes +CountPerOp=1 + +[8595BA0A0D2EA73944228BDED4A969AD] +GoodName=Paper Mario (U) [T+Chi] +CRC=85F5A08A EAC7053E +RefMD5=A722F8161FF489943191330BF8416496 + +[B7F2EB7989C9C00096655D087D72EC51] +GoodName=Paperboy (E) [!] +CRC=AC976B38 C3A9C97A +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes + +[C4CBCB54B010A5A71FE5CAA391E5C25F] +GoodName=Paperboy (U) [!] +CRC=3E198D9E F2E1267E +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes + +[12827E2EF6EB1FF0F8AA494E671C3094] +GoodName=Paperboy (U) [f1] (PAL) +CRC=8952E61E AA89984C +RefMD5=C4CBCB54B010A5A71FE5CAA391E5C25F + +[5DF3D21223F0DAFD0417998E9C1E7065] +GoodName=Paperboy (U) [hI] +CRC=89529B12 0853ED3B +RefMD5=C4CBCB54B010A5A71FE5CAA391E5C25F + +[0451768553AB8CDD6C9CA37514E6C339] +GoodName=Paperboy (U) [hI][f1] (PAL) +CRC=8F00E51E 030C92C8 +RefMD5=C4CBCB54B010A5A71FE5CAA391E5C25F + +[1F72E506250B16726E2C5A629CAE8E0F] +GoodName=Paperboy (U) [hI][t1] +CRC=8632071E 637E1042 +RefMD5=C4CBCB54B010A5A71FE5CAA391E5C25F + +[DF2A6A2446E8E01375ADE872A8F93366] +GoodName=Paperboy (U) [t1] +CRC=8632071E 637E1042 +RefMD5=C4CBCB54B010A5A71FE5CAA391E5C25F + +[D78E10C6B3E98F3B32FE0F23ED72DB42] +GoodName=Parlor! Pro 64 - Pachinko Jikki Simulation Game (J) [!] +CRC=CFE2CB31 4D6B1E1D +Players=1 +SaveType=Eeprom 16KB +Mempak=Yes + +[6DF573EE08C4577BBBF117B813D93B19] +GoodName=Pause Demo by RedboX (PD) +CRC=7D1727F1 6C6B83EB + +[20DA62ECE553EDE84D02283174BECC8F] +GoodName=Penny Racers (E) [!] +CRC=C83CEB83 FDC56219 +Status=3 +Players=4 +SaveType=Eeprom 4KB +Mempak=Yes + +[B6DF5A75CED54DFEE0E29BCE9ABD0AAF] +GoodName=Penny Racers (E) [h1C] +CRC=C83CEB83 FDC56219 +RefMD5=20DA62ECE553EDE84D02283174BECC8F + +[6AE97EC4933A13C153A281DC8B68A0D9] +GoodName=Penny Racers (E) [h2C] +CRC=C83CEB83 FDC56219 +RefMD5=20DA62ECE553EDE84D02283174BECC8F + +[518B14054A667A3B9E0B72D3BF784E41] +GoodName=Penny Racers (U) [!] +CRC=73ABB1FB 9CCA6093 +Players=4 +Status=3 +SaveType=Eeprom 4KB +Mempak=Yes + +[26F033C7716A10755A3D22C62ACF6851] +GoodName=Penny Racers (U) [hI] +CRC=AB5E61C8 A2FA7596 +RefMD5=518B14054A667A3B9E0B72D3BF784E41 + +[D9B5CD305D228424891CE38E71BC9213] +GoodName=Perfect Dark (E) (M5) [!] +CRC=E4B08007 A602FF33 +SaveType=Eeprom 16KB +Players=4 +Mempak=Yes +Rumble=Yes +Transferpak=Yes + +[9E6D80933B63B183CCBD8B5F6543DCAD] +GoodName=Perfect Dark (E) (M5) [b1] +CRC=E4B08007 A602FF33 +RefMD5=D9B5CD305D228424891CE38E71BC9213 + +[AD2DE210A3455BA5EC541F0C78D91444] +GoodName=Perfect Dark (E) (Debug) (2000-04-26) [!] +CRC=F9864452 890A5EA3 +SaveType=Eeprom 16KB +Players=4 +Mempak=Yes +Rumble=Yes +Transferpak=Yes + +[538D2B75945EAE069B29C46193E74790] +GoodName=Perfect Dark (J) [!] +CRC=96747EB4 104BB243 +SaveType=Eeprom 16KB +Players=4 +Mempak=Yes +Rumble=Yes +Transferpak=Yes + +[7F4171B0C8D17815BE37913F535E4E93] +GoodName=Perfect Dark (U) (V1.0) [!] +CRC=DDF460CC 3CA634C0 +SaveType=Eeprom 16KB +Players=4 +Mempak=Yes +Rumble=Yes +Transferpak=Yes + +[BF167523E079C57DCCA880A6F38889F2] +GoodName=Perfect Dark (U) (V1.0) [f1] (PAL) +CRC=65264217 7FB64F7F +RefMD5=7F4171B0C8D17815BE37913F535E4E93 + +[E03B088B6AC9E0080440EFED07C1E40F] +GoodName=Perfect Dark (U) (V1.1) [!] +CRC=41F2B98F B458B466 +SaveType=Eeprom 16KB +Players=4 +Mempak=Yes +Rumble=Yes +Transferpak=Yes + +[AA93F4DF16FCEADA399A749F5AD2F273] +GoodName=Perfect Dark (U) (Debug) (2000-03-22) [!] +CRC=2CE75AEF E16825BC +SaveType=Eeprom 16KB +Players=4 +Mempak=Yes +Rumble=Yes +Transferpak=Yes + +[5D72155E00Bf2CAB41B0F4A2f2E09C61] +GoodName=Perfect Dark Plus +CRC=FB453D58 AD565422 +RefMD5=E03B088B6AC9E0080440EFED07C1E40F + +[E0BCB2758EDF0AC6AB7DB36D98E1E57C] +GoodName=Pikachu Genki Dechu (J) [!] +CRC=3F245305 FC0B74AA +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes +AiDmaModifier=88 + +[D0AE6C07AC0481EBA5FF9CE798A69574] +GoodName=Pikachu Genki Dechu (J) [b1] +CRC=3F245305 FC0B74AA +RefMD5=E0BCB2758EDF0AC6AB7DB36D98E1E57C + +[3FCD4969F9A080BD2BCB913EC5D7A3BD] +GoodName=Pilotwings 64 (E) (M3) [!] +CRC=1AA05AD5 46F52D80 +Players=1 +SaveType=Eeprom 4KB +CountPerOp=3 + +[F21E2A3A05ACF49586F32DCE5C449FE4] +GoodName=Pilotwings 64 (E) (M3) [b1] +CRC=1AA05AD5 46F52D80 +RefMD5=3FCD4969F9A080BD2BCB913EC5D7A3BD + +[987682CC63777221B938CC465607BD8C] +GoodName=Pilotwings 64 (E) (M3) [b2] +CRC=1AA05AD5 46F52D80 +RefMD5=3FCD4969F9A080BD2BCB913EC5D7A3BD + +[99FD0E1CBA30C18C869F2DE98678CD16] +GoodName=Pilotwings 64 (E) (M3) [h1C] +CRC=1AA05AD5 46F52D80 +RefMD5=3FCD4969F9A080BD2BCB913EC5D7A3BD + +[E8E6EC0692009009F5DCA6827B21F59A] +GoodName=Pilotwings 64 (J) [!] +CRC=09CC4801 E42EE491 +Players=1 +SaveType=Eeprom 4KB +CountPerOp=3 + +[2740F1B89CE7D78A5D31CF60C97A0C11] +GoodName=Pilotwings 64 (J) [b1] +CRC=09CC4801 E42EE491 +RefMD5=E8E6EC0692009009F5DCA6827B21F59A + +[8B346182730CEAFFE5E2CCF6D223C5EF] +GoodName=Pilotwings 64 (U) [!] +CRC=C851961C 78FCAAFA +Players=1 +SaveType=Eeprom 4KB +CountPerOp=3 + +[E28F8F19E56CC6C7A0F3A3286AEB60C1] +GoodName=Pilotwings 64 (U) [h1C] +CRC=C851961C 78FCAAFA +RefMD5=8B346182730CEAFFE5E2CCF6D223C5EF + +[F69DE158BC76416B4C6C4704B15B6EB0] +GoodName=Pilotwings 64 (U) [t1] +CRC=70478A35 F9897402 +RefMD5=8B346182730CEAFFE5E2CCF6D223C5EF + +[BE9E0C9D509AAB0C72F7788D6BE3B443] +GoodName=Pip's Pong by Mr. Pips (PD) [b1] +CRC=D072CFE7 CE134788 + +[E821B540A91B7BF088E52ABC02A5CC9A] +GoodName=Pip's Pong by Mr. Pips (PD) +CRC=D072CFE7 CE134788 + +[63CBABEF9069FE3375A7726C89E9E25D] +GoodName=Pip's Porn Pack 1 by Mr. Pips (PD) +CRC=D851B920 F3D6C0CE + +[3DF1646CC28C04133B3CB5EB143AE016] +GoodName=Pip's Porn Pack 2 by Mr. Pips (POM '99) (PD) +CRC=BF9D0FB0 981C22D1 + +[547CF20308F2CE2CE5B5310A5E555113] +GoodName=Pip's Porn Pack 3 by Mr. Pips (PD) +CRC=EA2A6A75 52B2C00F + +[5D144D323785818A9BD5C667A5567BBD] +GoodName=Pip's RPGs Beta 12 by Mr. Pips (PD) +CRC=3CB8AAB8 05C8E573 + +[EFBCB657A3B05B5CB080FD628B852BD0] +GoodName=Pip's RPGs Beta 14 by Mr. Pips (PD) +CRC=56563C89 C803F77B + +[C6FAAC42045BE1AF769EC52CEA6DED52] +GoodName=Pip's RPGs Beta 15 by Mr. Pips (PD) +CRC=AFBBB9D5 8EE82954 + +[10A28DF32D06B7D3D9B14091AC9D2E14] +GoodName=Pip's RPGs Beta 2 by Mr. Pips (PD) +CRC=DAD7F751 8B6322F0 + +[6402498E891455FFB86C95AD8ABB87F6] +GoodName=Pip's RPGs Beta 3 by Mr. Pips (PD) +CRC=C830954A 29E257FC + +[10E62952244834E0B52AF32898DE8D9F] +GoodName=Pip's RPGs Beta 6 by Mr. Pips (PD) +CRC=7194B65B 9DE67E7D + +[35FAB2CC64E0E808EB629A25542C7326] +GoodName=Pip's RPGs Beta 7 by Mr. Pips (PD) +CRC=DB363DDA 50C1C2A5 + +[9E35B55606BDF4C77A1E817CE503A951] +GoodName=Pip's RPGs Beta x (PD) [a1] +CRC=668FA336 2C67F3AC + +[F8D6C5ABA62FC302C2848C53104E2683] +GoodName=Pip's RPGs Beta x (PD) +CRC=BB787C13 78C1605D + +[45CDCBCB7159EBAE1ED4D7AAE70749E0] +GoodName=Pip's Tic Tak Toe by Mark Pips (PD) +CRC=6459533B 7E22B56C + +[99D711AB6DFD36121E5C23C1DBA78C01] +GoodName=Pip's World Game 1 by Mr. Pips (PD) [b1] +CRC=762C75D1 AA09C759 + +[4D28DDB5B93EA302EE9F27805DE1B46F] +GoodName=Pip's World Game 1 by Mr. Pips (PD) +CRC=762C75D1 AA09C759 + +[BBF5060E64BD0201954E65BD281EC486] +GoodName=Pip's World Game 2 by Mr. Pips (PD) [b1] +CRC=FC051819 A46A48F6 + +[9358AA90887FC31C45BC2B849C37D6A0] +GoodName=Pip's World Game 2 by Mr. Pips (PD) +CRC=FC051819 A46A48F6 + +[9C1B750A2F9DFC53361F72F4BFB647A7] +GoodName=Pipendo by Mr. Pips (PD) +CRC=45627CED 28005F9C + +[1D7CFC7CDB5A0E1B69B1DC2E58A4F192] +GoodName=Planet Console Intro (PD) +CRC=1077590A B537FDA2 + +[83B75800690AF27800DF362697E5205E] +GoodName=Plasma Demo (PD) [a1] +CRC=7D1727F1 6C6B83EB + +[E27C00C2114A56D18DD27B426193B79C] +GoodName=Plasma Demo (PD) +CRC=E9F52336 6BEFAA5F + +[FBDD74ED68E6A0CD734562D56CCB752D] +GoodName=Pocket Monsters Snap (J) [!] +CRC=EC0F690D 32A7438C +Players=1 +SaveType=Flash RAM +CountPerOp=1 + +[33FDAB9712D9FEA793A3AE44293999C3] +GoodName=Pocket Monsters Snap (J) (VC) [!] +CRC=E0044E9E CD659D0D +RefMD5=FBDD74ED68E6A0CD734562D56CCB752D + +[42CC0FE1442B0A498DFD8F743179C51A] +GoodName=Pocket Monsters Snap (J) [b1] +CRC=BB2D10F8 B8ED4D23 +RefMD5=FBDD74ED68E6A0CD734562D56CCB752D + +[76AE2B6F38E611683ACA3B87D1B3D5CE] +GoodName=Pocket Monsters Snap (J) [f1] +CRC=BB2D10F8 B8ED4D23 +RefMD5=FBDD74ED68E6A0CD734562D56CCB752D + +[CCA8D3874996A78C3B5828E7A66AC916] +GoodName=Pocket Monsters Snap (J) [f2] (GameShark) +CRC=412D7090 CEDABAC3 +RefMD5=FBDD74ED68E6A0CD734562D56CCB752D + +[C46E087D966A35095DF96799B0B4FFAE] +GoodName=Pocket Monsters Stadium (J) [!] +CRC=665E8259 D098BD1D +Players=2 +SaveType=SRAM +Transferpak=Yes + +[B43B3C7A3D2149FEEDC8BA3B8198BE5D] +GoodName=Pocket Monsters Stadium (J) [b1] +CRC=665E8259 D098BD1D +RefMD5=C46E087D966A35095DF96799B0B4FFAE + +[D0698135C4A74CDEA8374DA0BD15DFDB] +GoodName=Pocket Monsters Stadium (J) [b2] +CRC=58FBD28F FEB595F0 +RefMD5=C46E087D966A35095DF96799B0B4FFAE + +[1A5D6FBF59D1639AF71B61410553AB04] +GoodName=Pocket Monsters Stadium (J) [f1] (Boot-PAL) +CRC=58FBD28F FEB595F0 +RefMD5=C46E087D966A35095DF96799B0B4FFAE + +[9BBC3945F526C8329710824C29FFC040] +GoodName=Pocket Monsters Stadium (J) [f2] (Boot) +CRC=76AF28D8 64A07F55 +RefMD5=C46E087D966A35095DF96799B0B4FFAE + +[2449BB712A64E3363A6CBD56F5ADEDA5] +GoodName=Pocket Monsters Stadium 2 (J) [!] +CRC=63775886 5FB80E7B +SaveType=Flash RAM +Players=4 +Transferpak=Yes + +[907403B12D2AD59A0F186A1632AE39B9] +GoodName=Pocket Monsters Stadium 2 (J) [f1] +CRC=FE667A12 0D2195AD +RefMD5=2449BB712A64E3363A6CBD56F5ADEDA5 + +[3F39C01455B585CAEB2DF8A09765D0B3] +GoodName=Pocket Monsters Stadium 2 (J) [f2] +CRC=FE667A12 0D2195AD +RefMD5=2449BB712A64E3363A6CBD56F5ADEDA5 + +[DC8F45A200FED15C3B0BD97A2F52ACA5] +GoodName=Pocket Monsters Stadium 2 (J) [f3] +CRC=058381EF 6A36FEC6 +RefMD5=2449BB712A64E3363A6CBD56F5ADEDA5 + +[E5D7B56B5EDBD8575ECEB9E5ECCF4A00] +GoodName=Pocket Monsters Stadium 2 (J) [f4] +CRC=FE667A12 0D2195AD +RefMD5=2449BB712A64E3363A6CBD56F5ADEDA5 + +[A17AADCC962393D476EDC321E59C504B] +GoodName=Pocket Monsters Stadium Kin Gin (J) [!] +CRC=EE4FD7C2 9CF1D938 +Players=4 +SaveType=Flash RAM +Transferpak=Yes + +[2EF9FA16DE2A09EA15B6289447F40490] +GoodName=Pokemon Puzzle League (E) [!] +CRC=4A1CD153 D830AEF8 +Players=2 +SaveType=Flash RAM + +[FBF566693BCA3145D86DF34D18DCDD43] +GoodName=Pokemon Puzzle League (E) (VC) [!] +CRC=4A1CD153 D830AEF8 +Players=2 +SaveType=Flash RAM + +[A3BA044DFC00BB766B4B2BFB9D4B5BE9] +GoodName=Pokemon Puzzle League (F) [!] +CRC=3EB2E6F3 062F9EFE +Players=2 +SaveType=Flash RAM + +[866D401C51CC05A3188C9A2D4E7BFEE5] +GoodName=Pokemon Puzzle League (F) (VC) [!] +CRC=3EB2E6F3 062F9EFE +Players=2 +SaveType=Flash RAM + +[000364BAC80E41D9060A31A5923874B7] +GoodName=Pokemon Puzzle League (G) [!] +CRC=7A4747AC 44EEEC23 +Players=2 +SaveType=Flash RAM + +[45B507AAAF0CCDB6EFE3CD717F0DDB95] +GoodName=Pokemon Puzzle League (G) (VC) [!] +CRC=7A4747AC 44EEEC23 +Players=2 +SaveType=Flash RAM + +[E722576A15182CFED6782379CE4BC8BE] +GoodName=Pokemon Puzzle League (U) [!] +CRC=19C553A7 A70F4B52 +Players=2 +SaveType=Flash RAM + +[D6F58B98115E78D841089074401AE524] +GoodName=Pokemon Puzzle League (U) (VC) [!] +CRC=19C553A7 A70F4B52 +Players=2 +SaveType=Flash RAM + +[DC09E2685EB95471311E57B3605F4894] +GoodName=Pokemon Puzzle League (U) [t1] +CRC=E1AAA925 27C9C94B +RefMD5=E722576A15182CFED6782379CE4BC8BE + +[D5EDC7B884DFBA7CF4AC4CDFA8AC64A4] +GoodName=Pokemon Puzzle League (U) [t2] +CRC=AAE125A9 C9274BC9 +RefMD5=E722576A15182CFED6782379CE4BC8BE + +[E5A0CA3DC54B38EA7FCD927E3CFFAD3B] +GoodName=Pokemon Snap (A) [!] +CRC=7BB18D40 83138559 +Players=1 +SaveType=Flash RAM +CountPerOp=1 + +[A88FCF3FF00F21D3CEC44D2E0FAAAAD8] +GoodName=Pokemon Snap (A) [f1] (GameShark) +CRC=F795ACE1 8DEDE03C +RefMD5=E5A0CA3DC54B38EA7FCD927E3CFFAD3B + +[F2A8106403D2BF9350BFEAB08689D54A] +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] +CRC=BA6C293A 9FAFA338 +RefMD5=E9028F9CCC307806695DD81742D05D5D + +[144B8906DC40534CFBEF6D7B994A982B] +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] +CRC=CA12B547 71FA4EE4 +RefMD5=FC3C9329B7CDD67CF7650ABF63B9A580 + +[E3D4F75C24DA0521488E704812259A46] +GoodName=Pokemon Snap (U) [f1] (Save) +CRC=3FF65EDD 0F8158B0 +RefMD5=FC3C9329B7CDD67CF7650ABF63B9A580 + +[373FBBF4B909E7C8A3AAB3DD80DEBD11] +GoodName=Pokemon Snap (U) [f2] (Save-PAL) +CRC=38186DAF 232AE3D8 +RefMD5=FC3C9329B7CDD67CF7650ABF63B9A580 + +[BCB210A6A3DCA9A653F836E2957BD6DC] +GoodName=Pokemon Snap (U) [f3] (GameShark) +CRC=03529CD9 186BDDCD +RefMD5=FC3C9329B7CDD67CF7650ABF63B9A580 + +[53A5D74FA55E378ADA84AF9B0ED2B728] +GoodName=Pokemon Snap (U) [f3] +CRC=3FF65EDD 0F8158B0 +RefMD5=FC3C9329B7CDD67CF7650ABF63B9A580 + +[A9C272687DABD59C5144774B53BCC35A] +GoodName=Pokemon Snap Station (U) [!] +CRC=39119872 07722E9F +Players=1 +SaveType=Flash RAM +CountPerOp=1 + +[B88F0EC125C54685FA516D233B564842] +GoodName=Pokemon Snap Station (U) [f1] +CRC=4B34DF0B 5899C0FE +RefMD5=A9C272687DABD59C5144774B53BCC35A + +[2859090D78581E0925A3AF8045E81E4B] +GoodName=Pokemon Stadium (E) (V1.0) [!] +CRC=84077275 57315B9C +Players=4 +SaveType=Flash RAM +Transferpak=Yes + +[9CC940F5F463416F0B2C15F07A088F33] +GoodName=Pokemon Stadium (E) (V1.0) [f1] +CRC=9DFE20E9 18894032 +RefMD5=2859090D78581E0925A3AF8045E81E4B + +[31EE2DE8E65E30F5934C450DBAA924F0] +GoodName=Pokemon Stadium (E) (V1.1) [!] +CRC=91C9E05D AD3AAFB9 +Players=4 +SaveType=Flash RAM +Transferpak=Yes + +[0E85A098D0F0E8A7EB572A69612A6873] +GoodName=Pokemon Stadium (F) [!] +CRC=A23553A3 42BF2D39 +Players=4 +SaveType=Flash RAM +Transferpak=Yes + +[4688C66F8C13EDA13DD5678176A7FD8A] +GoodName=Pokemon Stadium (F) [f1] +CRC=7E3D8157 D9BF4D91 +RefMD5=0E85A098D0F0E8A7EB572A69612A6873 + +[24BE2CCB0DEA0755908C02BF67E22FE5] +GoodName=Pokemon Stadium (G) [!] +CRC=42011E1B E3552DB5 +Players=4 +SaveType=Flash RAM +Transferpak=Yes + +[8FAA825507E6CD3F388CC33343FAE547] +GoodName=Pokemon Stadium (G) [f1] +CRC=D7F73553 1347659F +RefMD5=24BE2CCB0DEA0755908C02BF67E22FE5 + +[A81321759AF38BEB30A40FDACA2EA22A] +GoodName=Pokemon Stadium (I) [!] +CRC=A53FA82D DAE2C15D +Players=4 +SaveType=Flash RAM +Transferpak=Yes + +[D14A499BC4E324974EAE3E42DEC58625] +GoodName=Pokemon Stadium (S) [!] +CRC=B6E549CE DC8134C0 +Players=4 +SaveType=Flash RAM +Transferpak=Yes + +[8D296A614A47AC99B80D1EDE669E62B3] +GoodName=Pokemon Stadium (S) [f1] +CRC=4C115008 9F124960 +RefMD5=D14A499BC4E324974EAE3E42DEC58625 + +[ED1378BC12115F71209A77844965BA50] +GoodName=Pokemon Stadium (U) (V1.0) [!] +CRC=90F5D9B3 9D0EDCF0 +Players=4 +SaveType=Flash RAM +Transferpak=Yes + +[C9214988B08511D2F44FAC2FAD2EE67A] +GoodName=Pokemon Stadium (U) (V1.0) [f1] +CRC=84EBE70F 352C5E3F +RefMD5=ED1378BC12115F71209A77844965BA50 + +[40E03EDA831C01E0A12294287FD240E2] +GoodName=Pokemon Stadium (U) (V1.1) [!] +CRC=1A122D43 C17DAF0F +Players=4 +SaveType=Flash RAM +Transferpak=Yes + +[A7087A96A709E4C662A459B4B4159094] +GoodName=Pokemon Stadium (U) (V1.1) [b1] +CRC=1A122D43 C17DAF0F +RefMD5=40E03EDA831C01E0A12294287FD240E2 + +[A0087A475A29F38BD4CE5DF0A41A89CB] +GoodName=Pokemon Stadium (U) (V1.1) [b1][f1] +CRC=3FC42B3E CED602E6 +RefMD5=40E03EDA831C01E0A12294287FD240E2 + +[6DC6820CEF755FC1253D06DF45C9BD2A] +GoodName=Pokemon Stadium (U) (V1.2) [!] +CRC=9C8FB2FA 9B84A09B +Players=4 +SaveType=Flash RAM +Transferpak=Yes + +[B1271DB50D6EF8F6B53CC640C3743E4F] +GoodName=Pokemon Stadium 2 (E) [!] +CRC=2952369C B6E4C3A8 +Players=4 +SaveType=Flash RAM +Transferpak=Yes + +[BB1623BD4751240138DE55E18D3ACA7E] +GoodName=Pokemon Stadium 2 (E) [T+Ita0.05] +CRC=2952369C B6E4C3A8 +RefMD5=B1271DB50D6EF8F6B53CC640C3743E4F + +[4748D96916AE2BCC5FC1630515EE2561] +GoodName=Pokemon Stadium 2 (F) [!] +CRC=AC5AA5C7 A9B0CDC3 +Players=4 +SaveType=Flash RAM +Transferpak=Yes + +[484F3E696C94980ACF3D7068F9ACC98F] +GoodName=Pokemon Stadium 2 (G) [!] +CRC=439B7E7E C1A1495D +Players=4 +SaveType=Flash RAM +Transferpak=Yes + +[5A04D7F1AB9C6B080176567AA7168D3A] +GoodName=Pokemon Stadium 2 (I) [!] +CRC=EFCEAF00 22094848 +Players=4 +SaveType=Flash RAM +Transferpak=Yes + +[B26AAFD452C9816E1B7AA0954E75825F] +GoodName=Pokemon Stadium 2 (S) [!] +CRC=D0A1FC5B 2FB8074B +Players=4 +SaveType=Flash RAM +Transferpak=Yes + +[1561C75D11CEDF356A8DDB1A4A5F9D5D] +GoodName=Pokemon Stadium 2 (U) [!] +CRC=03571182 892FD06D +Players=4 +SaveType=Flash RAM +Transferpak=Yes + +[BBDC4C4F1C474298189312008A1768C4] +GoodName=Polaris SnoCross (U) [!] +CRC=41380792 A167E045 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[F27CBDB653AAF1D4856A53D5951F36DD] +GoodName=Polaris SnoCross (U) [o1][t1] +CRC=B8B73263 1492FC49 +RefMD5=BBDC4C4F1C474298189312008A1768C4 + +[35A01AEB01F3184DD20904AF28FA71C6] +GoodName=Polaris SnoCross (U) [t1] +CRC=B8B73263 1492FC49 +RefMD5=BBDC4C4F1C474298189312008A1768C4 + +[8847BD6403BA49FD62899115D661B623] +GoodName=Pom Part 1 Demo (PD) +CRC=1BC0CA2C 0F516B86 + +[037D2727B90998BED41DA0F290BB8441] +GoodName=Pom Part 2 Demo (PD) +CRC=ACD51083 EEC8DBED + +[5426EAED0D350367393F385025AF164C] +GoodName=Pom Part 3 Demo (PD) +CRC=1FE04890 D6696958 + +[C7921F3D4B91A42472DADD4DBA2CDC54] +GoodName=Pom Part 4 Demo (PD) +CRC=CFBEE39B 76F0A14A + +[F67C06AF4F6613804B3F700B1169B58D] +GoodName=Pom Part 5 Demo (PD) +CRC=2803B8CE 4A1EE409 + +[BA976164C2A900C03F445ACD51518FB0] +GoodName=Pong V0.01 by Omsk (PD) +CRC=C252F9B1 AD70338C + +[8EACC93671249508BF12CF6EC101056D] +GoodName=Pong by Oman (PD) +CRC=DAA76993 D8ACF77C +Players=2 +Status=3 +Rumble=No +SaveType=None + +[68C7FC1924AB4400CB65E40C32B7D3A6] +GoodName=Pong by Oman (PD) [a1] +CRC=DAA76993 D8ACF77C +RefMD5=8EACC93671249508BF12CF6EC101056D + +[E3CFB5F1828CAF1F00B23ADA863460AD] +GoodName=Pong by Oman (PD) [h1C][o1] +CRC=DAA76993 D8ACF77C +RefMD5=8EACC93671249508BF12CF6EC101056D + +[CD4D5C6C96C8C528A0FCE2958A4A7AC9] +GoodName=Pong by Oman (PD) [t1] +CRC=6BE878A8 3DC16D91 +RefMD5=8EACC93671249508BF12CF6EC101056D + +[8CC73C373016070647030DDE492FDC8C] +GoodName=Power League 64 (J) [!] +CRC=D7A6DCFA CCFEB6B7 +Players=4 +Mempak=Yes + +[6504FC6F3ADB596F7D68060EB39A75B4] +GoodName=Power League 64 (J) [o1] +CRC=D7A6DCFA CCFEB6B7 +RefMD5=8CC73C373016070647030DDE492FDC8C + +[AE3BDF729214964620417CC3163F0BB6] +GoodName=Power Rangers - Lightspeed Rescue (E) [!] +CRC=39F60C11 AB2EBA7D +Players=2 +SaveType=None +Mempak=Yes + +[24B5BFA896802253D2B715FC760D1B3E] +GoodName=Power Rangers - Lightspeed Rescue (E) [f1] (NTSC) +CRC=8CD06379 62319493 +RefMD5=AE3BDF729214964620417CC3163F0BB6 + +[91D74621DDEF6D37FB845B3BC7059A38] +GoodName=Power Rangers - Lightspeed Rescue (U) [!] +CRC=CF8957AD 96D57EA9 +Players=2 +SaveType=None +Mempak=Yes + +[2991BB68ECA54813D6B834ADBBBACC4C] +GoodName=Powerpuff Girls, The - Chemical X-Traction (U) [!] +CRC=FC74D475 9A0278AB +Players=2 +SaveType=None + +[25BAFC84BA4D87854DC44DF3EF8764EA] +GoodName=Premier Manager 64 (E) [!] +CRC=F3D27F54 C111ACF9 +Players=1 +Mempak=Yes + +[527F05F166398599F0A1B10F8E1F9585] +GoodName=Premier Manager 64 (E) [f1] (NTSC) +CRC=F45A6784 F587C72F +RefMD5=25BAFC84BA4D87854DC44DF3EF8764EA + +[ED4FE5EAA6631BB142DEF7F317315DFA] +GoodName=Premier Manager 64 (E) [f2] (NTSC100%) +CRC=C98C4580 A8C84DAD +RefMD5=25BAFC84BA4D87854DC44DF3EF8764EA + +[7995D76F4CE236B0F0289F47AE523D32] +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] +CRC=9BA10C4E 0408ABD3 +RefMD5=7995D76F4CE236B0F0289F47AE523D32 + +[6FEC88E88ED25AE7E823A69444D6098A] +GoodName=Pro Mahjong Kiwame 64 (J) (V1.0) [o1] +CRC=9BA10C4E 0408ABD3 +RefMD5=7995D76F4CE236B0F0289F47AE523D32 + +[B42F62483F7CA2AAC5AF911175463DB8] +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] +CRC=C5C4F0D5 4EEF2573 + +[592292DF29823A0FD81ED32666878C15] +GoodName=Psychodelic Demo by Ste (POM '98) (PD) +CRC=C5C4F0D5 4EEF2573 + +[22B86AB3F320A607899A0516C90A24D0] +GoodName=Puyo Puyo 4 - Puyo Puyo Party (J) [!] +CRC=4B4672B9 2DBE5DE7 +Players=4 +Rumble=Yes +Transferpak=Yes + +[FAAA2094B04DCA4C287AF9334D22529D] +GoodName=Puyo Puyo Sun 64 (J) [!] +CRC=94807E6B 60CC62E4 +Players=2 +Rumble=Yes + +[20C7ABF5A4DB8DC1C70725FD213E29A2] +GoodName=Puyo Puyo Sun 64 (J) [b1] +CRC=94807E6B 60CC62E4 +RefMD5=FAAA2094B04DCA4C287AF9334D22529D + +[B478D4AF60D43C38BA81DE9FAEA6E057] +GoodName=Puzzle Bobble 64 (J) [!] +CRC=C0DE0747 A2DF72D3 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[9B463A87DA73B8C923B05C3BD46EDB09] +GoodName=Puzzle Bobble 64 (J) [f1] (PAL) +CRC=53D93EA2 B88836C6 +RefMD5=B478D4AF60D43C38BA81DE9FAEA6E057 + +[EA335A87C87F302C6A10D0D3D3E09B72] +GoodName=Puzzle Bobble 64 (J) [f2] (PAL) +CRC=412E02B8 51A57E8E +RefMD5=B478D4AF60D43C38BA81DE9FAEA6E057 + +[FBDD421FC2105CF4B9663DF97FD7041D] +GoodName=Puzzle Master 64 by Michael Searl (PD) +CRC=4BBBA2E2 8BF3BBB2 +Players=1 +Rumble=No +SaveType=None +Status=2 + +[592CE7718EFDD1FF2F077C9B2B5275FB] +GoodName=Quake 64 (E) [!] +CRC=16931D74 65DC6D34 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[30EDCCA84850E3B4129936350A9B6B8B] +GoodName=Quake 64 (E) [o1] +CRC=16931D74 65DC6D34 +RefMD5=592CE7718EFDD1FF2F077C9B2B5275FB + +[FE4AC551B284BD0924F2AAA387249B4B] +GoodName=Quake 64 (E) [t1] +CRC=68CE63CC 2FFE262C +RefMD5=592CE7718EFDD1FF2F077C9B2B5275FB + +[097605021951024C3ECB2D502C0C2A9F] +GoodName=Quake 64 (U) [!] +CRC=9F5BF79C D2FE08A0 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[87F35BC0C6E2EAD981B49D691095B118] +GoodName=Quake 64 (U) [b1] +CRC=254CF663 DC8131EE +RefMD5=097605021951024C3ECB2D502C0C2A9F + +[295FAA9B7CC7127BC82AEA90ADB211E5] +GoodName=Quake 64 (U) [h1C] +CRC=9F5BF79C D2FE08A0 +RefMD5=097605021951024C3ECB2D502C0C2A9F + +[2138CE5AEC363BAC2F18CE65A78ECA25] +GoodName=Quake 64 (U) [o1] +CRC=9F5BF79C D2FE08A0 +RefMD5=097605021951024C3ECB2D502C0C2A9F + +[D599490909FAACB26D134D152CB5F1ED] +GoodName=Quake 64 (U) [o1][t1] +CRC=254CF663 DC8131EE +RefMD5=097605021951024C3ECB2D502C0C2A9F + +[F2FA48329FF6DDBB7BD4EEA838FD800B] +GoodName=Quake 64 (U) [o2] +CRC=9F5BF79C D2FE08A0 +RefMD5=097605021951024C3ECB2D502C0C2A9F + +[7B593077EFC15B44C8D8FF639D6FB434] +GoodName=Quake 64 (U) [o2][t1] +CRC=254CF663 DC8131EE +RefMD5=097605021951024C3ECB2D502C0C2A9F + +[953BB3AD87B3C1B7AC85F12B135FAA85] +GoodName=Quake 64 (U) [t1] +CRC=254CF663 DC8131EE +RefMD5=097605021951024C3ECB2D502C0C2A9F + +[C31A8BB6705BD2112A5ABF4F825FD3C0] +GoodName=Quake 64 Intro (PD) +CRC=F4D89C08 3F34930D + +[673D4BA4F41A0FE23650F06AF53EEC50] +GoodName=Quake II (E) [!] +CRC=7433D9D7 2C4322D0 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[55A789C553827114306E29D71E26E5DC] +GoodName=Quake II (E) [h1C] +CRC=7433D9D7 2C4322D0 +RefMD5=673D4BA4F41A0FE23650F06AF53EEC50 + +[CC93C30C633FF461C29B54CEABEFD701] +GoodName=Quake II (U) [!] +CRC=BDA8F143 B1AF2D62 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[920FAACCE1F8A80022433ACFD5CD2BC3] +GoodName=Quake II (U) [f1] (PAL) +CRC=4F8B1784 763A4E04 +RefMD5=CC93C30C633FF461C29B54CEABEFD701 + +[EA552E33973468233A0712C251ABDB6B] +GoodName=Quest 64 (U) [!] +CRC=C8BB4DD9 CC5F430B +Players=1 +SaveType=None +Mempak=Yes + +[6F32B4DE3B3FC0C719BF9EA27EFC18BE] +GoodName=Quest 64 (U) [b1] +CRC=C8BB4DD9 CC5F430B +RefMD5=EA552E33973468233A0712C251ABDB6B + +[0E2CAB03B712E7D4E1C6501978E2E637] +GoodName=Quest 64 (U) [b2] +CRC=C8BB4DD9 CC5F430B +RefMD5=EA552E33973468233A0712C251ABDB6B + +[4890576C70E8486D2A90424C57C53752] +GoodName=Quest 64 (U) [b3] +CRC=C8BB4DD9 CC5F430B +RefMD5=EA552E33973468233A0712C251ABDB6B + +[E9EFCC508A7054BB94E5B3243018F1AC] +GoodName=Quest 64 (U) [b4] +CRC=C8BB4DD9 CC5F430B +RefMD5=EA552E33973468233A0712C251ABDB6B + +[131CCC5C9E9BD830147562DFD06444BF] +GoodName=Quest 64 (U) [b5] +CRC=C8BB4DD9 CC5F430B +RefMD5=EA552E33973468233A0712C251ABDB6B + +[C01A079E0005DCF5AD9AB0D58CD9515E] +GoodName=Quest 64 (U) [t1] +CRC=5F48A227 B97D9B7F +RefMD5=EA552E33973468233A0712C251ABDB6B + +[5DF35D0C05E58FCE938BAEC6CB2A230E] +GoodName=R.I.P. Jay Demo by Ste (PD) [b1] +CRC=32A92961 DB34982C + +[03418F1567DC45CBB4B4E9DA772CAA7F] +GoodName=R.I.P. Jay Demo by Ste (PD) +CRC=32A92961 DB34982C + +[FFE3839FD3974A0858A62CF363D0F8DB] +GoodName=RADWAR 2K Party Inv. Intro by Ayatolloh (PD) +CRC=C9011D05 EF078B8C + +[34AF9F96DE01A7DF6B296598908BB398] +GoodName=RPA Site Intro by Lem (PD) +CRC=79E318E1 86861726 + +[4561840840760FFA7B59F03A5F416A5C] +GoodName=RR64 - Ridge Racer 64 (E) [!] +CRC=FEE97010 4E94A9A0 +SaveType=Eeprom 16KB +Players=4 +Rumble=Yes + +[990F97D56456FC23E52BD263E709E21E] +GoodName=RR64 - Ridge Racer 64 (U) [!] +CRC=2500267E 2A7EC3CE +SaveType=Eeprom 16KB +Players=4 +Rumble=Yes + +[8CF63267BA38AB73763354C79C4ADB74] +GoodName=RR64 - Ridge Racer 64 (U) [f1] (PAL) +CRC=4E17004A 259E946C +RefMD5=990F97D56456FC23E52BD263E709E21E + +[07D6006F744727DAAC7F53692AD950C4] +GoodName=RR64 - Ridge Racer 64 (U) [t1] +CRC=5A98A468 AB27C89D +RefMD5=990F97D56456FC23E52BD263E709E21E + +[A1082A6676455C040843FD75E92DE1A3] +GoodName=RTL World League Soccer 2000 (G) [!] +CRC=658F8F37 1813D28D +Players=4 +Mempak=Yes +Rumble=Yes + +[09BEE9D7EB1159D11E49BDFB03A2C4CC] +GoodName=RTL World League Soccer 2000 (G) [f1] (NTSC) +CRC=D250103E 136A0F0C +RefMD5=A1082A6676455C040843FD75E92DE1A3 + +[4392F33C4282B68C9DEF5111CCF733CA] +GoodName=RTL World League Soccer 2000 (G) [f1][o1] +CRC=D250103E 136A0F0C +RefMD5=A1082A6676455C040843FD75E92DE1A3 + +[AA57D69867F53456F351A289EBA08C3D] +GoodName=Racing Simulation 2 (G) [!] +CRC=2877AC2D C3DC139A +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[6160D5DE99BE421ACB620D2D203C2FEC] +GoodName=Racing Simulation 2 (G) [h1C] +CRC=2877AC2D C3DC139A +RefMD5=AA57D69867F53456F351A289EBA08C3D + +[167A3502F06CF0EEF56758533F3D0E52] +GoodName=Rakuga Kids (E) [!] +CRC=67D21868 C5424061 +Players=2 +Mempak=Yes + +[28FE768CED3C87659B343A7811CFAC0A] +GoodName=Rakuga Kids (E) [b1] +CRC=67D21868 C5424061 +RefMD5=167A3502F06CF0EEF56758533F3D0E52 + +[7F0900DD9726A7E56A398E910D014B61] +GoodName=Rakuga Kids (E) [f1] (NTSC) +CRC=49020C8E A000B949 +RefMD5=167A3502F06CF0EEF56758533F3D0E52 + +[98A802D44FE4169FD73D7B481C08613E] +GoodName=Rakuga Kids (E) [h1C] +CRC=67D21868 C5424061 +RefMD5=167A3502F06CF0EEF56758533F3D0E52 + +[813AD5C00BAD7C4D41F8558CECEDAE51] +GoodName=Rakuga Kids (J) [!] +CRC=9F1ECAF0 EEC48A0E +Players=2 +Mempak=Yes + +[378C6CE13DF3363F77D76B64C8DAB287] +GoodName=Rakuga Kids (J) [b1] +CRC=9F1ECAF0 EEC48A0E +RefMD5=813AD5C00BAD7C4D41F8558CECEDAE51 + +[08D79A5C0F393D81296F50A6D556D999] +GoodName=Rakuga Kids (J) [h1C] +CRC=9F1ECAF0 EEC48A0E +RefMD5=813AD5C00BAD7C4D41F8558CECEDAE51 + +[0630226F63561A05916EDCFBC8D96C04] +GoodName=Rally '99 (J) [!] +CRC=35D9BA0C DF485586 +Players=4 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[035B02E493A388E950FB42F4B3D891F8] +GoodName=Rally '99 (J) [f1] (PAL) +CRC=4C2B343C 7249BAFF +RefMD5=0630226F63561A05916EDCFBC8D96C04 + +[0458BC47CD771D8BC66B0CEAE6895724] +GoodName=Rally Challenge 2000 (U) [!] +CRC=73A88E3D 3AC5C571 +Players=4 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[08E02F52E0547686A9BFAC7CBB03C129] +GoodName=Rampage - World Tour (E) [!] +CRC=84D44448 67CA19B0 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[410146EA14CF34D134BC97C78522D322] +GoodName=Rampage - World Tour (E) [h1C] +CRC=84D44448 67CA19B0 +RefMD5=08E02F52E0547686A9BFAC7CBB03C129 + +[4645672A0CF00ADA9B5E37CFDE8B024E] +GoodName=Rampage - World Tour (U) [!] +CRC=C29FF9E4 264BFE7D +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[1659F9F8C8A5C24F775B245BDA574462] +GoodName=Rampage - World Tour (U) [b1] +CRC=C29FF9E4 264BFE7D +RefMD5=4645672A0CF00ADA9B5E37CFDE8B024E + +[71EC90E34421CEEAA8B71ACAF76EFD33] +GoodName=Rampage - World Tour (U) [b2] +CRC=C29FF9E4 264BFE7D +RefMD5=4645672A0CF00ADA9B5E37CFDE8B024E + +[669584EEB9F85C7A8A96B716A2B43739] +GoodName=Rampage - World Tour (U) [b3] +CRC=C29FF9E4 264BFE7D +RefMD5=4645672A0CF00ADA9B5E37CFDE8B024E + +[70C3E7412FF8196E16CCA076B3B622F7] +GoodName=Rampage - World Tour (U) [b4] +CRC=C29FF9E4 264BFE7D +RefMD5=4645672A0CF00ADA9B5E37CFDE8B024E + +[BE823D7958151B97F812FBF01E7621D2] +GoodName=Rampage - World Tour (U) [h1C] +CRC=C29FF9E4 264BFE7D +RefMD5=4645672A0CF00ADA9B5E37CFDE8B024E + +[E3060D3FADA2A502764E765F8140FC42] +GoodName=Rampage - World Tour (U) [t1] +CRC=588F980C 63FF7803 +RefMD5=4645672A0CF00ADA9B5E37CFDE8B024E + +[4D280855EA4FFE98054BDF633EA5A7F7] +GoodName=Rampage - World Tour (U) [t2] +CRC=588F980C 63FF7803 +RefMD5=4645672A0CF00ADA9B5E37CFDE8B024E + +[1492806F12D33C3EA0EDB6848D43B1CC] +GoodName=Rampage 2 - Universal Tour (E) [!] +CRC=5DFC4249 99529C07 +Players=3 +SaveType=None +Mempak=Yes +Rumble=Yes + +[8113D0EA2008402D4631F241F625D16B] +GoodName=Rampage 2 - Universal Tour (U) [!] +CRC=673D099B A4C808DE +Players=3 +SaveType=None +Mempak=Yes +Rumble=Yes + +[EBAFB5C3BCC84543A8E7FEF1993E573F] +GoodName=Rampage 2 - Universal Tour (U) [t1] +CRC=BF4317E2 2DF987E2 +RefMD5=8113D0EA2008402D4631F241F625D16B + +[EA383E48637B44FFF9294D23B076548B] +GoodName=Rampage 2 - Universal Tour (U) [t2] +CRC=FD2FC875 3BD10D89 +RefMD5=8113D0EA2008402D4631F241F625D16B + +[C7B9024594F932BA5E3A1FB70FE9BD6B] +GoodName=Rape Kombat Trilogy Beta1 (Mortal Kombat Hack) +CRC=9A2949C1 04E76074 + +[BC66239C12AE8696926E50C2B6ED9C49] +GoodName=Rat Attack (E) (M6) [!] +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) +CRC=85670AB4 3834BE8A +RefMD5=BC66239C12AE8696926E50C2B6ED9C49 + +[6F868B1652183376665F67F8183EEB5C] +GoodName=Rat Attack (E) (M6) [h1C] +CRC=20FD0BF1 F5CF1D87 +RefMD5=BC66239C12AE8696926E50C2B6ED9C49 + +[F661889FDF65DDCD212E9FB53B2C8F50] +GoodName=Rat Attack (U) (M6) [!] +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) [!] +CRC=60D5E10B 8BEDED46 +Players=1 +SaveType=None +Mempak=Yes + +[EF2001F581A80D760C51D130725A9930] +GoodName=Rayman 2 - The Great Escape (E) (M5) [f1] (NTSC) +CRC=B8C303FA 544BB5FA +RefMD5=5DBBFD5ACE8222FA8FE51BE113453C13 + +[53B325CCDF2069AB20CAF1C9B401CD20] +GoodName=Rayman 2 - The Great Escape (E) (M5) [f2] (NTSC) +CRC=7055FD0A E0A45808 +RefMD5=5DBBFD5ACE8222FA8FE51BE113453C13 + +[03AA4D09FDE77EED9B95BE68E603D233] +GoodName=Rayman 2 - The Great Escape (U) (M5) [!] +CRC=F3C5BF9B 160F33E2 +Players=1 +SaveType=None +Mempak=Yes + +[2B1D9F38389522A372D950E1BC6FA13F] +GoodName=Rayman 2 - The Great Escape (U) (M5) [t1] +CRC=8BB6E3EB 2402CC87 +RefMD5=03AA4D09FDE77EED9B95BE68E603D233 + +[406B08987AB92D73D72B597EC6B11BD9] +GoodName=Razor Freestyle Scooter (U) [!] +CRC=3918834A 15B50C29 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[FAA64ABB0D222FCC0C6E2515D3805D9F] +GoodName=Re-Volt (E) (M4) [!] +CRC=C3E7E29E 5D7251CC +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[3FC4D3187435443455F8355B2D3F8934] +GoodName=Re-Volt (U) [!] +CRC=0F1FA987 BFC1AFA6 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[377DAF6EDD0C996422D2A9C8C5DEC033] +GoodName=Re-Volt (U) [f1] (Country Check) +CRC=529AA985 A85509A3 +RefMD5=3FC4D3187435443455F8355B2D3F8934 + +[77DC38CCE0FFAB004FD54F54EE25A593] +GoodName=Re-Volt (U) [f2] (PAL) +CRC=53575A75 54573214 +RefMD5=3FC4D3187435443455F8355B2D3F8934 + +[197E24C1AB6503998798D7F56EAE7ADD] +GoodName=Re-Volt (U) [t1] +CRC=B754A584 D3530516 +RefMD5=3FC4D3187435443455F8355B2D3F8934 + +[ADC95AE01855FA305B13F8B22427E597] +GoodName=Ready 2 Rumble Boxing (E) (M3) [!] +CRC=8BD4A334 1E138B05 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[70F73D01FEAF768758F31B23DE2C2620] +GoodName=Ready 2 Rumble Boxing (E) (M3) [t1] (P1 Untouchable) +CRC=8638A334 8EBF1508 +RefMD5=ADC95AE01855FA305B13F8B22427E597 + +[A42F6F14F7EA10ABEB3B55FFD42EB572] +GoodName=Ready 2 Rumble Boxing (U) [!] +CRC=EAB7B429 BAC92C57 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[25620A9C9F372023A8BA862330E6373A] +GoodName=Ready 2 Rumble Boxing (U) [f1] (PAL) +CRC=5D6AA6EA 657352B1 +RefMD5=A42F6F14F7EA10ABEB3B55FFD42EB572 + +[CCECEAA389A7847DE3433888C66A76E5] +GoodName=Ready 2 Rumble Boxing (U) [t1] (P1 Untouchable) +CRC=E655B42D F22370DD +RefMD5=A42F6F14F7EA10ABEB3B55FFD42EB572 + +[DF4446A2B55C4D8D67E9C0C19E0FD9FB] +GoodName=Ready 2 Rumble Boxing - Round 2 (U) [!] +CRC=E9219533 13FBAFBD +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[CB97350D5CAB48EAB8B954D91C0E5DAC] +GoodName=Ready 2 Rumble Boxing - Round 2 (U) [t1] +CRC=6CED60AC C74292DC +RefMD5=DF4446A2B55C4D8D67E9C0C19E0FD9FB + +[B04F298721223A22E1150CEBC712EE6A] +GoodName=Resident Evil 2 (E) (M2) [!] +CRC=9B500E8E E90550B3 +Players=1 +SaveType=SRAM +Rumble=Yes +CountPerOp=1 + +[DD21150CBC21C05420304599EC57411C] +GoodName=Resident Evil 2 (U) (V1.0) [!] +CRC=2F493DD0 2E64DFD9 +Players=1 +SaveType=SRAM +Rumble=Yes +CountPerOp=1 + +[1ADD2C0217662B307CDFD876B35FBF7A] +GoodName=Resident Evil 2 (U) (V1.1) [!] +CRC=AA18B1A5 07DB6AEB +Players=1 +SaveType=SRAM +Rumble=Yes +CountPerOp=1 + +[AD922DAE446A301E1AAFE1DFBAD75A2E] +GoodName=Road Rash 64 (E) [!] +CRC=02D8366A 6CABEF9C +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=3 + +[5EB2B1892B68767EB1D310FF7507D34E] +GoodName=Road Rash 64 (E) [h1C] +CRC=02D8366A 6CABEF9C +RefMD5=AD922DAE446A301E1AAFE1DFBAD75A2E + +[28C2373F6D831EEC81F6146A809E701B] +GoodName=Road Rash 64 (U) [!] +CRC=F050746C 247B820B +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=3 + +[7966F17F36C43D3807C0949AAD45168A] +GoodName=Road Rash 64 (U) [f1] (PAL) +CRC=422D29E1 C1FB33F3 +RefMD5=28C2373F6D831EEC81F6146A809E701B + +[C6867566C9E173BEAB459C5945B69C23] +GoodName=Road Rash 64 (U) [t1] +CRC=48176863 E1829A22 +RefMD5=28C2373F6D831EEC81F6146A809E701B + +[41F67B5C8BB8DAEFFD989123846FC063] +GoodName=Roadsters Trophy (E) (M6) [!] +CRC=74E87A70 6293AED4 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[D3644B398C090528E0ED9EB3C140366E] +GoodName=Roadsters Trophy (U) (M3) [!] +CRC=0B6B4DDB 9671E682 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[AE705F25C57ACABBD0E8BAE5EC6E237F] +GoodName=Roadsters Trophy (U) (M3) [f1] (PAL) +CRC=787AECF1 CC8147BA +RefMD5=D3644B398C090528E0ED9EB3C140366E + +[5C9C715430ACBAEF3A5FBDB3E6661ACF] +GoodName=Roadsters Trophy (U) (M3) [t1] +CRC=74BCA5D3 4A945F7E +RefMD5=D3644B398C090528E0ED9EB3C140366E + +[444F70A655AC89CA900F6FAFAF926B16] +GoodName=Robot Ponkottsu 64 - 7tsu no Umi no Caramel (J) [!] +CRC=272B690F AD0A7A77 +Players=2 +SaveType=Eeprom 16KB +Transferpak=Yes + +[34779AF3681F58E4F642F03EAEF198F9] +GoodName=Robot Ponkotsu 64 - 7tsu no Umi no Caramel (J) [f1] (PAL) +CRC=7F564549 ED60C5E6 +RefMD5=444F70A655AC89CA900F6FAFAF926B16 + +[27C6F780F9032A531E9A322969CD9159] +GoodName=Robotech - Crystal Dreams (Beta) +CRC=75A0B893 4CA321B5 + +[B39592C6C9A3121258BDB62485956880] +GoodName=Robotech - Crystal Dreams (Beta) [a1] +CRC=75A0B893 4CA321B5 + +[2ABCD1AD41B3356FBC1018ECB121283E] +GoodName=Robotron 64 (E) [!] +CRC=9FF69D4F 195F0059 +Players=2 +SaveType=None +Mempak=Yes + +[360044D5675A328E62191250F43B6671] +GoodName=Robotron 64 (E) [h1C] +CRC=9FF69D4F 195F0059 +RefMD5=2ABCD1AD41B3356FBC1018ECB121283E + +[5698757883A6F46FE5B4C9B6E780B480] +GoodName=Robotron 64 (U) [!] +CRC=AC8E4B32 E7B47326 +Players=2 +SaveType=None +Mempak=Yes + +[C4A9BBF989DDFAF5F389E4ADC6195DBC] +GoodName=Robotron 64 (U) [b1] +CRC=AC8E4B32 E7B47326 +RefMD5=5698757883A6F46FE5B4C9B6E780B480 + +[8555DCF12FD35206451FB415F3FD2EEF] +GoodName=Robotron 64 (U) [b2] +CRC=8F4C4B32 6D881FCA +RefMD5=5698757883A6F46FE5B4C9B6E780B480 + +[AB50026DAEA629F554408E5BA3EFA182] +GoodName=Robotron 64 (U) [b3] +CRC=8F4C4B32 6D881FCA +RefMD5=5698757883A6F46FE5B4C9B6E780B480 + +[1AA79B5DEFE1F5852D5ADD799383CCCD] +GoodName=Robotron 64 (U) [b4] +CRC=575CCC2E A8B5ACE0 +RefMD5=5698757883A6F46FE5B4C9B6E780B480 + +[377B9C40EBE4F4CF845E577A8DC9ACCB] +GoodName=Robotron 64 (U) [f1] (PAL) +CRC=8F4C4B32 6D881FCA +RefMD5=5698757883A6F46FE5B4C9B6E780B480 + +[27E4C31540E18E3E8CEA97BFF744CC11] +GoodName=Robotron 64 (U) [o1] +CRC=AC8E4B32 E7B47326 +RefMD5=5698757883A6F46FE5B4C9B6E780B480 + +[E151CCE259636C5AE15CA1C8B380EE76] +GoodName=Robotron 64 (U) [t1] +CRC=575CCC2E A8B5ACE0 +RefMD5=5698757883A6F46FE5B4C9B6E780B480 + +[427C5457D4A29A222811F0CAA9CCA7B9] +GoodName=Rocket - Robot on Wheels (E) (M3) [!] +CRC=9FD375F8 45F32DC8 +SaveType=Eeprom 4KB +Players=1 +Rumble=Yes + +[C2907EB2F9A350793317ECE878A3B8E3] +GoodName=Rocket - Robot on Wheels (U) [!] +CRC=0C5EE085 A167DD3E +SaveType=Eeprom 4KB +Players=1 +Rumble=Yes + +[E8CBAADEDB6D19ACC142BE3105E94C4F] +GoodName=Rocket - Robot on Wheels (U) [b1] +CRC=0C5EE085 A167DD3E +RefMD5=C2907EB2F9A350793317ECE878A3B8E3 + +[991E5F527EC9330320E65233C293D4C5] +GoodName=Rocket - Robot on Wheels (U) [f1] (PAL) +CRC=B9233DC7 9CCF2D4C +RefMD5=C2907EB2F9A350793317ECE878A3B8E3 + +[B042C238C4093DB533EC4E849C40DE4F] +GoodName=Rocket - Robot on Wheels (U) [t1] +CRC=B31A9FBB 26D03050 +RefMD5=C2907EB2F9A350793317ECE878A3B8E3 + +[0C74B44680276FFE808CFA6045329819] +GoodName=Rockman Dash (J) [!] +CRC=D666593B D7A25C07 +Players=1 +SaveType=Flash RAM +Rumble=Yes + +[14F1F43A0314C3E36D9D248E1F03EC2E] +GoodName=Ronaldinho's Soccer 64 (B) (Unl) (Pirate) +CRC=6F46DA42 D971A312 + +[73971508A3B4CA92F7F4CF59C9170372] +GoodName=Rotating Demo USA by Rene (PD) [a1] +CRC=6FA4B821 29561690 + +[0BF79F532C938384431DA9406B846AFA] +GoodName=Rotating Demo USA by Rene (PD) +CRC=6FA4B821 29561690 + +[DEC4598A39728C28CD0CEBA45A173CE1] +GoodName=Rugrats - Die grosse Schatzsuche (G) [!] +CRC=451ACA0F 7863BC8A +Players=4 +SaveType=None +Rumble=Yes + +[8C432235A57D34BC4A9B8B290E21E01E] +GoodName=Rugrats - Scavenger Hunt (U) [!] +CRC=0C02B3C5 9E2511B8 +Players=4 +SaveType=None +Rumble=Yes + +[C3ED4CD05978DECFD761FA2503DCB39E] +GoodName=Rugrats - Scavenger Hunt (U) [f1] (PAL) +CRC=F04A729C 19971680 +RefMD5=8C432235A57D34BC4A9B8B290E21E01E + +[55185016031CDC73C0FD471527C35706] +GoodName=Rugrats - Treasure Hunt (E) [!] +CRC=4D3ADFDA 7598FCAE +Players=4 +SaveType=None +Rumble=Yes + +[950161325C7E11A057CC85C95685DB05] +GoodName=Rugrats - Treasure Hunt (E) [h1C] +CRC=4D3ADFDA 7598FCAE +RefMD5=55185016031CDC73C0FD471527C35706 + +[229089089661F517C863242D6BB77746] +GoodName=Rugrats in Paris - The Movie (E) [!] +CRC=0AC61D39 ABFA03A6 +Players=2 +SaveType=None +Mempak=Yes + +[207EFE58C7C221DBDFFF285AB80126C1] +GoodName=Rugrats in Paris - The Movie (U) [!] +CRC=1FC21532 0B6466D4 +Players=2 +SaveType=None +Mempak=Yes + +[F3515A45EC01D2C9FEAFBAB2B85D72C4] +GoodName=Rugrats in Paris - The Movie (U) [T+Spa0.10] +CRC=40D5D2DE 78489F0F +RefMD5=207EFE58C7C221DBDFFF285AB80126C1 + +[681DF5A32E857E77194106B35304D6B5] +GoodName=Rush 2 - Extreme Racing USA (E) (M6) [!] +CRC=B7CF2136 FA0AA715 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[8A59477C29B4353FEAB85303C58B98F0] +GoodName=Rush 2 - Extreme Racing USA (E) (M6) [h1I] +CRC=09A0A6E5 8396630D +RefMD5=681DF5A32E857E77194106B35304D6B5 + +[E9F65EA602A442966BE4DDCE799A8E20] +GoodName=Rush 2 - Extreme Racing USA (E) (M6) [h2I] +CRC=09A0A6E5 8396630D +RefMD5=681DF5A32E857E77194106B35304D6B5 + +[6A925AB624EE3B343231D799733BA898] +GoodName=Rush 2 - Extreme Racing USA (U) [!] +CRC=EDD6E031 68136013 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[7ED3F10BC32CF76F172D8C31D15A2799] +GoodName=S.C.A.R.S. (E) (M3) [!] +CRC=918E2D60 F865683E +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[0DC80ADCD95AF4FC8FE2C7E648CA64F0] +GoodName=S.C.A.R.S. (E) (M3) [h1C] +CRC=918E2D60 F865683E +RefMD5=7ED3F10BC32CF76F172D8C31D15A2799 + +[D0AA9D20A4B85FE514D2A3150D0133EA] +GoodName=S.C.A.R.S. (U) [!] +CRC=769147F3 2033C10E +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[D0A050E86E27126FD7324B5674A30764] +GoodName=S.C.A.R.S. (U) [f1] (PAL) +CRC=8954584D EFE71E95 +RefMD5=D0AA9D20A4B85FE514D2A3150D0133EA + +[40866BBE1629E9B170DE552ACA83D967] +GoodName=S.C.A.R.S. (U) [t1] +CRC=8954A655 3B38F292 +RefMD5=D0AA9D20A4B85FE514D2A3150D0133EA + +[637A7EA2A39F20C5B20834187230D89D] +GoodName=SD Hiryuu no Ken Densetsu (J) [!] +CRC=EBF5F6B7 C956D739 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[F29A0A02C41815EE3F5437E409EC327B] +GoodName=SD Hiryuu no Ken Densetsu (J) [f1] (PAL) +CRC=EBF5F6B7 C956D739 +RefMD5=637A7EA2A39F20C5B20834187230D89D + +[52FD60268A69DC7B532AD58EDD2133C0] +GoodName=SLiDeS (PD) +CRC=5BBE6E34 088B6D0E +Status=2 +Players=1 +SaveType=None + +[F323E3807A6AEDEDEAC9E0739490D13C] +GoodName=SNES 9X Alpha by Loom-Crazy Nation (PD) [f1] (V64BIOS1.91) +CRC=CA69ECE5 13A88244 + +[29E875C7FFA44CA629F2576CB47A1020] +GoodName=SNES 9X Alpha by Loom-Crazy Nation (PD) +CRC=CA69ECE5 13A88244 + +[919A27C2ABBEA83BA996CEE553227929] +GoodName=SPLiT's Nacho64 by SPLiT (PD) +CRC=1FBD27A9 6CC3EB42 +Players=0 +Status=3 +SaveType=None + +[A63921B3190C45940721BA3AC64D1114] +GoodName=SPLiT's Nacho64 by SPLiT (PD) [f1] (PAL) +CRC=1899FF33 885180E6 +RefMD5=919A27C2ABBEA83BA996CEE553227929 + +[123417811CDC49118EB01ECF76BAF760] +GoodName=SRAM Manager V1.0 Beta (32Mbit) (PD) [a1] +CRC=029CAE05 2B8F9DF1 + +[891E4A11B6F80E31A2F247FEA3730744] +GoodName=SRAM Manager V1.0 Beta (32Mbit) (PD) +CRC=029CAE05 2B8F9DF1 + +[98A5DBA896685D86A07CEEA283FD36D3] +GoodName=SRAM Manager V1.0 Beta (PD) +CRC=029CAE05 2B8F9DF1 + +[57BEB4B0AFDD4AFADE9DB6A13B72D17D] +GoodName=SRAM Manager V1.0 PAL Beta (PD) +CRC=4DEC9986 A8904450 + +[ED46A867A648A101D239DA0650B49783] +GoodName=SRAM Manager V2.0 (PD) [a1] +CRC=4E5507F2 E7D3B413 + +[657836F55DCB952C56BC5C645D82D6C2] +GoodName=SRAM Manager V2.0 (PD) [h1C] +CRC=4E5507F2 E7D3B413 + +[2E8367ED95724816646131BAD480BDD2] +GoodName=SRAM Manager V2.0 (PD) [h2C] +CRC=4E5507F2 E7D3B413 + +[597ADB9702440E72D5954D50671D9C57] +GoodName=SRAM Manager V2.0 (PD) +CRC=4E5507F2 E7D3B413 + +[00F846A9AA9E0083CE8C0E566843A7C7] +GoodName=SRAM Upload Tool (PD) +CRC=98A2BB11 EE4D4A86 + +[2FA1AC0A989D5F081D6A8733F2330923] +GoodName=SRAM Upload Tool + Star Fox 64 SRAM (PD) +CRC=3C524346 E4ABE776 + +[103592E65C65464C141A2184DBFD0947] +GoodName=SRAM Upload Tool V1 by LaC (PD) +CRC=3B8E7E01 6AE876A8 + +[71C2E66CCE1FEC929B5485AC41A61D95] +GoodName=SRAM Upload Tool V1.1 by Lac (PD) [b1] +CRC=98A2BB11 EE4D4A86 + +[2B2186A38B0B3541C3227144EA3C71A3] +GoodName=SRAM Upload Tool V1.1 by Lac (PD) +CRC=3C524346 E4ABE776 + +[F26102590AA6982EA78701E6A418BED0] +GoodName=SRAM Uploader-Editor by BlackBag (PD) +CRC=EC9BECFF CAB83632 + +[A5C1F8AF5D9AA7D2C771DA1C84841017] +GoodName=SRAM to DS1 Tool by WT_Riker (PD) +CRC=52BA5D2A 9BE3AB78 + +[C4E47228706BC724D7FBD811231D20C9] +GoodName=Saikyou Habu Shougi (J) [!] +CRC=5E3E60E8 4AB5D495 +Players=1 +Mempak=Yes + +[D92EEBA87794311C8F4443C29CC177C5] +GoodName=Saikyou Habu Shougi (J) [h1C] +CRC=5E3E60E8 4AB5D495 +RefMD5=C4E47228706BC724D7FBD811231D20C9 + +[0F205BA6B663C3C31579894873CAFA66] +GoodName=Saikyou Habu Shougi (J) [h2C] +CRC=5E3E60E8 4AB5D495 +RefMD5=C4E47228706BC724D7FBD811231D20C9 + +[95C345EE264F3A91F1381E76CAD82F11] +GoodName=Saikyou Habu Shougi (J) [h3C] +CRC=5E3E60E8 4AB5D495 +RefMD5=C4E47228706BC724D7FBD811231D20C9 + +[34F623903C3E2DBF8FB1E47F688D1859] +GoodName=Saikyou Habu Shougi (J) [h4C] +CRC=5E3E60E8 4AB5D495 +RefMD5=C4E47228706BC724D7FBD811231D20C9 + +[630A177A8D5B603F8C86D8A089E3471B] +GoodName=Sample Demo by Florian (PD) [b1] +CRC=C541EAB4 7397CB5F + +[2F8109E5C9BCC45B9987F31EA00ECA66] +GoodName=Sample Demo by Florian (PD) +CRC=C541EAB4 7397CB5F + +[81B1122EE15F7B50A341AE62E9C5716B] +GoodName=San Francisco Rush - Extreme Racing (E) (M3) [!] +CRC=61D116B0 FA24D60C +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[4FDF9E702D4A6A75124623D9434BF99F] +GoodName=San Francisco Rush - Extreme Racing (E) (M3) [h1C] +CRC=61D116B0 FA24D60C +RefMD5=81B1122EE15F7B50A341AE62E9C5716B + +[F015FC28E1D62A36B4EBF4C79CA8F285] +GoodName=San Francisco Rush - Extreme Racing (U) (M3) (V1.0) [!] +CRC=2A6B1820 6ABCF466 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[2A8086945375826FA6495F1EF2F1DFB6] +GoodName=San Francisco Rush - Extreme Racing (U) (M3) (V1.0) [b1] +CRC=2A6B1820 6ABCF466 +RefMD5=F015FC28E1D62A36B4EBF4C79CA8F285 + +[C870967473A8BD2942D00EAA3D7CCC9E] +GoodName=San Francisco Rush - Extreme Racing (U) (M3) (V1.0) [b2] +CRC=2A6B1820 6ABCF466 +RefMD5=F015FC28E1D62A36B4EBF4C79CA8F285 + +[CFD1B123BBABF1658CA6D52F34434A1E] +GoodName=San Francisco Rush - Extreme Racing (U) (M3) (V1.0) [b3] +CRC=2A6B1820 6ABCF466 +RefMD5=F015FC28E1D62A36B4EBF4C79CA8F285 + +[AD921B1336EDA406D124940BED174465] +GoodName=San Francisco Rush - Extreme Racing (U) (M3) (V1.0) [o1] +CRC=2A6B1820 6ABCF466 +RefMD5=F015FC28E1D62A36B4EBF4C79CA8F285 + +[390FC46621581FA62F7F4CC3537F255D] +GoodName=San Francisco Rush - Extreme Racing (U) (M3) (V1.0) [o2] +CRC=2A6B1820 6ABCF466 +RefMD5=F015FC28E1D62A36B4EBF4C79CA8F285 + +[90CA5D19B7F085474EBD2186D70C59AF] +GoodName=San Francisco Rush - Extreme Racing (U) (M3) (V1.0) [o3] +CRC=2A6B1820 6ABCF466 +RefMD5=F015FC28E1D62A36B4EBF4C79CA8F285 + +[5B127E6B090A0B3F68A114D4D89323D4] +GoodName=San Francisco Rush - Extreme Racing (U) (M3) (V1.1) [!] +CRC=AC9F7DA7 A8C029D8 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[02B16AC23998F78F09AF6513F4ACB664] +GoodName=San Francisco Rush 2049 (E) (M6) [!] +CRC=51D29418 D5B46AE3 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[AF5BE0ADFF51A8E9C6D771282C295810] +GoodName=San Francisco Rush 2049 (U) [!] +CRC=B9A9ECA2 17AAE48E +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[1977D63B511A900628DB2A3A104160AC] +GoodName=San Francisco Rush 2049 (U) [t1] +CRC=01D66F37 365F18B3 +RefMD5=AF5BE0ADFF51A8E9C6D771282C295810 + +[3B6DD7B60437234895500BEFF28DF6D6] +GoodName=Scooby-Doo! - Classic Creep Capers (E) [!] +CRC=E3BD221D 3C0834D3 +Players=1 +SaveType=None +Mempak=Yes + +[16CC6DB10A56331B56F374B4FB254D5E] +GoodName=Scooby-Doo! - Classic Creep Capers (U) (V1.0) [!] +CRC=0C814EC4 58FE5CA8 +Players=1 +SaveType=None +Mempak=Yes + +[01CD9938DAE5DCDD4B264AE7F26C6D4D] +GoodName=Scooby-Doo! - Classic Creep Capers (U) (V1.1) [!] +CRC=569433AD F7E13561 +Players=1 +SaveType=None +Mempak=Yes + +[FE2605193736A128AD65DB1C9835A130] +GoodName=Shadow Man (B) [!] +CRC=93A625B9 2D6022E6 +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[A485A6E9E30B7D55D23D8DD043770C64] +GoodName=Shadow Man (E) (M3) [!] +CRC=60C437E5 A2251EE3 +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[235511BBDB21AF5A767BDB7502A80F06] +GoodName=Shadow Man (F) [!] +CRC=EA06F8C3 07C2DEED +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[AF40EF12CE923FF1C26E76CC9D9B9ED9] +GoodName=Shadow Man (G) [!] +CRC=84D5FD75 BBFD3CDF +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[CFBDC1C5E419FF162DF02A0065D9BC1D] +GoodName=Shadow Man (G) [b1] +CRC=84D5FD75 BBFD3CDF +RefMD5=AF40EF12CE923FF1C26E76CC9D9B9ED9 + +[630776E478E00CDA1D09BAB55656ACA7] +GoodName=Shadow Man (G) [b2] +CRC=84D5FD75 BBFD3CDF +RefMD5=AF40EF12CE923FF1C26E76CC9D9B9ED9 + +[0802F5BB4004D8948A6C0B51C8857B74] +GoodName=Shadow Man (G) [f1] (NTSC) +CRC=720278EC 594B7975 +RefMD5=AF40EF12CE923FF1C26E76CC9D9B9ED9 + +[B457298B87B85BBF950F24867DAA9475] +GoodName=Shadow Man (U) [!] +CRC=3A4760B5 2D74D410 +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[474647AEDFA95AEF73229A2784897EDD] +GoodName=Shadow Man (U) [b1] +CRC=3A4760B5 2D74D410 +RefMD5=B457298B87B85BBF950F24867DAA9475 + +[5AE3BB3604539ABDEBA639E5892BD60E] +GoodName=Shadow Man (U) [b2] +CRC=3A4760B5 2D74D410 +RefMD5=B457298B87B85BBF950F24867DAA9475 + +[22A689C97FAEDF39A8F115DB8F71830C] +GoodName=Shadow Man (U) [b3] +CRC=82342320 BC65A550 +RefMD5=B457298B87B85BBF950F24867DAA9475 + +[C76828840668B6F3D4670CF4AD89C4AA] +GoodName=Shadow Man (U) [t1] +CRC=82342320 BC65A550 +RefMD5=B457298B87B85BBF950F24867DAA9475 + +[A06E757CF1930B29FA4C0B5C9F31335F] +GoodName=Shadowgate 64 - Trials Of The Four Towers (E) (M2) (Ita-Spa) [!] +CRC=02B46F55 61778D0B +Players=1 +SaveType=None +Mempak=Yes + +[11169A32D449EC3A8903CA8A9D69A6AA] +GoodName=Shadowgate 64 - Trials Of The Four Towers (E) (M3) (Fre-Ger-Dut) [!] +CRC=2BC1FCF2 7B9A0DF4 +Players=1 +SaveType=None +Mempak=Yes + +[E8955C3B743FDDFE403E52E769E9853F] +GoodName=Shadowgate 64 - Trials Of The Four Towers (E) [!] +CRC=D84EEA84 45B2F1B4 +Players=1 +SaveType=None +Mempak=Yes + +[5582CF3BB6E6B11D6D97F6FDD1EE9A3B] +GoodName=Shadowgate 64 - Trials Of The Four Towers (E) [f1] (NTSC) +CRC=80203B94 57B7F424 +RefMD5=E8955C3B743FDDFE403E52E769E9853F + +[C4F4CA4FFA94A870D0A3E18B74FE9FDE] +GoodName=Shadowgate 64 - Trials Of The Four Towers (J) [b1] +CRC=CCEDB696 D3883DB4 +RefMD5=1960A3879FADF2C5EFF5BEB47E0E1441 + +[66C31F31A386320F61AAF8F5F7936053] +GoodName=Shadowgate 64 - Trials Of The Four Towers (J) [b2] +CRC=CCEDB696 D3883DB4 +RefMD5=1960A3879FADF2C5EFF5BEB47E0E1441 + +[1960A3879FADF2C5EFF5BEB47E0E1441] +GoodName=Shadowgate 64 - Trials Of The Four Towers (J) [!] +CRC=CCEDB696 D3883DB4 +Players=1 +SaveType=None +Mempak=Yes + +[407A1A18BD7DBE0485329296C3F84EB8] +GoodName=Shadowgate 64 - Trials Of The Four Towers (U) (M2) [!] +CRC=036897CE E0D4FA54 +Players=1 +SaveType=None +Mempak=Yes + +[3B21996F8C6496903C01DCBD77DDD6EE] +GoodName=Shadowgate 64 - Trials Of The Four Towers (U) (M2) [f1] (PAL) +CRC=015BB81E F105AC82 +RefMD5=407A1A18BD7DBE0485329296C3F84EB8 + +[3D8F438057CB98F3C9E1472ABFF61610] +GoodName=Shadowgate 64 - Trials Of The Four Towers (U) (M2) [f2] (PAL) +CRC=123D0F44 CF60A446 +RefMD5=407A1A18BD7DBE0485329296C3F84EB8 + +[F6B0E57512FDDD06345DD41B7C73B228] +GoodName=Shag'a'Delic Demo by Steve and NEP (PD) +CRC=9D9C362D 5BE66B08 + +[13893DB9E919C4E7CF0C0B0064CCB554] +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] +CRC=D137A2CA 62B65053 +RefMD5=13893DB9E919C4E7CF0C0B0064CCB554 + +[13D9514A4D208DC6C7B0C833F68114D2] +GoodName=Shin Nihon Pro Wrestling - Toukon Road - Brave Spirits (J) [!] +CRC=EF703CA4 4D4A9AC9 +Players=4 +Mempak=Yes + +[DC1A78608B19DBE2AE3DC0CAD9B79472] +GoodName=Shin Nihon Pro Wrestling - Toukon Road - Brave Spirits (J) [b1] +CRC=EF703CA4 4D4A9AC9 +RefMD5=13D9514A4D208DC6C7B0C833F68114D2 + +[113044B16B75F98792BF9C20C6B6282B] +GoodName=Shin Nihon Pro Wrestling - Toukon Road 2 - The Next Generation (J) [!] +CRC=551C7F43 9149831C +Players=4 +SaveType=SRAM +Mempak=Yes + +[37149C4064A1D120B9F4F5482A915262] +GoodName=Shuffle Puck 64 (PD) +CRC=F7DF7D0D ED52018F + +[244BEA64EA209990E9C69A830B507135] +GoodName=Sim City 2000 (J) [!] +CRC=B1D5280C 4BA7BC2A +Players=1 +Mempak=Yes + +[FD2D06E59BF17A1BD1DA98454F83AB0D] +GoodName=Sim City 2000 (J) [b1] +CRC=B1D5280C 4BA7BC2A +RefMD5=244BEA64EA209990E9C69A830B507135 + +[F0AD16AA47258818D320A5217F2E6B1E] +GoodName=Sim City 2000 (J) [b1][o1] +CRC=B1D5280C 4BA7BC2A +RefMD5=244BEA64EA209990E9C69A830B507135 + +[A698B3419600E7E283AA1313FB2522CF] +GoodName=Sim City 2000 (J) [b2] +CRC=B1D5280C 4BA7BC2A +RefMD5=244BEA64EA209990E9C69A830B507135 + +[65FC73D7ABFFABAFFF3C35FF3CB60DE2] +GoodName=Sim City 2000 (J) [h1C] +CRC=B1D5280C 4BA7BC2A +RefMD5=244BEA64EA209990E9C69A830B507135 + +[137471D67DC8847815E327A73EA30068] +GoodName=Sim City 2000 (J) [o1] +CRC=B1D5280C 4BA7BC2A +RefMD5=244BEA64EA209990E9C69A830B507135 + +[973DE87CFC38353259F3B1F6678FEB76] +GoodName=Sim City 2000 (J) [o1][h1C] +CRC=B1D5280C 4BA7BC2A +RefMD5=244BEA64EA209990E9C69A830B507135 + +[A0E6FB493B57C2FAEE8E517E0330C23E] +GoodName=Sim City 64 (J) [CART HACK] +CRC=909535F8 118FEF8F + +[3E6FF36AE59F9261ED275FEABBF76CED] +GoodName=Simon for N64 V0.1a by Jean-Luc Picard (POM '99) (PD) +CRC=18531B7D 074AF73E +SaveType=None +Mempak=Yes +Status=1 + +[F7F44996DD1140469C6C866DA0AFFAD7] +GoodName=Sinus (PD) +CRC=C603175E ACADF5EC +Status=3 +Players=0 +SaveType=None + +[3194C65208047C938EF443325E1E73C1] +GoodName=Sitero Demo by Renderman (PD) +CRC=9A6CF2F5 D5F365EE + +[5AAC6E652C5CF1E37A466AC0073E88CA] +GoodName=SmashRemix0.9.4 +CRC=1B5AAD82 368B88C1 +Status=3 +SaveType=SRAM +Players=4 +Rumble=Yes +CountPerOp=1 + +[983F8A1D9A8D6AA1A6500AF413CE31FF] +GoodName=SmashRemix0.9.5b +CRC=B9CDC5C3 0D2F4668 +RefMD5=5AAC6E652C5CF1E37A466AC0073E88CA + +[D8D02E6F920E95047071E04420BB7D8F] +GoodName=SmashRemix0.9.7 +CRC=9D2B9C7F 6D90A8EF +RefMD5=5AAC6E652C5CF1E37A466AC0073E88CA + +[8EC29958E0E3EB8C20AB7C9B3ACB07D8] +GoodName=SmashRemix1.0.0 +CRC=FD0E716E FB029C8E +RefMD5=5AAC6E652C5CF1E37A466AC0073E88CA + +[0A6715A80957DD7C58F12E1F33D75F43] +GoodName=SmashRemix1.0.1 +CRC=FDFC3328 A0B2BA23 +RefMD5=5AAC6E652C5CF1E37A466AC0073E88CA + +[D8AB932AFD1CED97ACD33FA984B309ED] +GoodName=SmashRemix1.1.0 +CRC=FB816989 6F442541 +RefMD5=5AAC6E652C5CF1E37A466AC0073E88CA + +[70A61772B2123879367011A5E2900569] +GoodName=SmashRemix1.1.1 +CRC=FB816D35 3FC67AFF +RefMD5=5AAC6E652C5CF1E37A466AC0073E88CA + +[44DE1F9ED1FA35B72D31A1F809285B01] +GoodName=SmashRemix1.2.0 +CRC=A1BFF9C9 8FB192A2 +RefMD5=5AAC6E652C5CF1E37A466AC0073E88CA + +[B8D4B92E66A312708626B3216DE07A3A] +GoodName=Snobow Kids (J) [!] +CRC=84FC04FF B1253CE9 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[A29129B8C044D8A825F7F3780153FCC7] +GoodName=Snobow Kids (J) [h1C] +CRC=84FC04FF B1253CE9 +RefMD5=B8D4B92E66A312708626B3216DE07A3A + +[4379C26BF067F7161BC6629445E22188] +GoodName=Snobow Kids (J) [h2C] +CRC=84FC04FF B1253CE9 +RefMD5=B8D4B92E66A312708626B3216DE07A3A + +[F7E66DA23C8BB8E59F641A636A9CAE82] +GoodName=Snow Speeder (J) [!] +CRC=2EF4D519 C64A0C5E +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[F0FE973338C7170D54CB41602B9D48A3] +GoodName=Snow Speeder (J) [b1] +CRC=2EF4D519 C64A0C5E +RefMD5=F7E66DA23C8BB8E59F641A636A9CAE82 + +[AB4382E583AE139EEDBAFCE5FA87E4C8] +GoodName=Snowboard Kids (E) [!] +CRC=5FD7CDA0 D9BB51AD +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[55D13DC1512B1A3656DB8130E59E31D2] +GoodName=Snowboard Kids (E) [h1C] +CRC=5FD7CDA0 D9BB51AD +RefMD5=AB4382E583AE139EEDBAFCE5FA87E4C8 + +[EB31F4F9C1FE26A3A663F74E9790516E] +GoodName=Snowboard Kids (U) [!] +CRC=DBF4EA9D 333E82C0 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[FB1F9F093F6081E5695F688B9EFD4095] +GoodName=Snowboard Kids (U) [b1] +CRC=DBF4EA9D 333E82C0 +RefMD5=EB31F4F9C1FE26A3A663F74E9790516E + +[4B6914D5552E4FF348FB590D52A6DF8A] +GoodName=Snowboard Kids (U) [b2] +CRC=DBF4EA9D 333E82C0 +RefMD5=EB31F4F9C1FE26A3A663F74E9790516E + +[349FF1B4AE28E31A2B2DC93D76A5219E] +GoodName=Snowboard Kids (U) [b3] +CRC=DBF4EA9D 333E82C0 +RefMD5=EB31F4F9C1FE26A3A663F74E9790516E + +[759DF0ADF7F78D603AD344C89F360E32] +GoodName=Snowboard Kids (U) [h1C] +CRC=DBF4EA9D 333E82C0 +RefMD5=EB31F4F9C1FE26A3A663F74E9790516E + +[641A6513E4FE77B88085478F99F1857D] +GoodName=Snowboard Kids (U) [t1] +CRC=A1E78A63 022A67C9 +RefMD5=EB31F4F9C1FE26A3A663F74E9790516E + +[47B5E3955D54F969941533F26691AB38] +GoodName=Snowboard Kids 2 (E) [!] +CRC=C2751D1A F8C19BFF +SaveType=Eeprom 4KB +Players=4 +Rumble=Yes + +[08E1152E9D9742E9BBF6C224B6958F2D] +GoodName=Snowboard Kids 2 (U) [!] +CRC=930C29EA 939245BF +SaveType=Eeprom 4KB +Players=4 +Rumble=Yes + +[22C7FCDBC74DE237E0FC7778D8A6E671] +GoodName=Snowboard Kids 2 (U) [f1] (PAL) +CRC=D3DF2FEE 8090B699 +RefMD5=08E1152E9D9742E9BBF6C224B6958F2D + +[835B149A0A312262A69DAA010728A825] +GoodName=Snowboard Kids 2 (U) [f2] (PAL) +CRC=D3DF2FEE 8090B699 +RefMD5=08E1152E9D9742E9BBF6C224B6958F2D + +[B7240CADA85A35B6C872A865F6A018A1] +GoodName=Soncrap Intro by RedboX (PD) +CRC=AAA66229 98CA5CAA + +[7D47911B5C3D91A303EF19E764F3C02B] +GoodName=Sonic Wings Assault (J) [!] +CRC=22212351 4046594B +Players=2 +Rumble=Yes +SaveType=Eeprom 4KB + +[D313AF5F8AF4D19F732A1A2C4D4D66BB] +GoodName=South Park (B) [!] +CRC=D21AF769 DE1A0E3D +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[40CC2085A5C12456BEF830B047068326] +GoodName=South Park (E) (M3) [!] +CRC=20B53662 7B61899F +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[26C99A528862342791193CA6AAACC9DD] +GoodName=South Park (E) (M3) [b1] +CRC=20B53662 7B61899F +RefMD5=40CC2085A5C12456BEF830B047068326 + +[7C63BF480D1F84FC2C0D4A959154FA27] +GoodName=South Park (E) (M3) [h1C] +CRC=20B53662 7B61899F +RefMD5=40CC2085A5C12456BEF830B047068326 + +[2C94A246E701D667BA807DAB6C9771E2] +GoodName=South Park (G) [!] +CRC=91B66D42 16AC4E46 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[1730119B0455EF89C4E495DEC8E950A5] +GoodName=South Park (U) [!] +CRC=7ECBE939 3C331795 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[BE22C6B95553B9CD5E0934B66BC36C84] +GoodName=South Park (U) [b1] +CRC=7ECBE939 3C331795 +RefMD5=1730119B0455EF89C4E495DEC8E950A5 + +[6917DEEEBC2FA9E185582215E7460271] +GoodName=South Park (U) [f1] (PAL) +CRC=42EDB4BB DEA42760 +RefMD5=1730119B0455EF89C4E495DEC8E950A5 + +[AC52781C224E9EB0B8F408A782FAC22A] +GoodName=South Park (U) [t1] +CRC=018CF733 5409AD45 +RefMD5=1730119B0455EF89C4E495DEC8E950A5 + +[F1AE48B778C8431A50C37EB1ED96B120] +GoodName=South Park - Chef's Luv Shack (E) [!] +CRC=C00CA948 8E60D34B +Players=4 +SaveType=None + +[6AF573EB055648A8542AA82D9524FB2F] +GoodName=South Park - Chef's Luv Shack (U) [!] +CRC=C00CA948 8E60D34B +Players=4 +SaveType=None + +[FE2AA269FD3EC81C358845BBA6CA0167] +GoodName=South Park - Chef's Luv Shack (U) [f1] (Country Check) +CRC=C19EA928 226B2610 +RefMD5=6AF573EB055648A8542AA82D9524FB2F + +[C33FA02791077A71B0AFE1CFED47C180] +GoodName=South Park Rally (E) [!] +CRC=4F8AFC3A F7912DF2 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[1C494719032FF99382B167C43FB11762] +GoodName=South Park Rally (U) [!] +CRC=07F3B276 EC8F3D39 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[CD17388E175BCF0F621EE9313D5A1C8D] +GoodName=South Park Rally (U) [f1] (PAL) +CRC=A4C8852A E512045C +RefMD5=1C494719032FF99382B167C43FB11762 + +[5DA2C22480A3F6FE9BEF9C6AD4852D37] +GoodName=South Park Rally (U) [t1] +CRC=BE37CDC8 A88CB420 +RefMD5=1C494719032FF99382B167C43FB11762 + +[DDA7AA9C5D1E617DA183750F82B55780] +GoodName=South Park Rally (U) [t2] +CRC=BE37CDC8 A88CB420 +RefMD5=1C494719032FF99382B167C43FB11762 + +[7F9CDBBB1AAAAF0983C64988EF9C58BE] +GoodName=Space Dynamites (J) [!] +CRC=37463412 EAC5388D +Players=2 +SaveType=None + +[19BA66FEE088181BBB0ACA6894BB8971] +GoodName=Space Dynamites (J) [b1] +CRC=37463412 EAC5388D +RefMD5=7F9CDBBB1AAAAF0983C64988EF9C58BE + +[C72417E0F8F043F9F11851633C4B1A57] +GoodName=Space Invaders (U) [!] +CRC=EBFE2397 FF74DA34 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[63FA04C30C4A0FBE162BCDEC3CB42888] +GoodName=Space Invaders (U) [f1] (PAL) +CRC=00EDCC34 75D2DEA0 +RefMD5=C72417E0F8F043F9F11851633C4B1A57 + +[8C87830FF258893C453D70A90F62019F] +GoodName=Space Invaders (U) [t1] +CRC=33828616 933456E0 +RefMD5=C72417E0F8F043F9F11851633C4B1A57 + +[4EE1DC953B1FF209811CF2808D78F064] +GoodName=Space Invaders (U) [t2] +CRC=138D7E56 72BCC9D9 +RefMD5=C72417E0F8F043F9F11851633C4B1A57 + +[FCA7AFCADCF5E5545A62919BA94DAD18] +GoodName=Space Station Silicon Valley (E) (M7) [!] +CRC=FC70E272 08FFE7AA +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[5919371BCA053C750D1CB357C58953A5] +GoodName=Space Station Silicon Valley (E) (M7) [b1] +CRC=FC70E272 08FFE7AA +RefMD5=FCA7AFCADCF5E5545A62919BA94DAD18 + +[E66ED1CC4AB95D0872BB2EBC49B206C4] +GoodName=Space Station Silicon Valley (J) [!] +CRC=BFE23884 EF48EAAF +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[868B37D1B66D1D994E2BAD4E218BF129] +GoodName=Space Station Silicon Valley (U) [!] +CRC=BFE23884 EF48EAAF +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[4A8F8EBB93AF51878C8FB9057AD5F43C] +GoodName=Space Station Silicon Valley (U) [f1] (PAL) +CRC=47F09853 29CCE24F +RefMD5=868B37D1B66D1D994E2BAD4E218BF129 + +[7AE0BA601FD72514C984BC80EE6BAB8E] +GoodName=Space Station Silicon Valley (U) [f2] (PAL) +CRC=BFE23884 EF48EAAF +RefMD5=868B37D1B66D1D994E2BAD4E218BF129 + +[F1F1C5E2B895DB63348BC738C0CDC645] +GoodName=Space Station Silicon Valley (U) (V1.1) [!] +CRC=FC70E272 8FFE7AA +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[630E4122B0743A29C246DA2C257F92DA] +GoodName=Spacer by Memir (POM '99) (PD) +CRC=A3A044B5 6DB1BF5E +Players=4 +Status=3 +SaveType=None +CountPerOp=1 + +[3A6A249843DDEAFFFD334AB3C5931F8D] +GoodName=Spacer by Memir (POM '99) (PD) [t1] +CRC=1B6FAB59 99199038 +RefMD5=630E4122B0743A29C246DA2C257F92DA + +[A8E8AD9B1A05205085DCB4EADBE38020] +GoodName=Spacer by Memir (POM '99) (PD) [t2] +CRC=1B6FAB59 99199038 +RefMD5=630E4122B0743A29C246DA2C257F92DA + +[E8D70E021C40078F8A82318AE8165A73] +GoodName=Spacer by Memir (POM '99) (PD) [t2][b1] +CRC=1B6FAB59 99199038 +RefMD5=630E4122B0743A29C246DA2C257F92DA + +[44D7F3FC23428913D10E68017ACB097F] +GoodName=Spice Girls Rotator Demo by RedboX (PD) [a1] +CRC=8F5179C4 803526DC + +[1934618C99A70DD8E74305C6DB06CAF3] +GoodName=Spice Girls Rotator Demo by RedboX (PD) +CRC=8F5179C4 803526DC + +[7F1991B8861E7E532EC21ECF2AF82191] +GoodName=Spider-Man (U) [!] +CRC=A60ED171 3D85D06E +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes + +[8C5D52229DA5A223EA2DA093A5B9D31B] +GoodName=Spider-Man (U) [t1] +CRC=3E6250B2 12F5155C +RefMD5=7F1991B8861E7E532EC21ECF2AF82191 + +[041CE6116C560C239023EFB88705DA94] +GoodName=Split! 3D Demo by Lem (PD) +CRC=60B8BCC9 2EC4DFB6 + +[515C86480A7FC1238BFE252BD2C53B36] +GoodName=Sporting Clays by Charles Doty (PD) +CRC=E584FE34 9D91B1E2 +Players=1 +SaveType=None +Status=3 + +[993CCC0961CFD9F1342AD99A1BA2E282] +GoodName=Sporting Clays by Charles Doty (PD) [a1] +CRC=5402C27E 60021F86 +RefMD5=515C86480A7FC1238BFE252BD2C53B36 + +[094FE60C44F35BDC7FBE85339E9C4470] +GoodName=Sporting Clays by Charles Doty (PD) [b1] +CRC=E584FE34 9D91B1E2 +RefMD5=515C86480A7FC1238BFE252BD2C53B36 + +[B2242070800BF82E78CE33DC92A1DB84] +GoodName=Star Fox 64 (Ch) (V5) (iQue) [!] + +[3DCD5E15AA35A73C68DB4F56E2670FA2] +GoodName=Star Fox 64 (Ch) (V4) (iQue) (Manual) [!] + +[446D5215C4D34EB8AB0F355F324B8D0E] +GoodName=Star Fox 64 (J) (V1.0) [!] +CRC=FFCAA7C1 68858537 +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes + +[C4179723DC6E5D319C97F2F66AB05162] +GoodName=Star Fox 64 (J) (V1.0) [f1] +CRC=FFCAA7C1 68858537 +RefMD5=446D5215C4D34EB8AB0F355F324B8D0E + +[D0DD14F100B3825536DB8F32C332457F] +GoodName=Star Fox 64 (J) (V1.0) [o1] +CRC=FFCAA7C1 68858537 +RefMD5=446D5215C4D34EB8AB0F355F324B8D0E + +[D43D1E41DBA17FFF92829FD2495B7619] +GoodName=Star Fox 64 (J) (V1.0) [o1][f1] +CRC=FFCAA7C1 68858537 +RefMD5=446D5215C4D34EB8AB0F355F324B8D0E + +[0C9F7FA54CA36BFC6D8BE4187E4ABD99] +GoodName=Star Fox 64 (J) (V1.0) [o2][f1] +CRC=FFCAA7C1 68858537 +RefMD5=446D5215C4D34EB8AB0F355F324B8D0E + +[B74F70654B2FE3FC573D3BC913A62268] +GoodName=Star Fox 64 (J) (V1.0) [o3][f1] +CRC=FFCAA7C1 68858537 +RefMD5=446D5215C4D34EB8AB0F355F324B8D0E + +[AF8A5A437F286FA230D99507109C79D9] +GoodName=Star Fox 64 (J) (V1.0) [t1] (Boost) +CRC=305AB328 F72F632A +RefMD5=446D5215C4D34EB8AB0F355F324B8D0E + +[5E3B1FAC7C16D30499B3FAA36CAF98FD] +GoodName=Star Fox 64 (J) (V1.0) [t2] (No Damage-Unbreakable Wings) +CRC=1180A247 EBE234B3 +RefMD5=446D5215C4D34EB8AB0F355F324B8D0E + +[91FC4C63CA613530DF22C8BB810CB2C3] +GoodName=Star Fox 64 (J) (V1.1) (VC) [!] +CRC=65AEDEEF 3857C728 +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes + +[CAF9A78DB13EE00002FF63A3C0C5EABB] +GoodName=Star Fox 64 (U) (V1.0) [!] +CRC=A7D015F8 2289AA43 +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes + +[5653B6DDAE328C870138E71EC30122A1] +GoodName=Star Fox 64 (U) (V1.0) [f1] +CRC=A7D015F8 2289AA43 +RefMD5=CAF9A78DB13EE00002FF63A3C0C5EABB + +[ECB9184142D288B40BCD198FB191A275] +GoodName=Star Fox 64 (U) (V1.0) [f1][h1C] +CRC=A7D015F8 2289AA43 +RefMD5=CAF9A78DB13EE00002FF63A3C0C5EABB + +[E566D58641BEDD25C450E443608EB46E] +GoodName=Star Fox 64 (U) (V1.0) [f1][o1] +CRC=A7D015F8 2289AA43 +RefMD5=CAF9A78DB13EE00002FF63A3C0C5EABB + +[D81FFD06311AB9334858CCC28EFE992A] +GoodName=Star Fox 64 (U) (V1.0) [f2] (PAL) +CRC=CBD83828 6FDEBEDC +RefMD5=CAF9A78DB13EE00002FF63A3C0C5EABB + +[7052F9C1BE69B103D6BE3DE61A94F861] +GoodName=Star Fox 64 (U) (V1.0) [h1C] +CRC=A7D015F8 2289AA43 +RefMD5=CAF9A78DB13EE00002FF63A3C0C5EABB + +[80E9D39B21E537FF53FD362B7272F255] +GoodName=Star Fox 64 (U) (V1.0) [o1][f1] +CRC=A7D015F8 2289AA43 +RefMD5=CAF9A78DB13EE00002FF63A3C0C5EABB + +[06DB24BEFB76C04D06D4DDC3A50D5319] +GoodName=Star Fox 64 (U) (V1.0) [o2][f1] +CRC=CBD83828 6FDEBEDC +RefMD5=CAF9A78DB13EE00002FF63A3C0C5EABB + +[831DC9EEB9114912ABABC15B6B14DA4B] +GoodName=Star Fox 64 (U) (V1.0) [o3][f1] +CRC=A7D015F8 2289AA43 +RefMD5=CAF9A78DB13EE00002FF63A3C0C5EABB + +[23E5AF30267036A69A8328F005DF07B1] +GoodName=Star Fox 64 (U) (V1.0) [t1] +CRC=CBD83828 6FDEBEDC +RefMD5=CAF9A78DB13EE00002FF63A3C0C5EABB + +[3D38BCD5B57CEECB0985609CCE940FFA] +GoodName=Star Fox 64 (U) (V1.0) [t2] (Boost) +CRC=1B80E202 CB5AE74F +RefMD5=CAF9A78DB13EE00002FF63A3C0C5EABB + +[63CE29BBA130AACD05402EFC06C0DC89] +GoodName=Star Fox 64 (U) (V1.0) [t3] (No Damage-Unbreakable Wings) +CRC=F6621BFB 186D11A6 +RefMD5=CAF9A78DB13EE00002FF63A3C0C5EABB + +[741A94EEE093C4C8684E66B89F8685E8] +GoodName=Star Fox 64 (U) (V1.1) [!] +CRC=BA780BA0 0F21DB34 +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes + +[F0CD3B2DB0F20FFDD64BF081176EB421] +GoodName=Star Fox 64 (U) (V1.1) [t1] (Energy) +CRC=C3CA0BA3 25397DC8 +RefMD5=741A94EEE093C4C8684E66B89F8685E8 + +[FFA562936DB863EA02204F9F514B6067] +GoodName=Star Fox 64 (U) (V1.1) [t2] (Boost) +CRC=8264014A 3C9FBFC1 +RefMD5=741A94EEE093C4C8684E66B89F8685E8 + +[14A21928BE46C18BA04161305E89F5DE] +GoodName=Star Soldier - Vanishing Earth (J) [!] +CRC=B703EB23 28AAE53A +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[565DA8D53422F16207ECF11A81D2E649] +GoodName=Star Soldier - Vanishing Earth (J) [b1] +CRC=B703EB23 28AAE53A +RefMD5=14A21928BE46C18BA04161305E89F5DE + +[006CAFEC9BA13060D4D2F0BE211081BD] +GoodName=Star Soldier - Vanishing Earth (J) [h1C] +CRC=B703EB23 28AAE53A +RefMD5=14A21928BE46C18BA04161305E89F5DE + +[97275F6585547462A73910E9A80E4067] +GoodName=Star Soldier - Vanishing Earth (J) [o1] +CRC=B703EB23 28AAE53A +RefMD5=14A21928BE46C18BA04161305E89F5DE + +[CD40D9DD238E23AD79DC4484F77A7C4A] +GoodName=Star Soldier - Vanishing Earth (J) [t1] +CRC=31100ADC 86E97D63 +RefMD5=14A21928BE46C18BA04161305E89F5DE + +[EE045A2E9F924CD8FD00018B50E46650] +GoodName=Star Soldier - Vanishing Earth (U) [!] +CRC=DDD93C85 DAE381E8 +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[A68B65E6B4BC976AD9DEAB335DE3BF70] +GoodName=Star Soldier - Vanishing Earth (U) [t1] +CRC=DDD982EF 3B0D6FEC +RefMD5=EE045A2E9F924CD8FD00018B50E46650 + +[0529542DE0794316320CF99EA80C51B7] +GoodName=Star Soldier - Vanishing Earth Arcade (Aleck64) +CRC=315C7466 3A453265 +SaveType=Eeprom 4KB + +[CA28A3645FC7AD969EBD75C5D6506E7A] +GoodName=Star Twins (J) [!] +CRC=F163A242 F2449B3B +Players=4 +SaveType=Flash RAM +Rumble=Yes + +[7F919D2E35CBE561E139AE8FE93ACA86] +GoodName=Star Wars - Rogue Squadron (E) (M3) (V1.0) [!] +CRC=7EE0E8BB 49E411AA +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[E1376F9B151EE3DA3E8ED52D970480EF] +GoodName=Star Wars - Rogue Squadron (E) (M3) (V1.0) (Language Select Hack) +CRC=7EE0E945 7D8FEE20 +RefMD5=7F919D2E35CBE561E139AE8FE93ACA86 + +[231F61E0D66A70B173BB22672EE67BD6] +GoodName=Star Wars - Rogue Squadron (E) (M3) (V1.0) [t1] +CRC=5E6508BB F321C996 +RefMD5=7F919D2E35CBE561E139AE8FE93ACA86 + +[A9DD498E6A28F55311CE4EF057E164B8] +GoodName=Star Wars - Rogue Squadron (E) (M3) (V1.1) [!] +CRC=219191C1 33183C61 +RefMD5=7F919D2E35CBE561E139AE8FE93ACA86 + +[47CAC4E2A6309458342F21A9018FFBF0] +GoodName=Star Wars - Rogue Squadron (U) (M3) (V1.0) [!] +CRC=66A24BEC 2EADD94F +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[0583AD9FDD1E3D10076AAB40E5B4E7BB] +GoodName=Star Wars - Rogue Squadron (U) (M3) (V1.0) [b1] +CRC=66A24BEC 2EADD94F +RefMD5=47CAC4E2A6309458342F21A9018FFBF0 + +[6560FFC9208A31F0518036F7937B53DA] +GoodName=Star Wars - Rogue Squadron (U) (M3) (V1.0) [h1] (Language Select) +CRC=66A24A12 22AF6AC2 +RefMD5=47CAC4E2A6309458342F21A9018FFBF0 + +[4903C39007AEACC113FE0E9E4BBE4711] +GoodName=Star Wars - Rogue Squadron (U) (M3) (V1.0) [t1] +CRC=165CBDA2 05A62246 +RefMD5=47CAC4E2A6309458342F21A9018FFBF0 + +[2E458D7CC355D7918493B0E0362C9A20] +GoodName=Star Wars - Rogue Squadron (U) (M3) (V1.1) [!] +CRC=C7F30CFA ECB0FA36 +RefMD5=47CAC4E2A6309458342F21A9018FFBF0 + +[591CF8E672C9CC0FE9C871CC56DCC854] +GoodName=Star Wars - Shadows of the Empire (E) [!] +CRC=4D486681 AB7D9245 +Players=1 +SaveType=Eeprom 4KB + +[818737338B3F1D87B7E1B7FB55057BB5] +GoodName=Star Wars - Shadows of the Empire (E) [b1] +CRC=4D486681 AB7D9245 +RefMD5=591CF8E672C9CC0FE9C871CC56DCC854 + +[E83325EC6E8520B0CBDB49B52418FE4E] +GoodName=Star Wars - Shadows of the Empire (E) [b2] +CRC=4D486681 AB7D9245 +RefMD5=591CF8E672C9CC0FE9C871CC56DCC854 + +[64E59BA2F7BA4DAFFDD5934F818DC7DA] +GoodName=Star Wars - Shadows of the Empire (E) [b3] +CRC=4D486681 AB7D9245 +RefMD5=591CF8E672C9CC0FE9C871CC56DCC854 + +[554BFCC857BE49B2AACD077E6059B281] +GoodName=Star Wars - Shadows of the Empire (E) [b4] +CRC=4D486681 AB7D9245 +RefMD5=591CF8E672C9CC0FE9C871CC56DCC854 + +[30BDF5405A8C615DC924DB9480E996B7] +GoodName=Star Wars - Shadows of the Empire (E) [o1] +CRC=4D486681 AB7D9245 +RefMD5=591CF8E672C9CC0FE9C871CC56DCC854 + +[4076973CFDA277FC876E9F066CC73DEB] +GoodName=Star Wars - Shadows of the Empire (U) (Prototype) +CRC=FB315F95 7786CBFB + +[5CCE8AD5F86E8A373A7525DC4C7E6705] +GoodName=Star Wars - Shadows of the Empire (U) (V1.0) [!] +CRC=264D7E5C 18874622 +Players=1 +SaveType=Eeprom 4KB + +[C88637DCC7A00FED6297B61E79CF75A9] +GoodName=Star Wars - Shadows of the Empire (U) (V1.0) [b1] +CRC=BC3C9F6C 93B3CB13 +RefMD5=5CCE8AD5F86E8A373A7525DC4C7E6705 + +[C68CB260A7FD8D177640FA487DCCACF6] +GoodName=Star Wars - Shadows of the Empire (U) (V1.0) [b2] +CRC=BDA75F12 BDDC1661 +RefMD5=5CCE8AD5F86E8A373A7525DC4C7E6705 + +[7527B90543E3D6042A72619818B47145] +GoodName=Star Wars - Shadows of the Empire (U) (V1.0) [o1] +CRC=264D7E5C 18874622 +RefMD5=5CCE8AD5F86E8A373A7525DC4C7E6705 + +[C69FA82E2CA2460000C629E9D46D4DC2] +GoodName=Star Wars - Shadows of the Empire (U) (V1.0) [t1] +CRC=BC3C9F6C 93B3CB13 +RefMD5=5CCE8AD5F86E8A373A7525DC4C7E6705 + +[F8906B10BAE363ACB170FA841A88E96C] +GoodName=Star Wars - Shadows of the Empire (U) (V1.0) [t2] +CRC=BDA75F12 BDDC1661 +RefMD5=5CCE8AD5F86E8A373A7525DC4C7E6705 + +[FA635E837275D28FD5A24D5675BA42C8] +GoodName=Star Wars - Shadows of the Empire (U) (V1.1) [!] +CRC=4147B091 63251060 +Players=1 +SaveType=Eeprom 4KB + +[E8EE7D44858C1AB90C1F48A649DC98B6] +GoodName=Star Wars - Shadows of the Empire (U) (V1.1) [b1] +CRC=D3E792A5 05D39C97 +RefMD5=FA635E837275D28FD5A24D5675BA42C8 + +[64B4FB2D4C49AE6902F13149C81CF2A1] +GoodName=Star Wars - Shadows of the Empire (U) (V1.1) [o1] +CRC=4147B091 63251060 +RefMD5=FA635E837275D28FD5A24D5675BA42C8 + +[7BC08EAF55A645DE9226617C3F83B19F] +GoodName=Star Wars - Shadows of the Empire (U) (V1.1) [t1] +CRC=D3E792A5 05D39C97 +RefMD5=FA635E837275D28FD5A24D5675BA42C8 + +[C7B40352AAD8D863D88D51672F9A0087] +GoodName=Star Wars - Shadows of the Empire (U) (V1.2) [!] +CRC=4DD7ED54 74F9287D +Players=1 +SaveType=Eeprom 4KB + +[3FE2B38E18152162A34E3002DEA071F7] +GoodName=Star Wars - Shadows of the Empire (U) (V1.2) [b1] +CRC=D3E792A5 05D39C97 +RefMD5=C7B40352AAD8D863D88D51672F9A0087 + +[3BD4EE76D4CBB14D69BA628533BD7CBC] +GoodName=Star Wars - Shadows of the Empire (U) (V1.2) [b2] +CRC=D3E792A5 05D39C97 +RefMD5=C7B40352AAD8D863D88D51672F9A0087 + +[CD2C0DFDAC5572988AAB98D125EEEB53] +GoodName=Star Wars - Shadows of the Empire (U) (V1.2) [o1] +CRC=4DD7ED54 74F9287D +RefMD5=C7B40352AAD8D863D88D51672F9A0087 + +[8603B180E70B2A72EF77D46C2BEC2234] +GoodName=Star Wars - Shutsugeki! Rogue Chuutai (J) [!] +CRC=827E4890 958468DC +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[5B6B6B0C8C9A40286DCF61706B6A05CB] +GoodName=Star Wars - Teikoku no Kage (J) [!] +CRC=FE24AC63 1B41AA17 +Players=1 +SaveType=Eeprom 4KB + +[B5FDFDF26E1F27EAF0BD849CAA4CC3B8] +GoodName=Star Wars - Teikoku no Kage (J) [o1] +CRC=FE24AC63 1B41AA17 +RefMD5=5B6B6B0C8C9A40286DCF61706B6A05CB + +[222F1E75F70A654B642382989E024749] +GoodName=Star Wars - Teikoku no Kage (J) [o2] +CRC=FE24AC63 1B41AA17 +RefMD5=5B6B6B0C8C9A40286DCF61706B6A05CB + +[0BD1F7BB9F4B02520E4E9285C809F099] +GoodName=Star Wars Episode I - Battle for Naboo (E) [!] +CRC=EAE6ACE2 020B4384 +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes +CountPerOp=1 + +[3CB88B934572E7520F35E5458798775B] +GoodName=Star Wars Episode I - Battle for Naboo (U) [!] +CRC=3D02989B D4A381E2 +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes +CountPerOp=1 + +[B4724120C269A1DC86991D34B1561F3D] +GoodName=Star Wars Episode I - Battle for Naboo (U) [b1] +CRC=3D02989B D4A381E2 +RefMD5=3CB88B934572E7520F35E5458798775B + +[24E6E064454DE99C88EBA9F8C3574AF3] +GoodName=Star Wars Episode I - Battle for Naboo (U) [t1] +CRC=FD8F6875 42608FDC +RefMD5=3CB88B934572E7520F35E5458798775B + +[6EF9FED309F28BD59B605F128869AA00] +GoodName=Star Wars Episode I - Racer (E) (M3) [!] +CRC=53ED2DC4 06258002 +Players=2 +SaveType=Eeprom 16KB +Rumble=Yes + +[8CC7E31925FBFA13A584F529E8912207] +GoodName=Star Wars Episode I - Racer (E) (M3) [f1] (Save) +CRC=166312CB C30220D2 +RefMD5=6EF9FED309F28BD59B605F128869AA00 + +[7579AB0E79B1011479B88F2BF39D48E0] +GoodName=Star Wars Episode I - Racer (J) [!] +CRC=61F5B152 046122AB +Players=2 +SaveType=Eeprom 16KB +Rumble=Yes + +[CFA21E43DAC50DFF3122ABF3AF3511F8] +GoodName=Star Wars Episode I - Racer (J) [b1] +CRC=61F5B152 046122AB +RefMD5=7579AB0E79B1011479B88F2BF39D48E0 + +[1EE8800A4003E7F9688C5A35F929D01B] +GoodName=Star Wars Episode I - Racer (U) [!] +CRC=72F70398 6556A98B +Players=2 +SaveType=Eeprom 16KB +Rumble=Yes + +[E4353B43CB4302B7A308A42D6BB04435] +GoodName=Star Wars Episode I - Racer (U) [f1] (Save) +CRC=86EDC3C1 E983A7BF +RefMD5=1EE8800A4003E7F9688C5A35F929D01B + +[D6EED7BA15E4CF88B4D235A016B1C880] +GoodName=Star Wars Episode I - Racer (U) [t1] +CRC=C3193C16 53A19708 +RefMD5=1EE8800A4003E7F9688C5A35F929D01B + +[81FE5AD03175B6F2D23DBF5A549B0CDA] +GoodName=Star Wars Episode I - Racer (U) [t2] +CRC=1C37BF54 AC368304 +RefMD5=1EE8800A4003E7F9688C5A35F929D01B + +[0BE4958B3E8EED916307DC9F5DE3206D] +GoodName=Star Wars Episode I - Racer (U) [t3] +CRC=88C79381 85786A83 +RefMD5=1EE8800A4003E7F9688C5A35F929D01B + +[F21C920F0A7BF42F80C38C39CD61BD60] +GoodName=Star Wars Episode I - Racer (U) [t4] +CRC=B722133E 5EECEC4D +RefMD5=1EE8800A4003E7F9688C5A35F929D01B + +[3EB732A8D004263AD8EB0DA59A29582A] +GoodName=StarCraft 64 (Beta) +CRC=BC9B2CC3 4ED04DA5 +Status=1 +Players=2 +SaveType=Flash RAM +Rumble=Yes + +[432DF5EAC0BA573C6587A5BB4E51834A] +GoodName=StarCraft 64 (Beta) [f1] +CRC=BC9B2CC3 4ED04DA5 +RefMD5=3EB732A8D004263AD8EB0DA59A29582A + +[30486A26C7B87CDBDB1A421493CC745A] +GoodName=StarCraft 64 (Beta) [f2] (PAL) +CRC=036A20D8 A99C4D3D +RefMD5=3EB732A8D004263AD8EB0DA59A29582A + +[A9683B99E82271DBF84DDB59806E9423] +GoodName=StarCraft 64 (Beta) [f3] (Country Code) +CRC=BC9B2CC3 4ED04DA5 +RefMD5=3EB732A8D004263AD8EB0DA59A29582A + +[72B60FAC5EE257FA387B43C57632D50C] +GoodName=StarCraft 64 (E) [!] +CRC=42CF5EA3 9A1334DF +Status=1 +Players=2 +SaveType=Flash RAM +Rumble=Yes + +[B75945407D7DEA00A2A29AD24056A416] +GoodName=StarCraft 64 (E) [b1] +CRC=42CF5EA3 9A1334DF +RefMD5=72B60FAC5EE257FA387B43C57632D50C + +[762543CC6409C199FD50A3BCF545730D] +GoodName=StarCraft 64 (E) [f1] (NTSC) +CRC=C7501968 06533B11 +RefMD5=72B60FAC5EE257FA387B43C57632D50C + +[356A5D3D59E0ADEF6EFAE6096FC20F77] +GoodName=StarCraft 64 (G) (Prototype) +CRC=FD6907F0 83CBC160 + +[559F71B861F639B6376D891E3023414B] +GoodName=StarCraft 64 (U) [!] +CRC=0684FBFB 5D3EA8A5 +Status=1 +Players=2 +SaveType=Flash RAM +Rumble=Yes + +[A9C393AA232B32798ADF378F4318F99F] +GoodName=Starshot - Space Circus Fever (E) (M3) [!] +CRC=D89E0E55 B17AA99A +Players=1 +SaveType=Eeprom 4KB + +[B23BFC7DC874DDAA2005F9AFF59A47FF] +GoodName=Starshot - Space Circus Fever (E) (M3) [f1] (NTSC100%) +CRC=287AAA27 8C2C02D8 +RefMD5=A9C393AA232B32798ADF378F4318F99F + +[AA11E9E44B401794C37290896C9412AC] +GoodName=Starshot - Space Circus Fever (E) (M3) [f2] (NTSC) +CRC=AD199971 1075F279 +RefMD5=A9C393AA232B32798ADF378F4318F99F + +[BAE518E0D40F846B17C510E4EA9E8C52] +GoodName=Starshot - Space Circus Fever (E) (M3) [f3] (NTSC) +CRC=ADD78971 A09C18CF +RefMD5=A9C393AA232B32798ADF378F4318F99F + +[530B796EA3B1748841F9D057F3F9EFA8] +GoodName=Starshot - Space Circus Fever (E) (M3) [t1] +CRC=AD197171 04DB7E9E +RefMD5=A9C393AA232B32798ADF378F4318F99F + +[42AF1992978229BBB5F560571708E25E] +GoodName=Starshot - Space Circus Fever (U) (M3) [!] +CRC=94EDA5B8 8673E903 +Players=1 +SaveType=Eeprom 4KB + +[BD22A79568534B42EAA3D8DB9A7C4C91] +GoodName=Starshot - Space Circus Fever (U) (M3) [b1] +CRC=94EDA5B8 8673E903 +RefMD5=42AF1992978229BBB5F560571708E25E + +[E8B666A429FEDB2A1A1228CD450CD4FC] +GoodName=Stunt Racer 64 (U) [!] +CRC=9510D8D7 35100DD2 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[14DDF19382385774F253049ABEAF01D2] +GoodName=Summer64 Demo by Lem (PD) [b1] +CRC=4794B85F 3EBD5B68 + +[1B1DC8B1DD950E70C0F532DD81C9A982] +GoodName=Summer64 Demo by Lem (PD) +CRC=4794B85F 3EBD5B68 + +[B3C1D4B9EC7DCD2922E681DBBC393915] +GoodName=Super B-Daman - Battle Phoenix 64 (J) [!] +CRC=F4646B69 C5751095 +Players=4 +Mempak=Yes +Transferpak=Yes + +[4168C145279EA29912BA0E35DCA35289] +GoodName=Super Bomberman 2 by Rider (POM '99) (PD) +CRC=BB214F79 8B88B16B +Status=1 +Players=4 + +[09C5B4D19364EFE48BB818087734978E] +GoodName=Super Bowling (J) [!] +CRC=F3F2F385 6E490C7F +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[FA3A043997A3ACDF17337385B126BC04] +GoodName=Super Bowling (U) [!] +CRC=AA1D215A 91CBBE9A +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[7FCF424B960F4E429FD683A4B19B3356] +GoodName=Super Fighter Demo Halley's Comet Software (PD) +CRC=1AD61BB9 F1E2BE1A + +[A215BC1CE06960E0C469DB9520E907C6] +GoodName=Super Irishley Drunk Giant WaLuigi 64 (Super Mario 64 Hack) +CRC=635A42C5 BDC58EDC + +[29047FBA820695BD14C5BD7AA1AA4400] +GoodName=Super Mario 64 (Ch) (iQue) [!] +Players=1 + +[B4BD31B13E474DF29922150E1EF3F328] +GoodName=Super Mario 64 (Ch) (V6) (iQue) (Manual) [!] + +[45676429EF6B90E65B517129B700308E] +GoodName=Super Mario 64 (E) (M3) [!] +CRC=A03CF036 BCC1C5D2 +Players=1 +Status=4 +SaveType=Eeprom 4KB + +[9EE432F07F1E4E9A13CD0090CCC5A94B] +GoodName=Super Mario 64 (E) (M3) [b1] +CRC=A03CF036 BCC1C5D2 +RefMD5=45676429EF6B90E65B517129B700308E + +[225223ABF4BC1F3E38A45873BA94CEBC] +GoodName=Super Mario 64 (E) (M3) [b2] +CRC=A03CF036 BCC1C5D2 +RefMD5=45676429EF6B90E65B517129B700308E + +[6A954E08533C13DBD7599068D03A3ADB] +GoodName=Super Mario 64 (E) (M3) [h1C] +CRC=A03CF036 BCC1C5D2 +RefMD5=45676429EF6B90E65B517129B700308E + +[D1F6BC22557BF5607AA2E3C61BE44D59] +GoodName=Super Mario 64 (E) (M3) [o1] +CRC=A03CF036 BCC1C5D2 +RefMD5=45676429EF6B90E65B517129B700308E + +[DF2031338C9B0AB8317661AFA64E5F9E] +GoodName=Super Mario 64 (E) (M3) [o2] +CRC=A03CF036 BCC1C5D2 +RefMD5=45676429EF6B90E65B517129B700308E + +[121A19E2A547C554155433788986033C] +GoodName=Super Mario 64 (E) (M3) [t1] +CRC=77C44B0F 5E8948A3 +RefMD5=45676429EF6B90E65B517129B700308E + +[994D171A0154ABE747338890AF179252] +GoodName=Super Mario 64 (E) (M3) [t2] +CRC=16510823 E2EEE387 +RefMD5=45676429EF6B90E65B517129B700308E + +[85D61F5525AF708C9F1E84DCE6DC10E9] +GoodName=Super Mario 64 (J) [!] +CRC=4EAA3D0E 74757C24 +Players=1 +Status=4 +SaveType=Eeprom 4KB + +[DBF7F4D881E1DF604C41367B04233E74] +GoodName=Super Mario 64 (J) [h1C] +CRC=4EAA3D0E 74757C24 +RefMD5=85D61F5525AF708C9F1E84DCE6DC10E9 + +[20B854B239203BAF6C961B850A4A51A2] +GoodName=Super Mario 64 (U) [!] +CRC=635A2BFF 8B022326 +Players=1 +Status=4 +SaveType=Eeprom 4KB + +[E458F74E694B2916EBA9818103F7CF13] +GoodName=Super Mario 64 (U) (Enable Hidden Scroller Hack) +CRC=DACDE68E 7381B3C9 +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[FF5A05FFDE29707C15D89E807ED66B81] +GoodName=Super Mario 64 (U) (No Cap Hack) +CRC=5B5DA9FB 11EEE5E5 +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[6C5AEE2BE768E581038F3B211D7F6066] +GoodName=Super Mario 64 (U) (Silver Mario Hack) +CRC=658E2804 443386FA +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[597204EE766B93C1AE33B7FC0739E170] +GoodName=Super Mario 64 (U) [T+Rus] +CRC=267FBAD5 7593FADC +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[E51A6FF9B2DBBD216158CACFF35EB215] +GoodName=Super Mario 64 (U) [T+SpaFinal_Mistergame] +CRC=635A42C5 BDC58EDC +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[99BD941850AA68440B886EA05539F7DC] +GoodName=Super Mario 64 (U) [T+SpaFinal_Mistergame][a1] +CRC=635A42C5 BDC58EDC +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[35BBAF4869D0B0D2147D35F1EC3CF2CA] +GoodName=Super Mario 64 (U) [T-Ita1.0final_beta1_Rulesless] +CRC=819D5B33 A5096295 +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[CDACC6FE2CC7851A1110A60CE76FBDFB] +GoodName=Super Mario 64 (U) [T+Ita2.0final_beta2_Rulesless] +CRC=490A59F2 22BC515E +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[933C474FC970A0E7D659F32334DB6475] +GoodName=Super Mario 64 (U) [b1] +CRC=635A2BFF 8B022326 +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[0513A584BC6B3859555E72E10008B55F] +GoodName=Super Mario 64 (U) [b2] +CRC=77C44B0F 5E8948A3 +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[C3A4EBEEA4D22D8FC245B346D5C1A81E] +GoodName=Super Mario 64 (U) [h1C] +CRC=635A2BFF 8B022326 +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[179537A49DAA33BF031F09A9589EAA28] +GoodName=Super Mario 64 (U) [h2C] +CRC=635A2BFF 8B022326 +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[AED29A731056F34B79E6B996BDBAFB63] +GoodName=Super Mario 64 (U) [o1] +CRC=635A2BFF 8B022326 +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[3F3EBFAD624D623FAFEF767B99609E15] +GoodName=Super Mario 64 (U) [t1] (Invincible) +CRC=5C8BD407 63F71E2A +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[B48A8F8E2D9C7403210C2AA5262D94C7] +GoodName=Super Mario 64 (U) [t2] (Speed) +CRC=5B652BFF 8FA82E35 +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[C293D2ADF01E0528554CDBADF0F86554] +GoodName=Super Mario 64 (U) [t3] +CRC=FECE2B85 331406D1 +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[A75637B1D22F59F2C32BDA359A9EE79E] +GoodName=Super Mario Magic Plant Adventure 64 (Super Mario 64 Hack) +CRC=635A42C5 BDC58EDC +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[338FAA6E250F72F1B1D7B873BFAEE918] +GoodName=SM64 Splitscreen Multiplayer Beta +CRC=5C277FBA E8A351C9 +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[F0595A36EAB6109C5FF2420EB452B6E2] +GoodName=SM64 Splitscreen Multiplayer +CRC=13CD0830 3CCF65E9 +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[2D727C3278AA232D94F2FB45AEC4D303] +GoodName=Super Mario 64 - Shindou Edition (J) [!] +CRC=D6FBA4A8 6326AA2C +Players=1 +Status=4 +SaveType=Eeprom 4KB +Rumble=Yes + +[23033085561CD331CC81F0026FCB2CE2] +GoodName=Super Mario 64 - Shindou Edition (J) [b1] +CRC=D6FBA4A8 6326AA2C +RefMD5=2D727C3278AA232D94F2FB45AEC4D303 + +[8C361E9283D740E2F266782D9C1CE914] +GoodName=Super Mario 64 - Shindou Edition (J) [b2] +CRC=D6FBA4A8 6326AA2C +RefMD5=2D727C3278AA232D94F2FB45AEC4D303 + +[E824B289A850E7E161AF761D876F1CAE] +GoodName=Super Mario 64 - Shindou Edition (J) [h1C] +CRC=D6FBA4A8 6326AA2C +RefMD5=2D727C3278AA232D94F2FB45AEC4D303 + +[7BA990008966BDA71D8CB78FB7BA414E] +GoodName=Super Mario 64 - Shindou Edition (J) [h2C] +CRC=D6FBA4A8 6326AA2C +RefMD5=2D727C3278AA232D94F2FB45AEC4D303 + +[3EC3F83EAB22702E146C467EB1DB45FA] +GoodName=Super Robot Spirits (J) [!] +CRC=66572080 28E348E1 +Players=2 +SaveType=Eeprom 4KB +Rumble=Yes + +[E92FC6AE193092F6B597E05946B558EB] +GoodName=Super Robot Spirits (J) [b1] +CRC=66572080 28E348E1 +RefMD5=3EC3F83EAB22702E146C467EB1DB45FA + +[3F4B73963ABC91CEE59C416063EFD4AE] +GoodName=Super Robot Taisen 64 (J) [!] +CRC=1649D810 F73AD6D2 +Players=1 +SaveType=SRAM +Mempak=Yes +Transferpak=Yes + +[462A2AF0E3B72DA4A0E9266078EE5717] +GoodName=Super Robot Taisen 64 (J) [b1] +CRC=1649D810 F73AD6D2 +RefMD5=3F4B73963ABC91CEE59C416063EFD4AE + +[BB5C21BFEA9AA7E9C90FE76C132BEC49] +GoodName=Super Robot Taisen 64 (J) [b2] +CRC=1649D810 F73AD6D2 +RefMD5=3F4B73963ABC91CEE59C416063EFD4AE + +[9AF2919C27FCF6972986993C564947CD] +GoodName=Super Robot Taisen 64 (J) [f1] (PAL) +CRC=AF981AB7 AA1A0A7A +RefMD5=3F4B73963ABC91CEE59C416063EFD4AE + +[694DEA68DBF1C3F06FF0476ACF2169E6] +GoodName=Super Smash Bros. (A) [!] +CRC=DD26FDA1 CB4A6BE3 +Status=3 +SaveType=SRAM +Players=4 +Rumble=Yes +CountPerOp=1 + +[7F18A06BB16A507E23F9DD636B7046A6] +GoodName=Super Smash Bros. (A) [f1] +CRC=9624C4F9 3FB02E03 +RefMD5=694DEA68DBF1C3F06FF0476ACF2169E6 + +[7B815846EC91E6C4A8B8BAA0CE4078F0] +GoodName=Super Smash Bros. (Ch) (iQue) [!] +Players=4 + +[3ABC2D34AD3CE623F4ED8F126D30CC80] +GoodName=Super Smash Bros. (Ch) (iQue) (Manual) [!] + +[5E54C6C563B09C107F86FB33E914EF81] +GoodName=Super Smash Bros. (E) (M3) [!] +CRC=93945F48 5C0F2E30 +Status=3 +SaveType=SRAM +Players=4 +Rumble=Yes +CountPerOp=1 + +[4D37726FDFEC039CB36E2AAE65B9727D] +GoodName=Super Smash Bros. (E) (M3) [b1] +CRC=593BD58B C330786C +RefMD5=5E54C6C563B09C107F86FB33E914EF81 + +[99C1AB76126B7BADFA9023D50DCA1430] +GoodName=Super Smash Bros. (E) (M3) [f1] +CRC=593BD58B C330786C +RefMD5=5E54C6C563B09C107F86FB33E914EF81 + +[F7C52568A31AADF26E14DC2B6416B2ED] +GoodName=Super Smash Bros. (U) [!] +CRC=916B8B5B 780B85A4 +Status=3 +SaveType=SRAM +Players=4 +Rumble=Yes +CountPerOp=1 + +[508BE860974B75470851A2D25C0FCB36] +GoodName=Super Smash Bros. (U) [b1] +CRC=916B8B5B 780B85A4 +RefMD5=F7C52568A31AADF26E14DC2B6416B2ED + +[313F1541748ACF01C4355BA471043868] +GoodName=Super Smash Bros. (U) [b2] +CRC=916B8B5B 780B85A4 +RefMD5=F7C52568A31AADF26E14DC2B6416B2ED + +[326DC227FCCAA4975583E63624DDFDA1] +GoodName=Super Smash Bros. (U) [f1] +CRC=3409CEB6 CEC8517A +RefMD5=F7C52568A31AADF26E14DC2B6416B2ED + +[C2DBAE0C18C6666336F4CFA896D8ED18] +GoodName=Super Smash Bros. (U) [f2] (PAL) +CRC=8CF1CECB C8902FF4 +RefMD5=F7C52568A31AADF26E14DC2B6416B2ED + +[5A19D395B6A8B1911DEB334E392F4526] +GoodName=Super Smash Bros. (U) [f3] +CRC=3409CEB6 CEC8517A +RefMD5=F7C52568A31AADF26E14DC2B6416B2ED + +[98A3122A6D7C9B02381FC5B0CFB8C14B] +GoodName=Super Smash Bros. (U) [f4] (GameShark) +CRC=EA6D4C3F 13837E54 +RefMD5=F7C52568A31AADF26E14DC2B6416B2ED + +[ED8641A704910BB4A0FAC9AD08F9C1D2] +GoodName=Super Smash Bros. (U) [hI] +CRC=916B8B5B 780B85A4 +RefMD5=F7C52568A31AADF26E14DC2B6416B2ED + +[6B5D93B3566E96147009D1AC4FB15C97] +GoodName=Super Speed Race 64 (J) [!] +CRC=9CE02E22 206EF1B0 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[27A7A2A19FC67346BB25E3C5BB3A91CE] +GoodName=Super Speed Race 64 (J) [o1] +CRC=9CE02E22 206EF1B0 +RefMD5=6B5D93B3566E96147009D1AC4FB15C97 + +[DB502D4577EE908160441D38531EBB8D] +GoodName=Super WaLuigi 64 (Super Mario 64 Hack) +CRC=635A42C5 BDC58EDC +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[99138CB0D1325F7BB7C2EDAB5D7F6C54] +GoodName=Super Wario 64 (Super Mario 64 Hack) +CRC=635A42C5 BDC58EDC +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[7DDF1CC63401CF43836BD14F199B6C70] +GoodName=Super Wario 64 V1.0 by Rulesless (Super Mario 64 Hack) [T+Ita] +CRC=75A15B07 2E391683 +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[93582A59F442502CADAA39BD6CC1B2CE] +GoodName=Super Wario 64 V1.0 by Rulesless (Super Mario 64 Hack) +CRC=635A42C5 BDC58EDC +RefMD5=20B854B239203BAF6C961B850A4A51A2 + +[6D58A01EF7A7A7C779D2A66315992C5F] +GoodName=Supercross 2000 (E) (M3) [!] +CRC=2CBB127F 09C2BFD8 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[60347200A1A7CABC0D849EE69EC51DF7] +GoodName=Supercross 2000 (U) [!] +CRC=C1452553 5D7B24D9 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[53922802F7744CC38BDD75852214057F] +GoodName=Supercross 2000 (U) [b1] +CRC=C1452553 5D7B24D9 +RefMD5=60347200A1A7CABC0D849EE69EC51DF7 + +[4EAB63BE36DCC7FA6D612BE780BF79C1] +GoodName=Supercross 2000 (U) [f1] (PAL) +CRC=1917566C 8BE6CD0F +RefMD5=60347200A1A7CABC0D849EE69EC51DF7 + +[5AB39F2D7A144E1BA243DF059560E878] +GoodName=Superman (E) (M6) [!] +CRC=B44CAB74 07029A29 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[3F64B4F72E61225EF3AE93976C9BFC7C] +GoodName=Superman (U) (M3) [!] +CRC=A2E8F35B C9DC87D9 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[1170033980ADC1981505CF958F35F1EB] +GoodName=Superman (U) (M3) (Beta) [!] +CRC=944FAFC4 B288266A +RefMD5=3F64B4F72E61225EF3AE93976C9BFC7C + +[04A6F25CB0F2084E631B3B7FFF76BEFD] +GoodName=Superman (U) (M3) [T+Ita100_Cattivik66] +CRC=A2E8F35B C9DC87D9 +RefMD5=3F64B4F72E61225EF3AE93976C9BFC7C + +[3C28C951B1EA46690065DC32862272E4] +GoodName=Superman (U) (M3) [b1] +CRC=A2E8F35B C9DC87D9 +RefMD5=3F64B4F72E61225EF3AE93976C9BFC7C + +[574704AFFBD28C7A2728DA85CC1DA0F3] +GoodName=Superman (U) (M3) [b2] +CRC=A2E8F35B C9DC87D9 +RefMD5=3F64B4F72E61225EF3AE93976C9BFC7C + +[12562BFF127E52A6EE9B4FEF92050AF9] +GoodName=Superman (U) (M3) [f1] (PAL) +CRC=EEF7DE23 57E4FEA9 +RefMD5=3F64B4F72E61225EF3AE93976C9BFC7C + +[943337C945DA689AF869877498C7AA2C] +GoodName=Superman (U) (M3) [f2] (PAL) +CRC=06F6B180 97F0AD11 +RefMD5=3F64B4F72E61225EF3AE93976C9BFC7C + +[DBA237ED8415383AFCABA035D817272F] +GoodName=Superman (U) (M3) [t1] +CRC=5AEB33A3 23063A25 +RefMD5=3F64B4F72E61225EF3AE93976C9BFC7C + +[26F4CA20F7B9C88199AC046C57E282B4] +GoodName=Susume! Taisen Puzzle Dama Toukon! Marumata Chou (J) [!] +CRC=35E811F3 99792724 +Players=2 +Mempak=Yes +Rumble=Yes + +[59985249F824F74C335C6C47A6E29C4A] +GoodName=Susume! Taisen Puzzle Dama Toukon! Marumata Chou (J) [b1] +CRC=35E811F3 99792724 +RefMD5=26F4CA20F7B9C88199AC046C57E282B4 + +[993A67ECD02212B4BE5B2E14652F835B] +GoodName=Susume! Taisen Puzzle Dama Toukon! Marumata Chou (J) [b2] +CRC=35E811F3 99792724 +RefMD5=26F4CA20F7B9C88199AC046C57E282B4 + +[EFE2CEBF5BB21BF766FF72C055DF36BE] +GoodName=Susume! Taisen Puzzle Dama Toukon! Marumata Chou (J) [b3] +CRC=35E811F3 99792724 +RefMD5=26F4CA20F7B9C88199AC046C57E282B4 + +[B0FE1343A2ED21D2F083041B1FE1B7A9] +GoodName=Susume! Taisen Puzzle Dama Toukon! Marumata Chou (J) [h1C] +CRC=35E811F3 99792724 +RefMD5=26F4CA20F7B9C88199AC046C57E282B4 + +[987A07DAF0F06567BC8E794291D98695] +GoodName=Susume! Taisen Puzzle Dama Toukon! Marumata Chou (J) [h2C] +CRC=35E811F3 99792724 +RefMD5=26F4CA20F7B9C88199AC046C57E282B4 + +[E946855EEF7F1BBD47AEECA33A2737BB] +GoodName=Susume! Taisen Puzzle Dama Toukon! Marumata Chou (J) [o1] +CRC=35E811F3 99792724 +RefMD5=26F4CA20F7B9C88199AC046C57E282B4 + +[D6B0135BE06DF3545A8931957FE805FA] +GoodName=Susume! Taisen Puzzle Dama Toukon! Marumata Chou (J) [o2] +CRC=35E811F3 99792724 +RefMD5=26F4CA20F7B9C88199AC046C57E282B4 + +[6922A2D0DB719AD7972C0DC146FF0D8C] +GoodName=Susume! Taisen Puzzle Dama Toukon! Marumata Chou (J) [o2][b1] +CRC=35E811F3 99792724 +RefMD5=26F4CA20F7B9C88199AC046C57E282B4 + +[FC32007BA03FF2510020E979C7BDAD4F] +GoodName=Sydney 2000 (E) (Prototype) +CRC=ECBD95DD 1FAB637D + +[2EEA8D20BEF26F88A5E82FDD39F87E75] +GoodName=Sydney 2000 (U) (Prototype) +CRC=80A78080 5F9F8833 + +[4BC1D3074FA3A3DCAF1F16888B82A966] +GoodName=T-Shirt Demo by Neptune and Steve (POM '98) (PD) [b1] +CRC=1AA71519 51360D55 + +[E4D314C536F7BF78F60197EC238514AE] +GoodName=T-Shirt Demo by Neptune and Steve (POM '98) (PD) +CRC=1AA71519 51360D55 + +[ACD0118AC4709DB3943B3D35112C2001] +GoodName=TG Rally 2 (E) [!] +CRC=F82DD377 8C3FB347 +Players=4 +SaveType=None +Rumble=Yes +Mempak=Yes + +[65E67D43E0A9B146D7881CBC803EC5C3] +GoodName=TR64 Demo by FIres and Icepir8 (PD) +CRC=2070044B E7D82D16 + +[07660B03456DD0F776F392EF3E05C481] +GoodName=TRON Demo (PD) [a1] +CRC=CB3FF554 8773CD0B + +[4D6E12E0AB62D4045B4934B6D7BB8BDC] +GoodName=TRON Demo (PD) +CRC=CB3FF554 8773CD0B + +[503C548F7B38A3721B93FD0ABF979019] +GoodName=TRSI Intro by Ayatollah (POM '99) (PD) +CRC=2DD07E20 24D40CD6 + +[CECAB8DF02C02F38C9CF1BDD57B1DA00] +GoodName=Tamiya Racing 64 (U) (Prototype) +CRC=37955E65 C6F2B7B3 + +[192B715E8BC5972A4986DF21DC8BF357] +GoodName=Taz Express (E) (M6) [!] +CRC=AEBCDD54 15FF834A +Players=1 +Rumble=Yes + +[53DFA593019BDA070DD3CD5FC5B58436] +GoodName=Taz Express (E) (M6) [f1] (NTSC) +CRC=17679054 E235F4A7 +RefMD5=192B715E8BC5972A4986DF21DC8BF357 + +[AD47A9521988CEDD8D43097CFD9BE042] +GoodName=Taz Express (E) (M6) [f2] (NTSC) +CRC=00BC1D78 00709D53 +RefMD5=192B715E8BC5972A4986DF21DC8BF357 + +[7A94F94485BD28F0D6D67257050B26D4] +GoodName=Taz Express (U) (Prototype) +CRC=6C2C6C49 9BE5CA66 + +[7F244AFF8D729417E32B6A5B299AFDA5] +GoodName=Telefoot Soccer 2000 (F) [!] +CRC=D9042FBB FCFF997C +Players=4 +Mempak=Yes +Rumble=Yes + +[8F96FF06D9B3C3219CEBA5CDB7CF19ED] +GoodName=Telefoot Soccer 2000 (F) [b1] +CRC=6440D7CE F6597A03 +RefMD5=7F244AFF8D729417E32B6A5B299AFDA5 + +[D1B6D277F9FAE2029A7532D8E1F4D6B2] +GoodName=Telefoot Soccer 2000 (F) [f1] (NTSC) +CRC=6440D7CE F6597A03 +RefMD5=7F244AFF8D729417E32B6A5B299AFDA5 + +[7C8EFCF4FBA28F9F5B5EA10A71283BF3] +GoodName=Tetris 64 (J) [!] +CRC=963ADBA6 F7D5C89B +Players=4 +Biopak=Yes +SiDmaDuration=100 + +[1587B17344A43532B791DCEB237D2BFC] +GoodName=Tetris 64 (J) [T+Ita] +CRC=963ADBA6 F7D5C89B +RefMD5=7C8EFCF4FBA28F9F5B5EA10A71283BF3 + +[ECC06617156122882C4FA4BBCD241A4F] +GoodName=Tetris 64 (J) [b1] +CRC=963ADBA6 F7D5C89B +RefMD5=7C8EFCF4FBA28F9F5B5EA10A71283BF3 + +[9036BB44A51A62CB0A74C288EBB850C7] +GoodName=Tetris 64 (J) [b2] +CRC=963ADBA6 F7D5C89B +RefMD5=7C8EFCF4FBA28F9F5B5EA10A71283BF3 + +[8C9F139BF5FC0B7A0497F28241C6F819] +GoodName=Tetris Beta Demo by FusionMan (POM '98) (PD) [b1] +CRC=81361532 2AEB643F + +[674D416C2BD1EF0192BEE34AA260B21A] +GoodName=Tetris Beta Demo by FusionMan (POM '98) (PD) +CRC=81361532 2AEB643F + +[765A330D5CE2DBE7120C6C8E18A1487D] +GoodName=Tetrisphere (E) [!] +CRC=0FE684A9 8BB77AC4 +Players=2 +SaveType=Eeprom 4KB + +[A87455244919BDA6E44FA32C7E72BFBA] +GoodName=Tetrisphere (E) [b1] +CRC=0FE684A9 8BB77AC4 +RefMD5=765A330D5CE2DBE7120C6C8E18A1487D + +[822154EE2B96BF78BCE2E46AF6578131] +GoodName=Tetrisphere (E) [b2] +CRC=0FE684A9 8BB77AC4 +RefMD5=765A330D5CE2DBE7120C6C8E18A1487D + +[3F88078E2D9DBF6C9372F6373CF9AE09] +GoodName=Tetrisphere (U) [!] +CRC=3C1FDABE 02A4E0BA +Players=2 +SaveType=Eeprom 4KB + +[7211951FDF7DA809D5F3D51CA06CD465] +GoodName=Tetrisphere (U) [b1] +CRC=3C1FDABE 02A4E0BA +RefMD5=3F88078E2D9DBF6C9372F6373CF9AE09 + +[9F7527EE8A80DAE339DB769EAE707DCC] +GoodName=Tetrisphere (U) [t1] +CRC=4EF87A50 975A7CC7 +RefMD5=3F88078E2D9DBF6C9372F6373CF9AE09 + +[B11B30536D445AB6C7DC22C85C68A218] +GoodName=Textlight Demo by Horizon64 (PD) [b1] +CRC=41B1BF58 A1EB9BB7 + +[33CF09D5EAB2FB1242108A172E1844C2] +GoodName=Textlight Demo by Horizon64 (PD) +CRC=41B1BF58 A1EB9BB7 + +[DA934FF1A6CE9EEC70C235F879B23AFE] +GoodName=The Corporation 1st Intro by i_savant (PD) [b1] +CRC=44705CED 6FDFDE02 + +[B42C11B1DCBFC0AE42551021CD69AB22] +GoodName=The Corporation 1st Intro by i_savant (PD) +CRC=44705CED 6FDFDE02 + +[F6AE85B8CC2B643F37DE95D7F5682262] +GoodName=The Corporation 2nd Intro by TS_Garp (PD) [a1] +CRC=C3AB938D D48143B2 + +[EA9D71AF1508636E88D95AC1D525EF93] +GoodName=The Corporation 2nd Intro by TS_Garp (PD) [b1] +CRC=C3AB938D D48143B2 + +[756325378480E1252CB089110A689563] +GoodName=The Corporation 2nd Intro by TS_Garp (PD) +CRC=C3AB938D D48143B2 + +[D52E871B562AD000BA3728D9B45EC9CB] +GoodName=The Corporation XMAS Demo '99 by TS_Garp (PD) [b1] +CRC=93DA8551 D231E8AB + +[AF284AB7FF9363016782E99D00574E70] +GoodName=The Corporation XMAS Demo '99 by TS_Garp (PD) +CRC=93DA8551 D231E8AB + +[A09663B596F348D28AF846A51375EB81] +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] +CRC=E972B385 7668D414 +RefMD5=F8636514B5B0EDEBF376C3111D24417A + +[7B261247150C431DE55AB371E8B46EA8] +GoodName=Tokisora Senshi Turok (J) [!] +CRC=916AE6B8 8817AB22 +Players=1 +SaveType=None +Mempak=Yes + +[1B991CF41C70FF2C92FFBEFACABE8D03] +GoodName=Tom Clancy's Rainbow Six (E) [!] +CRC=4875AF3D 9A66D3A2 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[FC2D2F7EF02484EA0478A5EAFD0CBFF0] +GoodName=Tom Clancy's Rainbow Six (E) [b1] +CRC=4875AF3D 9A66D3A2 +RefMD5=1B991CF41C70FF2C92FFBEFACABE8D03 + +[C0612AA12888C10E9565A57EB2C3605D] +GoodName=Tom Clancy's Rainbow Six (E) [h1C] +CRC=4875AF3D 9A66D3A2 +RefMD5=1B991CF41C70FF2C92FFBEFACABE8D03 + +[AAD3D42A9E800780087009B16AFB1327] +GoodName=Tom Clancy's Rainbow Six (E) [o1] +CRC=4875AF3D 9A66D3A2 +RefMD5=1B991CF41C70FF2C92FFBEFACABE8D03 + +[15E4C1B4F3F459D4CAA7F7E2CF0C95DA] +GoodName=Tom Clancy's Rainbow Six (F) [!] +CRC=486BF335 034DCC81 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[FDC76A53B1056D3E50EA6A3E295FE4D1] +GoodName=Tom Clancy's Rainbow Six (G) [!] +CRC=8D412933 588F64DB +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[80F3B1ABD9FB9AE73997489DB185A74D] +GoodName=Tom Clancy's Rainbow Six (U) [!] +CRC=392A0C42 B790E77D +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[2CF9568A149177AC0B86378FBC8DCB71] +GoodName=Tom Clancy's Rainbow Six (U) [f1] (PAL) +CRC=8B79DBFD 0BB32AC0 +RefMD5=80F3B1ABD9FB9AE73997489DB185A74D + +[B9EF940408E1DFD63F867527E4212B9D] +GoodName=Tom Demo (PD) +CRC=5ECE09AE 8230C82D + +[46BE5D00682FCC1F7FC0FBA507E8E5C1] +GoodName=Tom and Jerry in Fists of Furry (E) (M6) [!] +CRC=2B4F4EFB 43C511FE +Players=2 +Rumble=Yes +SaveType=Eeprom 4KB + +[9EAA60F295DBA9A9687E3238DABA14EE] +GoodName=Tom and Jerry in Fists of Furry (E) (M6) [f1] (NTSC) +CRC=EC6F66AC 618EF742 +RefMD5=46BE5D00682FCC1F7FC0FBA507E8E5C1 + +[A63A9AF85BE8BB47C1741B8A37115354] +GoodName=Tom and Jerry in Fists of Furry (U) [!] +CRC=63E7391C E6CCEA33 +Players=2 +Rumble=Yes +SaveType=Eeprom 4KB + +[17D6D6DA5D03C9D295D72A212A719EB2] +GoodName=Tom and Jerry in Fists of Furry (U) [t1] +CRC=9BF2A817 EE20252A +RefMD5=A63A9AF85BE8BB47C1741B8A37115354 + +[99F95AD4A3B0C78B6F58A0FC3AD22DB6] +GoodName=Tommy Thunder (U) (Prototype) +CRC=21260D94 06AE1DFE + +[3D3573A855835A98DE29D598C35590E0] +GoodName=Tonic Trouble (E) (M5) [!] +CRC=093F916E 4408B698 +Players=1 +SaveType=None +Mempak=Yes + +[7D3E935156844DE0002DB875E1076A5C] +GoodName=Tonic Trouble (U) (V1.1) [!] +CRC=EF9E9714 C03B2C7D +Players=1 +SaveType=None +Mempak=Yes + +[A6C5625FF127D9E741F595EBF3B3ABB9] +GoodName=Tonic Trouble (U) (V1.1) [b1] +CRC=EF9E9714 C03B2C7D +RefMD5=7D3E935156844DE0002DB875E1076A5C + +[012C9DAF61705F109392A85B2621CD42] +GoodName=Tonic Trouble (U) (V1.1) [f1] (PAL) +CRC=1671E7BC B7D756B9 +RefMD5=7D3E935156844DE0002DB875E1076A5C + +[1987E0F12DDD619F440CD9637DF7CC28] +GoodName=Tonic Trouble (U) (V1.1) [t1] +CRC=1671F4A0 5C0E7928 +RefMD5=7D3E935156844DE0002DB875E1076A5C + +[C9E9C4A18B1540C6B4111331D7C663B8] +GoodName=Tony Hawk's Pro Skater (E) [!] +CRC=9F8926A5 0587B409 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[5ED7E392198A5FA56EE37EA9E93A8D50] +GoodName=Tony Hawk's Pro Skater (U) (V1.0) [!] +CRC=204EC022 B119D185 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[30EC0EEA5C487E5609D9F9F356D21F27] +GoodName=Tony Hawk's Pro Skater (U) (V1.0) [t1] +CRC=85C52CA4 017EE9A6 +RefMD5=5ED7E392198A5FA56EE37EA9E93A8D50 + +[AFF424A1883DC7BB92C7B2EBE9342F85] +GoodName=Tony Hawk's Pro Skater (U) (V1.1) [!] +CRC=E0144180 650B78C9 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[6BE030475C4DB52F273EF8A02B4DAFA8] +GoodName=Tony Hawk's Pro Skater 2 (E) [!] +CRC=84EAB557 C88A190F +Players=2 +SaveType=None +Rumble=Yes +Mempak=Yes + +[29974692808C112B306FBD259273DC96] +GoodName=Tony Hawk's Pro Skater 2 (U) [!] +CRC=99150E18 1266E6A5 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[9D4891BF26881C4541171B0235015FD4] +GoodName=Tony Hawk's Pro Skater 3 (U) +CRC=1A7F70B5 00B7B9FD +Players=2 +SaveType=None +Rumble=Yes +Mempak=Yes + +[B6FD2A048D1F4F324CEBC97BA09872BB] +GoodName=Toon Panic (J) (Prototype) +CRC=9A746EBF 2802EA99 + +[B60D26C2C2242BFF61F76469FC272D2A] +GoodName=Top Gear Hyper Bike (Beta) +CRC=75FBDE20 A3189B31 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[0072538EF925645DB310F8E23A480B89] +GoodName=Top Gear Hyper Bike (E) [!] +CRC=5F3F49C6 0DC714B0 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[561B438F6E8240BEF1DAEB36AAE72675] +GoodName=Top Gear Hyper Bike (E) [b1] +CRC=5F3F49C6 0DC714B0 +RefMD5=0072538EF925645DB310F8E23A480B89 + +[4347174BB415CA970F2D50DF2973F656] +GoodName=Top Gear Hyper Bike (J) [!] +CRC=845B0269 57DE9502 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[7258F4AB367B025C95A4F476C461E717] +GoodName=Top Gear Hyper Bike (U) [!] +CRC=8ECC02F0 7F8BDE81 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[6C65A252F227AEF18DF2DD3CE04CC821] +GoodName=Top Gear Overdrive (E) [!] +CRC=D09BA538 1C1A5489 +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes +CountPerOp=1 + +[11D6FFF288DE1BD61CCBD7CCA0C4A97B] +GoodName=Top Gear Overdrive (E) [h1C] +CRC=D09BA538 1C1A5489 +RefMD5=6C65A252F227AEF18DF2DD3CE04CC821 + +[B5691794A851D8B603F0C741D44AA244] +GoodName=Top Gear Overdrive (J) [!] +CRC=0578F24F 9175BF17 +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes +CountPerOp=1 + +[8C0F46FEF9A6034FCF0B7D6952FFEC53] +GoodName=Top Gear Overdrive (J) [b1] +CRC=0578F24F 9175BF17 +RefMD5=B5691794A851D8B603F0C741D44AA244 + +[7818696426C0A429FBFCCC4EFE8D5570] +GoodName=Top Gear Overdrive (U) [!] +CRC=D741CD80 ACA9B912 +Players=4 +SaveType=Eeprom 4KB +Rumble=Yes +CountPerOp=1 + +[773FD446DA7F4E392907505053BF2A42] +GoodName=Top Gear Overdrive (U) [o1] +CRC=D741CD80 ACA9B912 +RefMD5=7818696426C0A429FBFCCC4EFE8D5570 + +[211256ABBC0844D9152D6A7FFA9E48BD] +GoodName=Top Gear Overdrive (U) [t1] +CRC=0F5FD10B AAEDEBEB +RefMD5=7818696426C0A429FBFCCC4EFE8D5570 + +[50195216C8A37F9BD5B2105A40EE8D8F] +GoodName=Top Gear Rally (As) [!] +CRC=1A4D3AD8 59AF7FA9 +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[1698508F521280D0A80E078EC981D4AC] +GoodName=Top Gear Rally (E) [!] +CRC=7F43E701 536328D1 +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[48D6C194AE106018DDFC3486A8B347F7] +GoodName=Top Gear Rally (E) [b1] +CRC=7F43E701 536328D1 +RefMD5=1698508F521280D0A80E078EC981D4AC + +[108F6609CB131830EC4C67F4A8A71D30] +GoodName=Top Gear Rally (E) [h1C] +CRC=7F43E701 536328D1 +RefMD5=1698508F521280D0A80E078EC981D4AC + +[6E0AF13DCEFEE6A11C4D7262206D6D2D] +GoodName=Top Gear Rally (J) [!] +CRC=0E596247 753D4B8B +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[6F7030284B6BC84A49E07DA864526B52] +GoodName=Top Gear Rally (U) [!] +CRC=62269B3D FE11B1E8 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[FA88969ECFA72358EF1C045035442F5C] +GoodName=Top Gear Rally (U) [b1] +CRC=62269B3D FE11B1E8 +RefMD5=6F7030284B6BC84A49E07DA864526B52 + +[E9E3680C47CE093A3F0765539F31C6AE] +GoodName=Top Gear Rally (U) [b2] +CRC=62269B3D FE11B1E8 +RefMD5=6F7030284B6BC84A49E07DA864526B52 + +[194CE13B2B6B1F584587A68CC2F398DC] +GoodName=Top Gear Rally (U) [b3] +CRC=62269B3D FE11B1E8 +RefMD5=6F7030284B6BC84A49E07DA864526B52 + +[4FCD85C487E1FBEDFD85E27F991D1FA6] +GoodName=Top Gear Rally (U) [o1] +CRC=62269B3D FE11B1E8 +RefMD5=6F7030284B6BC84A49E07DA864526B52 + +[C33CD926E1E71F39F7238AF7B9E0DC5C] +GoodName=Top Gear Rally 2 (Beta) +CRC=EFDF9140 A4168D6B +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[44C4566572DC0662D4299AB5B19043AE] +GoodName=Top Gear Rally 2 (E) [!] +CRC=BEBAB677 51B0B5E4 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[B10D781EC625CA45713FD34E5096C24A] +GoodName=Top Gear Rally 2 (J) [!] +CRC=CFEF2CD6 C9E973E6 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[1FA409FCAC007DDECCC4CF439A0D8DAE] +GoodName=Top Gear Rally 2 (U) [!] +CRC=BE5973E0 89B0EDB8 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[4648C4F656BD4A74647DF6A7A2985F37] +GoodName=Top Gear Rally 2 (U) [f1] (PAL) +CRC=1C952873 FDA4238B +RefMD5=1FA409FCAC007DDECCC4CF439A0D8DAE + +[CAA7CAA9ADFB4B8E4B2DBED88F963D07] +GoodName=TopGun Demo by Horizon64 (PD) +CRC=E8BF8416 F2D9DA43 + +[3CBB8012F1256A37D5284A85B859CC8B] +GoodName=Tower&Shaft (Aleck64) +CRC=90AF8D2C E1AC1B37 +SaveType=Eeprom 4KB + +[5F2C9E5E39AB09311D96E6C751184B6B] +GoodName=Toy Story 2 - Buzz Lightyear to the Rescue! (E) [!] +CRC=CCEB3858 26952D97 +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[FA0F12C15B3655F9F56888C3249B1CED] +GoodName=Toy Story 2 - Buzz L'eclair A La Rescousse! (F) [!] +CRC=CB93DB97 7F5C63D5 +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[3F40F37B0464DD065067523FB21016DD] +GoodName=Toy Story 2 - Captain Buzz Lightyear auf Rettungsmission! (G) (V1.0) [!] +CRC=782A9075 E552631D +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[A4A2B825797E2059B5DF60D733461F34] +GoodName=Toy Story 2 - Captain Buzz Lightyear auf Rettungsmission! (G) (V1.1) [!] +CRC=BC4F2AB8 AA99E32E +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[B44E9C2D9D2F2DE3AF4793B824CCF936] +GoodName=Toy Story 2 - Buzz Lightyear to the Rescue! (U) [!] +CRC=A150743E CF2522CD +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) +CRC=161545FE A3C44C28 +RefMD5=B44E9C2D9D2F2DE3AF4793B824CCF936 + +[F551ADA6C6FC1877FCA0515DF4F515DF] +GoodName=Toy Story 2 - Buzz Lightyear to the Rescue! (U) (V1.0) [t1] +CRC=1416FEBB 93472028 +RefMD5=B44E9C2D9D2F2DE3AF4793B824CCF936 + +[CD61A7FDBD7297733B246204E8360D83] +GoodName=Toy Story 2 - Buzz Lightyear to the Rescue! (U) (V1.1) [!] +CRC=C151AD61 280FFF22 +Players=1 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[3D22D5BD7997293612ECDD3046BEBA13] +GoodName=Transformers - Beast Wars Metals 64 (J) [!] +CRC=91691C3D F4AC5B4D +Players=2 +SaveType=Eeprom 4KB +Rumble=Yes +Transferpak=Yes + +[6D38909FAA2840FC409AFA221489DE49] +GoodName=Transformers - Beast Wars Transmetal (U) [!] +CRC=4D79D316 E8501B33 +Players=2 +SaveType=None +Rumble=Yes + +[6F2C37A20E6ECCB657FBFC4BA36A34BB] +GoodName=Triple Play 2000 (U) [!] +CRC=FE4B6B43 081D29A7 +Players=2 +SaveType=None +Rumble=Yes +Mempak=Yes +CountPerOp=1 + +[25E03763FC8A388A33871C58DFEB7C0E] +GoodName=Tristar and Lightforce Quake Intro by Ayatollah & Mike (PD) +CRC=F4D89C08 3F34930D + +[5BA3AA2953C47C8B2E615B21E60F2F17] +GoodName=Tsumi to Batsu - Hoshi no Keishousha (Ch) (iQue) [!] +Players=2 + +[9ABB0F6F79E01FC9A942D6027719C3E4] +GoodName=Tsumi to Batsu - Hoshi no Keishousha (Ch) (iQue) (Manual) [!] + +[A0657BC99E169153FD46AECCFDE748F3] +GoodName=Tsumi to Batsu - Hoshi no Keishousha (J) [!] +CRC=B6BC0FB0 E3812198 +Players=2 +Rumble=Yes + +[6E51B140A9B0C30D6F55CA7942A969FC] +GoodName=Tsumi to Batsu - Hoshi no Keishousha (J) [T+Eng1.0_Zoinkity] +CRC=B73AB6F6 296267DD +RefMD5=A0657BC99E169153FD46AECCFDE748F3 + +[13FAA58604597E4EDC608070F8E0AE24] +GoodName=Turok - Dinosaur Hunter (E) (V1.0) [!] +CRC=2F7009DD FC3BAC53 +Players=1 +SaveType=None +Mempak=Yes + +[6D5147A9CD7DDD0F1FA8B8BDA439A734] +GoodName=Turok - Dinosaur Hunter (E) (V1.0) [b1] +CRC=665F09DD FC3BAC53 +RefMD5=13FAA58604597E4EDC608070F8E0AE24 + +[E887BEE5B1DE4E4D92ADA183A245150E] +GoodName=Turok - Dinosaur Hunter (E) (V1.0) [h1C] +CRC=2F7009DD FC3BAC53 +RefMD5=13FAA58604597E4EDC608070F8E0AE24 + +[992BA72F4A1E9C51934FF345CDD0D90C] +GoodName=Turok - Dinosaur Hunter (E) (V1.1) [!] +CRC=2F700DCD 176CC5C9 +Players=1 +SaveType=None +Mempak=Yes + +[548FC0E6035B65BC2108255039859934] +GoodName=Turok - Dinosaur Hunter (E) (V1.2) [!] +CRC=2F700DCD 176CC5C9 +Players=1 +SaveType=None +Mempak=Yes + +[0C0BFD1038EDA4F5C958DC362CDFF2D6] +GoodName=Turok - Dinosaur Hunter (G) (V1.0) [!] +CRC=665FD963 B5CC6612 +Players=1 +SaveType=None +Mempak=Yes + +[388440013641887D85B791CF01729FA8] +GoodName=Turok - Dinosaur Hunter (G) (V1.1) [!] +CRC=665FC793 6934A73B +Players=1 +SaveType=None +Mempak=Yes + +[F0F687B449A9F4B0BFF08104C35EA08C] +GoodName=Turok - Dinosaur Hunter (G) (V1.2) [!] +CRC=665FC793 6934A73B +Players=1 +SaveType=None +Mempak=Yes + +[AE5107EFDD3C210E1EDD4ACD9B3CAC31] +GoodName=Turok - Dinosaur Hunter (U) (V1.0) [!] +CRC=2F70F10D 5C4187FF +Players=1 +SaveType=None +Mempak=Yes + +[E5B207E7C8DBD8BAF9B42C96EF3C42E8] +GoodName=Turok - Dinosaur Hunter (U) (V1.0) [b1] +CRC=2F70F10D 5C4187FF +RefMD5=AE5107EFDD3C210E1EDD4ACD9B3CAC31 + +[7BBD5A1594526DE1CE6A16F4FAF82E7D] +GoodName=Turok - Dinosaur Hunter (U) (V1.0) [h1C] +CRC=2F70F10D 5C4187FF +RefMD5=AE5107EFDD3C210E1EDD4ACD9B3CAC31 + +[9D258DF027ED369886A0249BFCA936BD] +GoodName=Turok - Dinosaur Hunter (U) (V1.0) [o1] +CRC=2F70F10D 5C4187FF +RefMD5=AE5107EFDD3C210E1EDD4ACD9B3CAC31 + +[E7916845B46C3482CF4843968370557E] +GoodName=Turok - Dinosaur Hunter (U) (V1.0) [t1] +CRC=9542E183 B1D245E6 +RefMD5=AE5107EFDD3C210E1EDD4ACD9B3CAC31 + +[3DC541C0B97DB9C95A6AA8C2DED27F4A] +GoodName=Turok - Dinosaur Hunter (U) (V1.0) [t2] +CRC=9542E183 B1D245E6 +RefMD5=AE5107EFDD3C210E1EDD4ACD9B3CAC31 + +[37260287D59FE4EC6049C1D22B5614E6] +GoodName=Turok - Dinosaur Hunter (U) (V1.1) [!] +CRC=2F700DCD 176CC5C9 +Players=1 +SaveType=None +Mempak=Yes + +[039875B92C0E4FEF9797EC1744877B17] +GoodName=Turok - Dinosaur Hunter (U) (V1.2) [!] +CRC=2F700DCD 176CC5C9 +Players=1 +SaveType=None +Mempak=Yes + +[72A6AA28608EE93A1CB6FEB0A5F4C28C] +GoodName=Turok - Legenden des Verlorenen Landes (G) [!] +CRC=66E4FA0F DE88C7D0 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[241CF94BED487FFF62FFB7B846DA46AB] +GoodName=Turok - Rage Wars (E) (M3) (Eng-Fre-Ita) [!] +CRC=B6BE20A5 FACAF66D +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[DBA166A42710F40DC78DC52EB37B0BE6] +GoodName=Turok - Rage Wars (E) [!] +CRC=1EA26214 E790900F +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[CF5B28578FD62FA1FF8690079F5D68F5] +GoodName=Turok - Rage Wars (U) (V1.0) [!] +CRC=ADB9498B DAF28F55 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[07E123E104BA7B335B53932EDB2CFB2F] +GoodName=Turok - Rage Wars (U) (V1.0) [f1] (PAL) +CRC=700694EA 636C43D5 +RefMD5=CF5B28578FD62FA1FF8690079F5D68F5 + +[CA825227E9E203E8429600189825AD74] +GoodName=Turok - Rage Wars (U) (V1.0) [f2] (PAL) +CRC=72618906 0EDC784B +RefMD5=CF5B28578FD62FA1FF8690079F5D68F5 + +[9B2FFE72080B03A5F92EB87EA849CAC4] +GoodName=Turok - Rage Wars (U) (V1.1) [!] +CRC=2388984C DA7B3CC5 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[CE72237707F481CFE97FDE330C2AFCD6] +GoodName=Turok 2 - Seeds of Evil (E) (Kiosk Demo) [!] +CRC=E8C95AFC 35D121DA +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[144B10A484A22367FD2679529DBD2FED] +GoodName=Turok 2 - Seeds of Evil (E) (M4) [!] +CRC=2E0E7749 B8B49D59 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[E5A39521FA954EB97B96AC2154A5FD7A] +GoodName=Turok 2 - Seeds of Evil (E) [!] +CRC=E0B92B94 80E87CBD +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[AC1C00167B95929F8EE40DFACB49BB57] +GoodName=Turok 2 - Seeds of Evil (E) [b1] +CRC=E0B92B94 80E87CBD +RefMD5=E5A39521FA954EB97B96AC2154A5FD7A + +[B932116C967795076B5C112841AB4427] +GoodName=Turok 2 - Seeds of Evil (G) [!] +CRC=FE05840B 9393320C +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[3BD42F6AEC477C056E1AFEBB3515495C] +GoodName=Turok 2 - Seeds of Evil (U) (Kiosk Demo) [!] +CRC=E8C95AFC 35D121DA +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[4250FF0265AD72FC798E6ABA61CFCD0E] +GoodName=Turok 2 - Seeds of Evil (U) (Kiosk Demo) (Gore On Hack) +CRC=AAD95AFC BB3A44AC +RefMD5=3BD42F6AEC477C056E1AFEBB3515495C + +[4EA0F7563F2EAEB3D46E860C12FABFCB] +GoodName=Turok 2 - Seeds of Evil (U) (Kiosk Demo) [h1C] +CRC=E8C95AFC 35D121DA +RefMD5=3BD42F6AEC477C056E1AFEBB3515495C + +[166221365DB70D446C4206083D422DD1] +GoodName=Turok 2 - Seeds of Evil (U) (V1.1) [!] +CRC=E0B92B94 B9A7E025 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[FAD4DA8E17CE12F68CDF29180CDD4A90] +GoodName=Turok 2 - Seeds of Evil (U) (V1.0) [!] +CRC=49088A11 6494957E +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[8DC201A0A9CFD1D2C85EE2B42D8AC49A] +GoodName=Turok 2 - Seeds of Evil (U) (V1.0) [t1] +CRC=544E3629 875BDD4A +RefMD5=FAD4DA8E17CE12F68CDF29180CDD4A90 + +[72BA2C693EFA5FF3B80374CDBD0C957B] +GoodName=Turok 2 - Seeds of Evil (U) (V1.0) [t2] +CRC=544E3629 875BDD4A +RefMD5=FAD4DA8E17CE12F68CDF29180CDD4A90 + +[401C0DBDF49A64294DAA2BC8607245DD] +GoodName=Turok 2 - Seeds of Evil (U) (V1.0) [t3] +CRC=544E3629 875BDD4A +RefMD5=FAD4DA8E17CE12F68CDF29180CDD4A90 + +[279EC83BD60A3CCE69A1DB22B0A5C318] +GoodName=Turok 3 - Shadow of Oblivion (E) [!] +CRC=6A162FF2 2093704C +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[03D17AA3DC7663502017D3CC5A19AA8B] +GoodName=Turok 3 - Shadow of Oblivion (E) (Beta) (2000-05-31) +CRC=D124DBB7 7C9FF5E5 +RefMD5=279EC83BD60A3CCE69A1DB22B0A5C318 + +[69CE88C46A7C829C6F54004DE93EFCEF] +GoodName=Turok 3 - Shadow of Oblivion (E) (Beta) (2000-06-06) +CRC=37FA8F16 5F824D37 +RefMD5=279EC83BD60A3CCE69A1DB22B0A5C318 + +[C38ACBAE773CC3845EA354421E171998] +GoodName=Turok 3 - Shadow of Oblivion (E) (Beta) (2000-07-10) +CRC=D25C1211 13EEBF67 +RefMD5=279EC83BD60A3CCE69A1DB22B0A5C318 + +[0A3A4C761960F7D648AFA60B1E565C7C] +GoodName=Turok 3 - Shadow of Oblivion (U) (Beta) [h1C] +CRC=D25C1211 13EEBF67 +RefMD5=279EC83BD60A3CCE69A1DB22B0A5C318 + +[1211C556D77B169D81A666A9661E1777] +GoodName=Turok 3 - Shadow of Oblivion (U) [!] +CRC=89A579F1 667E97EF +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[8A5F9B3308107C253EC5DCA198F55C83] +GoodName=Turok 3 - Shadow of Oblivion (U) [t1] +CRC=6192E59D 538A78CF +RefMD5=1211C556D77B169D81A666A9661E1777 + +[A74738D03ACA4E51690408D203E86D49] +GoodName=Twintris by Twinsen (POM '98) (PD) +CRC=37B8F920 A58BB3EF + +[420C9FDBAE15767C5E584070209FF253] +GoodName=Twisted Edge Extreme Snowboarding (E) [!] +CRC=E688A5B8 B14B3F18 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes + +[4F0E2AF205BEEB49270154810660FF37] +GoodName=Twisted Edge Extreme Snowboarding (E) [b1] +CRC=BBC99D32 117DAA80 +RefMD5=420C9FDBAE15767C5E584070209FF253 + +[FDE5F910974A8B9C561A27B07E68F244] +GoodName=Twisted Edge Extreme Snowboarding (E) [h1C] +CRC=E688A5B8 B14B3F18 +RefMD5=420C9FDBAE15767C5E584070209FF253 + +[9DF6C2C97FA34A978EF3CB77631536FE] +GoodName=Twisted Edge Extreme Snowboarding (U) [!] +CRC=BBC99D32 117DAA80 +Players=2 +SaveType=None +Rumble=Yes +Mempak=Yes + +[0B0DF8EC747BF99F3A55A3300CE8BC0D] +GoodName=U64 (Chrome) Demo by Horizon64 (PD) [a1] +CRC=7739A454 A2F52A66 + +[9B4EFC228C894E1BA80D7D11FDA4E037] +GoodName=U64 (Chrome) Demo by Horizon64 (PD) [a1][b1] +CRC=7739A454 A2F52A66 + +[DFB437BFB32864A17E903FEDE9EC3A27] +GoodName=U64 (Chrome) Demo by Horizon64 (PD) [b1] +CRC=95013CCC 73F7C072 + +[33EFC323AA05F522CEF2324CC1D3F5DD] +GoodName=U64 (Chrome) Demo by Horizon64 (PD) +CRC=7739A454 A2F52A66 + +[A56BEF4C7E6899A96F1F33424B434790] +GoodName=U64 (Chrome) Demo by Horizon64 (older) (PD) [b1] +CRC=95013CCC 73F7C072 + +[2628818AF2FEE3C649AAF8627981A63D] +GoodName=U64 (Chrome) Demo by Horizon64 (older) (PD) +CRC=95013CCC 73F7C072 + +[FFEB5C1A85BABBBE60F2FEBA2B35C893] +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] +CRC=28D5562D E4D5AE50 +RefMD5=FFEB5C1A85BABBBE60F2FEBA2B35C893 + +[6AFA476787B762DC08F5B9EEB237C4EE] +GoodName=Uchhannanchan no Hono no Challenger - Denryu IraIra Bou (J) [h2C] +CRC=28D5562D E4D5AE50 +RefMD5=FFEB5C1A85BABBBE60F2FEBA2B35C893 + +[D42E4496BEA3C61E353643C8438CD9C7] +GoodName=Uchhannanchan no Hono no Challenger - Denryu IraIra Bou (J) [o1] +CRC=28D5562D E4D5AE50 +RefMD5=FFEB5C1A85BABBBE60F2FEBA2B35C893 + +[CEEDAB23299FA003F32975A4C1E407E3] +GoodName=Ultra Demo Bootcode by Locke^ (PD) [h1C] +CRC=ED42A2D4 7A71CD91 + +[B882EDA9CBF832BEEA2641E442A79EDD] +GoodName=Ultra Demo Bootcode by Locke^ (PD) +CRC=ED42A2D4 7A71CD91 + +[7E6456E104503B51A97735C8FF349E4C] +GoodName=Ultra Demo by Locke^ (PD) [a1] +CRC=ED42A2D4 7A71CD91 + +[2E2C990D8BBAEE7E0681FDC89C29C0F3] +GoodName=Ultra Demo by Locke^ (PD) +CRC=ED42A2D4 7A71CD91 + +[1DE07FCA04FB0810D95B8AE4DA173A2E] +GoodName=UltraMSX2 V1.0 by Jos Kwanten (PD) [f1] (V64) +CRC=31C41A8B 544057AE + +[6A11F7EB319CF603AB30A281E0639126] +GoodName=UltraMSX2 V1.0 by Jos Kwanten (PD) +CRC=4E7DE4EF 0DEC3712 + +[FCA7BE078D6DC68AC6F2E1B7B4369720] +GoodName=UltraMSX2 V1.0 w-F1 Spirit by Jos Kwanten (PD) +CRC=504ABA0A 269AA7F4 + +[D2BD19A0873A6900AEF07ECCE103710C] +GoodName=UltraMSX2 V1.0 w-Salamander by Jos Kwanten (PD) +CRC=FF922478 570B5673 + +[8E3D79FD6C089F88ED7A2CC1CDBDD535] +GoodName=UltraSMS V1.0 by Jos Kwanten (PD) [f1] (V64) +CRC=CD29E6E5 4533F032 + +[8095B5926A9FA7A0C9DA7B46731513A1] +GoodName=UltraSMS V1.0 by Jos Kwanten (PD) +CRC=F291B959 A24CBCAF + +[27CB290FAB6C32FAA75EB0E53BE73418] +GoodName=Ultrafox 64 by Megahawks (PD) +CRC=66D8DE56 C2AA25B2 +Players=0 +SaveType=None +Rumble=No +Status=3 + +[C0B245E95A0CE736E1401A2183C3BBD1] +GoodName=Unix SRAM-Upload Utility 1.0 by Madman (PD) +CRC=5F44492A 18552A0A + +[DCAC12EB5832D4A489188330EB9EC387] +GoodName=V-Rally Edition 99 (E) (M3) [!] +CRC=636E6B19 E57DDC5F +Players=2 +SaveType=Eeprom 4KB +Rumble=Yes + +[7DCEAFF24BB1BB3D9B8FE9B78CCC7048] +GoodName=V-Rally Edition 99 (E) (M3) [f1] (NTSC) +CRC=75CF4CCD F47E10F6 +RefMD5=DCAC12EB5832D4A489188330EB9EC387 + +[8541D7A8737BE09C52D4EC1274DE2A91] +GoodName=V-Rally Edition 99 (J) [!] +CRC=4D0224A5 1BEB5794 +Players=2 +SaveType=Eeprom 4KB +Rumble=Yes + +[0C3448A9D85300ACB9C5556F27A84B23] +GoodName=V-Rally Edition 99 (U) [!] +CRC=3C059038 C8BF2182 +Players=2 +SaveType=Eeprom 4KB +Rumble=Yes + +[9768A9874D8329569F8FB27EC0AB723B] +GoodName=V-Rally Edition 99 (U) [f1] (PAL) +CRC=6F48FF84 754B4549 +RefMD5=0C3448A9D85300ACB9C5556F27A84B23 + +[7E0AC3917227EDF51132FBEBB867FF9B] +GoodName=V64Jr 512M Backup Program by HKPhooey (PD) +CRC=760EF304 AD6D6A7C + +[FD523AF9832B5A17F0EB96ED2A77E77B] +GoodName=V64Jr Backup Tool V0.2b_Beta by RedboX (PD) +CRC=F11B663A 698824C0 + +[5BAA85768F2410C61FBE2DFB62C3D836] +GoodName=V64Jr Backup Tool by WT_Riker (PD) +CRC=4BD245D4 4202B322 + +[19BA19834F948EEE3828640246405B5D] +GoodName=V64Jr Flash Save Util by CrowTRobo (PD) +CRC=6FC4EEBC 125BF459 + +[1A232A07B0D2A102CA528E75CB7BBA22] +GoodName=VNES64 + Galaga (PD) +CRC=DCBE12CD FCCB5E58 +Status=0 +SaveType=None +Mempak=Yes + +[495E0B30318FC67978D68BD034165981] +GoodName=VNES64 + Mario (PD) +CRC=66807E77 EBEA2D76 +Status=0 +SaveType=None +Mempak=Yes + +[2953091D648ED1B60A67200B17A9410D] +GoodName=VNES64 + Test Cart (PD) +CRC=4537BDFF D1ECB425 + +[BE804A0317F138775454405155C1D9A5] +GoodName=VNES64 V0.1 by Jean-Luc Picard (POM '98) (PD) +CRC=4537BDFF D1ECB425 +Status=0 +SaveType=None +Mempak=Yes + +[062C3AD13478D5C75B4E8DB2FFD500DC] +GoodName=VNES64 V0.12 by Jean-Luc Picard (PD) +CRC=0E4B8C92 7F47A9B8 +Status=0 +SaveType=None +Mempak=Yes + +[B61F53695517D380EB7240331A2342C2] +GoodName=Vector Demo by Destop (POM '99) (PD) +CRC=1CEACBA0 42BC06D6 + +[A95442CE25EEB3BD31CEF8525B9936FD] +GoodName=View N64 Test Program (PD) [b1] +CRC=A38F7AA6 03A48A45 + +[CF17AF84662E1457E61AD54575D50D20] +GoodName=View N64 Test Program (PD) +CRC=34B493C9 07654185 + +[DF011E19F41B1B19C21F1E77E13780B7] +GoodName=Vigilante 8 (E) [!] +CRC=151F79F4 8EEDC8E5 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[637B9A40BED777FC96EB1BD07EA74783] +GoodName=Vigilante 8 (E) [h1C] +CRC=151F79F4 8EEDC8E5 +RefMD5=DF011E19F41B1B19C21F1E77E13780B7 + +[FF9F85C50982DBDBA9853A8915321D31] +GoodName=Vigilante 8 (F) [!] +CRC=E2BC82A2 591CD694 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[B69B84083D1B4EC99A465B3067F74417] +GoodName=Vigilante 8 (F) [b1] +CRC=E2BC82A2 591CD694 +RefMD5=FF9F85C50982DBDBA9853A8915321D31 + +[37B430EE16167831C6C6292994F93277] +GoodName=Vigilante 8 (G) [!] +CRC=6EDA5178 D396FEC1 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[D616ADF6441ACBBD0E6BEF023A8F6031] +GoodName=Vigilante 8 (U) [!] +CRC=EA71056A E4214847 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[9F42209E413A1A92C788BF7BC26BFB7B] +GoodName=Vigilante 8 (U) [b1] +CRC=5573C64D 905B49FA +RefMD5=D616ADF6441ACBBD0E6BEF023A8F6031 + +[5DDCE4475A98F7BA9CCE2F255723EB31] +GoodName=Vigilante 8 (U) [b2] +CRC=EA71056A E4214847 +RefMD5=D616ADF6441ACBBD0E6BEF023A8F6031 + +[B6154ECD50053CA96953176404B07824] +GoodName=Vigilante 8 (U) [f1] (PAL) +CRC=4FAFC64B B7DBE63A +RefMD5=D616ADF6441ACBBD0E6BEF023A8F6031 + +[F747B178FFAB97EE8545F7E6EFAEF7CA] +GoodName=Vigilante 8 (U) [f2] (PAL) +CRC=44C54A0B 22C0B63A +RefMD5=D616ADF6441ACBBD0E6BEF023A8F6031 + +[829E4F5DDECED5DB6C64E346EDA47E5C] +GoodName=Vigilante 8 (U) [t1] +CRC=5573C64D 905B49FA +RefMD5=D616ADF6441ACBBD0E6BEF023A8F6031 + +[47661EF1964524B6319B759913F08B62] +GoodName=Vigilante 8 - 2nd Offence (E) [!] +CRC=DD10BC7E F900B351 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[60CDF7445FAD2ABA05C958F46691501B] +GoodName=Vigilante 8 - 2nd Offense (U) [!] +CRC=F5C5866D 052713D9 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[5E30D0208FC4CB810A464E5DEFFB29A3] +GoodName=Vigilante 8 - 2nd Offense (U) [f1] (PAL) +CRC=098D46A2 D1A4CF3B +RefMD5=60CDF7445FAD2ABA05C958F46691501B + +[C3005D76AF42E929E5C67421A19F8235] +GoodName=Violence Killer - Turok New Generation (J) [!] +CRC=60006C98 2605A381 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[50272F8EA99E4E06ADD8CCAB5F5A4F41] +GoodName=Violence Killer - Turok New Generation (J) [b1] +CRC=60006C98 2605A381 +RefMD5=C3005D76AF42E929E5C67421A19F8235 + +[E790BE1A5B883BEBA44BC0D2666C65F5] +GoodName=Virtual Chess 64 (E) (M6) [!] +CRC=2FDAA221 A588A7CE +Players=2 +SaveType=None +Mempak=Yes + +[4166D03402397A56043AC2CD45F4CB87] +GoodName=Virtual Chess 64 (E) (M6) [b1] +CRC=2FDAA221 A588A7CE +RefMD5=E790BE1A5B883BEBA44BC0D2666C65F5 + +[C5594DEFBCFE16D56284C66FDE49E540] +GoodName=Virtual Chess 64 (E) (M6) [b2] +CRC=2FDAA221 A588A7CE +RefMD5=E790BE1A5B883BEBA44BC0D2666C65F5 + +[88D89282B2346F98C7F30850B061D486] +GoodName=Virtual Chess 64 (E) (M6) [o1] +CRC=2FDAA221 A588A7CE +RefMD5=E790BE1A5B883BEBA44BC0D2666C65F5 + +[CB2B7214BE1084F2BFAEE556B0B4FD2C] +GoodName=Virtual Chess 64 (E) (M6) [o1][h1C] +CRC=2FDAA221 A588A7CE +RefMD5=E790BE1A5B883BEBA44BC0D2666C65F5 + +[F8A35270279B277586D7210FD15134FF] +GoodName=Virtual Chess 64 (U) (M3) [!] +CRC=82B3248B E73E244D +Players=2 +SaveType=None +Mempak=Yes + +[F05BD2DAD01F3E354713380AAFFB63E9] +GoodName=Virtual Chess 64 (U) (M3) [b1] +CRC=82B3248B E73E244D +RefMD5=F8A35270279B277586D7210FD15134FF + +[C252FEC96171ABD07A6C5B99B74924D4] +GoodName=Virtual Chess 64 (U) (M3) [b1][o1] +CRC=82B3248B E73E244D +RefMD5=F8A35270279B277586D7210FD15134FF + +[F41FCA7F185B3EC45ED90491BC8C0983] +GoodName=Virtual Chess 64 (U) (M3) [f1] (PAL) +CRC=46F3248B 534F2F61 +RefMD5=F8A35270279B277586D7210FD15134FF + +[E62751EFDE5312ED12DEC6C9FDCBF062] +GoodName=Virtual Chess 64 (U) (M3) [f1][o1] +CRC=46F3248B 534F2F61 +RefMD5=F8A35270279B277586D7210FD15134FF + +[0343B990F58CD816D96FBE5D5E710C82] +GoodName=Virtual Chess 64 (U) [o1] +CRC=82B3248B E73E244D +RefMD5=F8A35270279B277586D7210FD15134FF + +[AB68FB43F012C1A45AF1DBCC8E8C109C] +GoodName=Virtual Pool 64 (E) [!] +CRC=98F9F2D0 03D9F09C +Players=2 +SaveType=None +Mempak=Yes +CountPerOp=1 + +[C4FD61C707977F1BF48DC15E31BD2FB1] +GoodName=Virtual Pool 64 (E) [o1] +CRC=98F9F2D0 03D9F09C +RefMD5=AB68FB43F012C1A45AF1DBCC8E8C109C + +[6D3DB67319DA339DF4B68AD0084904D5] +GoodName=Virtual Pool 64 (U) [!] +CRC=4E4A7643 A37439D7 +Players=2 +SaveType=None +Mempak=Yes +CountPerOp=1 + +[C6855DF00BD5BE8A41DCE809093EE40B] +GoodName=Virtual Pool 64 (U) [o1] +CRC=4E4A7643 A37439D7 +RefMD5=6D3DB67319DA339DF4B68AD0084904D5 + +[90002501777E3237739F5ED9B0E349E2] +GoodName=Virtual Pro Wrestling 2 - Oudou Keishou (J) [!] +CRC=CD094235 88074B62 +Players=4 +SaveType=SRAM +Mempak=Yes +Rumble=Yes + +[5E6202200AF40A8F026780EDFE1E15D0] +GoodName=Virtual Pro Wrestling 64 (J) [!] +CRC=045C08C4 4AFD798B +Players=4 +SaveType=SRAM +Mempak=Yes +Rumble=Yes + +[7FDC16C96B517D4E433CF7353B22FBA6] +GoodName=Virtual Pro Wrestling 64 (J) [b1] +CRC=045C08C4 4AFD798B +RefMD5=5E6202200AF40A8F026780EDFE1E15D0 + +[290BE44B47110A011523A343786A15A0] +GoodName=Virtual Pro Wrestling 64 (J) [f1] +CRC=B3CD11F6 60725EB0 +RefMD5=5E6202200AF40A8F026780EDFE1E15D0 + +[9B241103CE0F13CAD5FE522DF67ED88B] +GoodName=Virtual Pro Wrestling 64 (J) [f2] +CRC=B3CD11F6 60725EB0 +RefMD5=5E6202200AF40A8F026780EDFE1E15D0 + +[1D2CB88BBCB67E12289B74F5BD88AE4C] +GoodName=Virtual Pro Wrestling 64 (J) [h1C] +CRC=045C08C4 4AFD798B +RefMD5=5E6202200AF40A8F026780EDFE1E15D0 + +[35BF5C390AF1AD730E00EB618AED7B72] +GoodName=Virtual Springfield Site Intro by Presten (PD) +CRC=4F55D05C 0CD66C91 + +[2AEE59CC8DDA4382969BB76DC97D4228] +GoodName=Vivid Dolls (Aleck64) +CRC=2F57C9F7 F1E29CA6 +SaveType=Eeprom 4KB + +[02AED169EB579494ACE75D22E10D789B] +GoodName=WCW Backstage Assault (U) [!] +CRC=396F5ADD 6693ECA7 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[9E943752BCF4FBA9CA3028E596F4EB4A] +GoodName=WCW Mayhem (E) [!] +CRC=AA7B0658 9C96937B +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[F1AF35375519E97BB7C0E37E2F68416E] +GoodName=WCW Mayhem (E) [h1C] +CRC=AA7B0658 9C96937B +RefMD5=9E943752BCF4FBA9CA3028E596F4EB4A + +[87BF3784709CD09693CD7BCC08460C63] +GoodName=WCW Mayhem (U) [!] +CRC=33BE8CD6 EC186912 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[5D7368D95B89F451E68F0832ED2BA8FF] +GoodName=WCW Mayhem (U) [f1] (PAL) +CRC=2AD07230 7A0719F7 +RefMD5=87BF3784709CD09693CD7BCC08460C63 + +[1E9FEAD701FE5AAAA248D4713891775D] +GoodName=WCW Nitro (U) [!] +CRC=D4C45A1A F425B25E +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=3 + +[EC097EB33BAD93A8AC6E15F7839762AB] +GoodName=WCW Nitro (U) [b3] +CRC=D4C45A1A F425B25E +RefMD5=1E9FEAD701FE5AAAA248D4713891775D + +[BC8BA67065FDBAA731DEFC866D25B8C2] +GoodName=WCW Nitro (U) [b1] +CRC=D4C45A1A F425B25E +RefMD5=1E9FEAD701FE5AAAA248D4713891775D + +[CE86CE535A5B55AE4A0E6CC942701082] +GoodName=WCW Nitro (U) [b2] +CRC=5DDB495C CE6E5573 +RefMD5=1E9FEAD701FE5AAAA248D4713891775D + +[8524D92A742BC9D0D6F072F9F80E887C] +GoodName=WCW Nitro (U) [f1] (PAL) +CRC=85DB4944 43ADE940 +RefMD5=1E9FEAD701FE5AAAA248D4713891775D + +[A6A0109023837C4ED5CAC62F4A66ABA6] +GoodName=WCW Nitro (U) [f2] (PAL) +CRC=ACDCA0C6 0F4C66F9 +RefMD5=1E9FEAD701FE5AAAA248D4713891775D + +[553D8D5347969C66E5D91C3FE35208B9] +GoodName=WCW vs. nWo - World Tour (E) [!] +CRC=8BDBAF68 345B4B36 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[203C3BBFDD10C5A0B7C5D0CDB085D853] +GoodName=WCW vs. nWo - World Tour (U) (V1.0) [!] +CRC=2C3E19BD 5113EE5E +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[6BD5C85E25BF3146A42F962A379B4F54] +GoodName=WCW vs. nWo - World Tour (U) (V1.0) [b1] +CRC=2C3E19BD 5113EE5E +RefMD5=203C3BBFDD10C5A0B7C5D0CDB085D853 + +[B7A220B59303D47F3BEAE233CA868CFD] +GoodName=WCW vs. nWo - World Tour (U) (V1.1) [!] +CRC=71BE60B9 1DDBFB3C +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[30C6676EC1D62122F4E7607EF3ABBD41] +GoodName=WCW-nWo Revenge (E) [!] +CRC=68E8A875 0CE7A486 +Players=4 +SaveType=SRAM +Rumble=Yes +CountPerOp=1 + +[07F0AD841350BD7CA1E6A99FB7E887E6] +GoodName=WCW-nWo Revenge (E) [h1C] +CRC=68E8A875 0CE7A486 +RefMD5=30C6676EC1D62122F4E7607EF3ABBD41 + +[C1384F3637D7A381B29341FED3EF3CEB] +GoodName=WCW-nWo Revenge (U) [!] +CRC=DEE596AB AF3B7AE7 +Players=4 +SaveType=SRAM +Rumble=Yes +CountPerOp=1 + +[B230D307428F4B69B3A80109AC905A44] +GoodName=WCW-nWo Revenge (U) [b1] +CRC=DEE596AB AF3B7AE7 +RefMD5=C1384F3637D7A381B29341FED3EF3CEB + +[117EF2639E0485210C7AB70CBF3E0C00] +GoodName=WCW-nWo Revenge (U) [b2] +CRC=DEE596AB AF3B7AE7 +RefMD5=C1384F3637D7A381B29341FED3EF3CEB + +[D6CD1AF1597CF0D279A39F75EE07C43A] +GoodName=WCW-nWo Revenge (U) [f1] (PAL) +CRC=768AD2AA C3C79B68 +RefMD5=C1384F3637D7A381B29341FED3EF3CEB + +[847A00F2C5DA6696FC49702431DF3150] +GoodName=WCW-nWo Revenge (U) [f2] (PAL) +CRC=768AD2AA C3C79B68 +RefMD5=C1384F3637D7A381B29341FED3EF3CEB + +[EBC0CF55FC58845C6EE86CF8B2D87303] +GoodName=WWF - War Zone (E) [!] +CRC=33A275A4 B8504459 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[2322DA2B9E7DC74678CD683B7A246B49] +GoodName=WWF - War Zone (U) [!] +CRC=CD5BEC0F 86FD1008 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[3FDB2E5F9982FDA2C2344A883B8AB6EF] +GoodName=WWF Attitude (E) [!] +CRC=5BF45B7B 596BEEE8 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[B86EC8D19D7D1A50EA900EA10355A735] +GoodName=WWF Attitude (G) [!] +CRC=8F3151C8 4F3AF545 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[5AC5CEDBD22CEEA8DD50CF6084193357] +GoodName=WWF Attitude (G) [b1] +CRC=8F3151C8 4F3AF545 +RefMD5=B86EC8D19D7D1A50EA900EA10355A735 + +[9FAF514CB3DBB742C129DEB395DCA342] +GoodName=WWF Attitude (U) [!] +CRC=D2BE2F14 38453788 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[6D4CBA7FB2E910CA1A87E63A4C1924C2] +GoodName=WWF Attitude (U) [b1] +CRC=D2BE2F14 38453788 +RefMD5=9FAF514CB3DBB742C129DEB395DCA342 + +[44BC029B5219E1A16F3B99125056F98B] +GoodName=WWF Attitude (U) [b2] +CRC=D2BE2F14 38453788 +RefMD5=9FAF514CB3DBB742C129DEB395DCA342 + +[382ECA33C5DD52B8C03A56D20F2D3F21] +GoodName=WWF Attitude (U) [f1] (PAL) +CRC=D89261A9 B1A2C9AF +RefMD5=9FAF514CB3DBB742C129DEB395DCA342 + +[D94A8F78178473D4BA4BED62FA8E2E66] +GoodName=WWF No Mercy (E) (V1.0) [!] +CRC=6D8DF08E D008C3CF +SaveType=Flash RAM +Players=4 +Mempak=Yes +Rumble=Yes + +[473FDDBB121255A171A40C14130D0165] +GoodName=WWF No Mercy (E) (V1.0) [b1] +CRC=6D8DF08E D008C3CF +RefMD5=D94A8F78178473D4BA4BED62FA8E2E66 + +[C9A6446918DA5D65612C521D432B7DA1] +GoodName=WWF No Mercy (E) (V1.0) [b2] +CRC=6D8DF08E D008C3CF +RefMD5=D94A8F78178473D4BA4BED62FA8E2E66 + +[400A14F132D993F5544F8B008EC136FA] +GoodName=WWF No Mercy (E) (V1.1) [!] +CRC=8CDB94C2 CB46C6F0 +Players=4 +SaveType=Flash RAM +Mempak=Yes +Rumble=Yes + +[04C492BE7F89FC6F425238BD67629544] +GoodName=WWF No Mercy (U) (V1.0) [!] +CRC=4E4B0640 1B49BCFB +Players=4 +SaveType=Flash RAM +Mempak=Yes +Rumble=Yes + +[51074CFE7A319270CF088A7C65387368] +GoodName=WWF No Mercy (U) (V1.0) [t1] +CRC=361E1288 7A26BE5F +RefMD5=04C492BE7F89FC6F425238BD67629544 + +[66B8EC24557A50514A814F15429BD559] +GoodName=WWF No Mercy (U) (V1.1) [!] +CRC=6C80F13B 427EDEAA +RefMD5=04C492BE7F89FC6F425238BD67629544 + +[B75149F87CC5F3A508643AC377F2FCC9] +GoodName=WWF WrestleMania 2000 (E) [!] +CRC=C71353BE AA09A6EE +Players=4 +SaveType=SRAM +Mempak=Yes +Rumble=Yes + +[EBB9E3D3782347743BFFB8B6D178FC8A] +GoodName=WWF WrestleMania 2000 (E) [h1C] +CRC=C71353BE AA09A6EE +RefMD5=B75149F87CC5F3A508643AC377F2FCC9 + +[11EEE2F34BF8DA05A1B8F4FB9FE9F74C] +GoodName=WWF WrestleMania 2000 (J) [!] +CRC=12737DA5 23969159 +Players=4 +SaveType=SRAM +Mempak=Yes +Rumble=Yes + +[AFC5EEDD3FCEEF85458E9C8FA162B303] +GoodName=WWF WrestleMania 2000 (J) [b1] +CRC=12737DA5 23969159 +RefMD5=11EEE2F34BF8DA05A1B8F4FB9FE9F74C + +[D9030CA30E4D1AF805ACCE1BFED988CC] +GoodName=WWF WrestleMania 2000 (U) [!] +CRC=90A59003 31089864 +Players=4 +SaveType=SRAM +Mempak=Yes +Rumble=Yes + +[CB174FA89F352DD8451A43FEF2B8D1AA] +GoodName=WWF WrestleMania 2000 (U) [b1] +CRC=90A59003 31089864 +RefMD5=D9030CA30E4D1AF805ACCE1BFED988CC + +[9EAFCA831487923E0BE79717A678894E] +GoodName=WWF WrestleMania 2000 (U) [t1] (Never Drop Weapons) +CRC=90A59003 31089864 +RefMD5=D9030CA30E4D1AF805ACCE1BFED988CC + +[5F1906DF4EB30537C2AC2FCBD005907D] +GoodName=Waialae Country Club - True Golf Classics (E) (M4) (V1.0) [!] +CRC=93053075 261E0F43 +Players=4 +SaveType=SRAM +Rumble=Yes + +[1FC540D2168650E135BCC7D3B542E03A] +GoodName=Waialae Country Club - True Golf Classics (E) (M4) (V1.0) [b1] +CRC=93053075 261E0F43 +RefMD5=5F1906DF4EB30537C2AC2FCBD005907D + +[F7C1B1EE1CE37CE09AA48C7E0A115EFA] +GoodName=Waialae Country Club - True Golf Classics (E) (M4) (V1.1) [!] +CRC=0C5057AD 046E126E +RefMD5=5F1906DF4EB30537C2AC2FCBD005907D + +[DD8154D507C88694AFD69C7AF16A8CD6] +GoodName=Waialae Country Club - True Golf Classics (U) (V1.0) [!] +CRC=8066D58A C3DECAC1 +Players=4 +SaveType=SRAM +Rumble=Yes + +[67F75C4DD30922A001C8C32AEB9333AC] +GoodName=Waialae Country Club - True Golf Classics (U) (V1.1) [!] +CRC=DD318CE2 B73798BA +RefMD5=DD8154D507C88694AFD69C7AF16A8CD6 + +[D25DD15903BDCB7724A2E8A02561987F] +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] +CRC=F7FE28F6 C3F2ACC3 +RefMD5=9FF2BA3C8408DE9F0EDB6D764A97C197 + +[0D3F2F58310387C60F932F6EC936788D] +GoodName=War Gods (U) [o1][h1C] +CRC=F7FE28F6 C3F2ACC3 +RefMD5=9FF2BA3C8408DE9F0EDB6D764A97C197 + +[F87937C9DE3703898C480FC84C692523] +GoodName=War Gods (U) [o2] +CRC=F7FE28F6 C3F2ACC3 +RefMD5=9FF2BA3C8408DE9F0EDB6D764A97C197 + +[5C98466C2B2AAF7F3B51D4406EEE39FD] +GoodName=War Gods (U) [o3] +CRC=F7FE28F6 C3F2ACC3 +RefMD5=9FF2BA3C8408DE9F0EDB6D764A97C197 + +[771FC17CDC840ED36DB8A699757C37F8] +GoodName=War Gods (U) [t1] (God Mode) +CRC=59BEB6F9 E6DC1630 +RefMD5=9FF2BA3C8408DE9F0EDB6D764A97C197 + +[D24435C65C48E8DE0831FC8F466BAA51] +GoodName=War Gods (U) (Power Bar Hack) +CRC=AFBEB6F6 B0E715DC +RefMD5=9FF2BA3C8408DE9F0EDB6D764A97C197 + +[1F83663B2C84512FC3706A6CACC1A9F3] +GoodName=Wave Race 64 (Ch) (iQue) [!] + +[A66FEE7AF89D58B24A25C346A0E90172] +GoodName=Wave Race 64 (Ch) (V2) (iQue) (Manual) [!] + +[926B1495565435DA0AF29BB660532DA3] +GoodName=Wave Race 64 (Ch) (V4) (iQue) (Manual) [!] + +[310659115E9939F219A783ABDD456CE9] +GoodName=Wave Race 64 (E) (M2) [!] +CRC=650EFA96 30DDF9A7 +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes + +[A992E010BC3740C7C266D4F6E90226A1] +GoodName=Wave Race 64 (E) (M2) [h1C] +CRC=650EFA96 30DDF9A7 +RefMD5=310659115E9939F219A783ABDD456CE9 + +[470D3E391A2B4CEBF0A9E15EC49CD324] +GoodName=Wave Race 64 (E) (M2) [o1] +CRC=650EFA96 30DDF9A7 +RefMD5=310659115E9939F219A783ABDD456CE9 + +[B32E555BC1A375256E8A4021A25339BE] +GoodName=Wave Race 64 (J) [!] +CRC=5C9191D6 B30AC306 +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes + +[D05C6F3CAF9059B306CC13535E2A8BA6] +GoodName=Wave Race 64 (J) (V1.1) [!] +CRC=44995484 20A5FC5E +RefMD5=B32E555BC1A375256E8A4021A25339BE + +[AE480013F39D4AEC86EEA1B4995600D1] +GoodName=Wave Race 64 (U) (V1.0) [!] +CRC=7DE11F53 74872F9D +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes + +[D653E6B050F63B5E1C1E9856319287E1] +GoodName=Wave Race 64 (U) (V1.0) [t1] +CRC=C5F4865F 03340B83 +RefMD5=AE480013F39D4AEC86EEA1B4995600D1 + +[2048A640C12D1CF2052BA1629937D2FF] +GoodName=Wave Race 64 (U) (V1.1) [!] +CRC=492F4B61 04E5146A +Players=2 +SaveType=Eeprom 4KB +Mempak=Yes + +[FF67DF97476C210D158779AE6142F239] +GoodName=Wave Race 64 - Shindou Edition (J) (V1.2) [!] +CRC=535DF3E2 609789F1 +Players=2 +CountPerOp=3 +SaveType=Eeprom 4KB +Mempak=Yes +Rumble=Yes + +[AFBC694A3BA5AE83D3CEEF906BF01839] +GoodName=Wave Race 64 - Shindou Edition (J) (V1.2) [b1] +CRC=535DF3E2 609789F1 +RefMD5=FF67DF97476C210D158779AE6142F239 + +[41E419F4392CFEF2C354006169362286] +GoodName=Wave Race 64 - Shindou Edition (J) (V1.2) [b2] +CRC=535DF3E2 609789F1 +RefMD5=FF67DF97476C210D158779AE6142F239 + +[CAD993128A11B5616E5DDE5CF50CB998] +GoodName=Wave Race 64 - Shindou Edition (J) (V1.2) [h1C] +CRC=535DF3E2 609789F1 +RefMD5=FF67DF97476C210D158779AE6142F239 + +[F9DA7EB74E391C5E6813212F7F55959A] +GoodName=Wave Race 64 - Shindou Edition (J) (V1.2) [o1] +CRC=535DF3E2 609789F1 +RefMD5=FF67DF97476C210D158779AE6142F239 + +[24A0D8C8CABC22116E469476FF6C691D] +GoodName=Wayne Gretzky's 3D Hockey '98 (E) (M4) [!] +CRC=661B45F3 9ED6266D +Players=4 +SaveType=None +Mempak=Yes + +[810F8BC2C8C66BDA3B206C7DD4B6D42F] +GoodName=Wayne Gretzky's 3D Hockey '98 (U) [!] +CRC=5A9D3859 97AAE710 +Players=4 +SaveType=None +Mempak=Yes + +[096726498E698B51AFE72AAB5262A15A] +GoodName=Wayne Gretzky's 3D Hockey '98 (U) [T+Ita_cattivik66] +CRC=5A9D3859 97AAE710 + +[C9F95F9480B5867B03CFC0533F319253] +GoodName=Wayne Gretzky's 3D Hockey '98 (U) [h1C] +CRC=5A9D3859 97AAE710 + +[F7E5BDF8E4076C27961BAF9A42C73524] +GoodName=Wayne Gretzky's 3D Hockey '98 (U) [h2C] +CRC=5A9D3859 97AAE710 + +[319816AAA30E512827BE7B7F81F80D86] +GoodName=Wayne Gretzky's 3D Hockey (E) (M4) [!] +CRC=2209094B 2C9559AF +Players=4 +SaveType=None +Mempak=Yes + +[65F1D583B5392D3467BD187224FBBD89] +GoodName=Wayne Gretzky's 3D Hockey (E) (M4) [b1] +CRC=2209095F ECD28311 +RefMD5=319816AAA30E512827BE7B7F81F80D86 + +[0905A37DBB3B9CEC38B52F6E109A9EAA] +GoodName=Wayne Gretzky's 3D Hockey (E) (M4) [h1C] +CRC=2209094B 2C9559AF +RefMD5=319816AAA30E512827BE7B7F81F80D86 + +[61E637B542D5DF178040454075C28E19] +GoodName=Wayne Gretzky's 3D Hockey (J) [!] +CRC=F1301043 FD80541A +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[371620871660767900FC00F72681E1FD] +GoodName=Wayne Gretzky's 3D Hockey (J) [b1] +CRC=F1301043 FD80541A +RefMD5=61E637B542D5DF178040454075C28E19 + +[03877A5CD0DD1E8C14EEEE70660E79DA] +GoodName=Wayne Gretzky's 3D Hockey (J) [o1] +CRC=F1301043 FD80541A +RefMD5=61E637B542D5DF178040454075C28E19 + +[81EFB80DB5E014D865EC2EC88C393E4D] +GoodName=Wayne Gretzky's 3D Hockey (J) [o2] +CRC=F1301043 FD80541A +RefMD5=61E637B542D5DF178040454075C28E19 + +[6DF0D6259261D0096C90BBC6AA037D8E] +GoodName=Wayne Gretzky's 3D Hockey (U) (V1.0) [!] +CRC=6B45223F F00E5C56 +Players=4 +SaveType=None +Mempak=Yes + +[EDBDB55AD58554C48B25A47D7E178513] +GoodName=Wayne Gretzky's 3D Hockey (U) (V1.0) [b1] +CRC=6B45223F F00E5C56 +RefMD5=6DF0D6259261D0096C90BBC6AA037D8E + +[5349ABD4EE13C8F029A60032735B1AE3] +GoodName=Wayne Gretzky's 3D Hockey (U) (V1.0) [o1] +CRC=6B45223F F00E5C56 +RefMD5=6DF0D6259261D0096C90BBC6AA037D8E + +[04E650B7742A69DAE98F125D1B492D78] +GoodName=Wayne Gretzky's 3D Hockey (U) (V1.1) [!] +CRC=DC3BAA59 0ABB456A +Players=4 +SaveType=None +Mempak=Yes + +[98C20A229170CF393BBF442D44FFC5B1] +GoodName=Wet Dreams Can Beta Demo by Immortal (POM '99) (PD) +CRC=CA3BC095 9649860A + +[D652769F8EE9BBE5F0BD5DF9B955D47E] +GoodName=Wet Dreams Madeiragames Demo by Immortal (POM '99) (PD) +CRC=993B7D7A 2E54F04D + +[37C0C97DFCE99F9968778448F5C9F0B6] +GoodName=Wet Dreams Main Demo by Immortal (POM '99) (PD) +CRC=A3A95A57 9FE6C27D + +[7B7B2916A857B9FC513C5F9619B36C98] +GoodName=Wet Dreams Readme by Immortal (POM '99) (PD) +CRC=9C044945 D31E0B0C +Status=5 +SaveType=None +Players=0 +Rumble=No + +[A99E2CB6ACEF7A004961DE5F6DFEEFF0] +GoodName=Wetrix (E) (M6) [!] +CRC=CEA8B54F 7F21D503 +Players=4 +SaveType=None +Mempak=Yes +CountPerOp=3 + +[15F425829D54DD290451D2F3EBAF953F] +GoodName=Wetrix (E) (M6) [f1] (NTSC) +CRC=792C3A8E 0F2200F7 +RefMD5=A99E2CB6ACEF7A004961DE5F6DFEEFF0 + +[087B6C2D5FBD778667C12D7FC7C305A7] +GoodName=Wetrix (E) (M6) [t1] +CRC=773E3E8E 1E8A0CBE +RefMD5=A99E2CB6ACEF7A004961DE5F6DFEEFF0 + +[E8997BF5662540B184FBF8277D260984] +GoodName=Wetrix (J) [!] +CRC=DCB6EAFA C6BBCFA3 +Players=4 +SaveType=Eeprom 4KB +CountPerOp=3 + +[08826E96F3FB022A1C6351774198BA9D] +GoodName=Wetrix (J) [o1] +CRC=DCB6EAFA C6BBCFA3 +RefMD5=E8997BF5662540B184FBF8277D260984 + +[6E81D3056E409208E4AF2D39A2FF0F03] +GoodName=Wetrix (U) (M6) [!] +CRC=CEA8B54F 7F21D503 +Players=4 +SaveType=None +Mempak=Yes +CountPerOp=3 + +[2ABE36754E866B9B6C4BDCFFC1D11ABF] +GoodName=Wheel of Fortune (U) [!] +CRC=E896092B DC244D4E +SaveType=None +Players=4 +Rumble=Yes + +[CC75D0771DBC825AC9F499400443A6A0] +GoodName=Wheel of Fortune (U) [b1] +CRC=E896092B DC244D4E +RefMD5=2ABE36754E866B9B6C4BDCFFC1D11ABF + +[D20F2C6704D5B93372816BA0559E4E0F] +GoodName=Wheel of Fortune (U) [o1] +CRC=E896092B DC244D4E +RefMD5=2ABE36754E866B9B6C4BDCFFC1D11ABF + +[CC8460B117AAFBD484CF43C1EB3D8E15] +GoodName=Wheel of Fortune (U) [o1][b1] +CRC=E896092B DC244D4E +RefMD5=2ABE36754E866B9B6C4BDCFFC1D11ABF + +[764DCDF5163D3FCE81D3E7189FA97E05] +GoodName=WideBoy BIOS V980910 +CRC=D1C6C55D F010EF52 + +[FFF632A867CDADB5AB2098CB8E2CFADC] +GoodName=WideBoy BIOS V980914 +CRC=64F1084A 763C7E91 + +[F85F2A2B6CA64898F0ADD2A78CCDCCF3] +GoodName=Wild Choppers (J) [!] +CRC=0CEBC4C7 0C9CE932 +Players=1 +SaveType=Eeprom 4KB +Rumble=Yes + +[BA538CBF43471B3522C4D08BAD0797A7] +GoodName=Wild Choppers (J) [b1] +CRC=0CEBC4C7 0C9CE932 +RefMD5=F85F2A2B6CA64898F0ADD2A78CCDCCF3 + +[AC1339207A3E442B61EC0E074673C93B] +GoodName=Wild Choppers (J) [b2] +CRC=F4520439 753A6281 +RefMD5=F85F2A2B6CA64898F0ADD2A78CCDCCF3 + +[DFB55C3F9B2D2A188616E9C123E0C816] +GoodName=Wild Choppers (J) [b3] +CRC=0CEBC4C7 0C9CE932 +RefMD5=F85F2A2B6CA64898F0ADD2A78CCDCCF3 + +[7FE135D08035782A8AAE0BEFE9A9780B] +GoodName=Wild Choppers (J) [o1] +CRC=0CEBC4C7 0C9CE932 +RefMD5=F85F2A2B6CA64898F0ADD2A78CCDCCF3 + +[B2DE25613755B234A376747422D83BBC] +GoodName=Wild Choppers (J) [t1] +CRC=F4520439 753A6281 +RefMD5=F85F2A2B6CA64898F0ADD2A78CCDCCF3 + +[B867880C96C9E8D3130DDE5526C95439] +GoodName=Wildwaters (U) (Prototype) +CRC=A04237B9 68F62C72 + +[EE3D3550ACC463CA57408BF14E541F68] +GoodName=WinBack (J) (V1.0) [!] +CRC=1FA056E0 A4B9946A +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[1B94D98F509F467F9BC541102F6EBDFC] +GoodName=WinBack (J) (V1.0) [b1] +CRC=1FA056E0 A4B9946A +RefMD5=EE3D3550ACC463CA57408BF14E541F68 + +[9789A48E1D9E42C2F69C59964371089F] +GoodName=WinBack (J) (V1.1) [!] +CRC=C52E0BC6 56BC6556 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[48DA6CDCAB838153CAA2ECC3DD592A65] +GoodName=WinBack - Covert Operations (U) [!] +CRC=ED98957E 8242DCAC +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[ACC6FD4E26D360D1BED54C316D7E33B9] +GoodName=WinBack - Covert Operations (U) [b1] +CRC=ED98957E 8242DCAC +RefMD5=48DA6CDCAB838153CAA2ECC3DD592A65 + +[F3365B47E430011D89162FB0D7DD8DE5] +GoodName=WinBack - Covert Operations (U) [f1] (PAL) +CRC=337F24EE 73A807D9 +RefMD5=48DA6CDCAB838153CAA2ECC3DD592A65 + +[FA34EAEBAA8A4E48D6BBD93DF62CD995] +GoodName=WinBack - Covert Operations (U) [t1] +CRC=35F51C8E 39EF72B8 +RefMD5=48DA6CDCAB838153CAA2ECC3DD592A65 + +[5783373634B11F81C86908C3D81CA988] +GoodName=Wipeout 64 (E) [!] +CRC=54310E7D 6B5430D8 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[7260DA1CECD0D8844C5E29AA63476DEF] +GoodName=Wipeout 64 (E) (Beta) [!] +CRC=136EBEE3 35B7229E +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[73C6D87DBE50F73F3B44E0F237A546D7] +GoodName=Wipeout 64 (U) [!] +CRC=132D2732 C70E9118 +SaveType=None +Mempak=Yes +Rumble=Yes +Players=4 +CountPerOp=1 + +[361F65D37F41536CDE98F83CAD456217] +GoodName=Wipeout 64 (U) [o1] +CRC=132D2732 C70E9118 +RefMD5=73C6D87DBE50F73F3B44E0F237A546D7 + +[0E274A162CAD0B1B50F9B8D64D9F82FC] +GoodName=Wipeout 64 (U) [t1] +CRC=A6A99491 52B4E765 +RefMD5=73C6D87DBE50F73F3B44E0F237A546D7 + +[B8DD77F17A8B638B1D38F57C81EAA89A] +GoodName=Wipeout 64 (U) [t2] +CRC=A6A99491 52B4E765 +RefMD5=73C6D87DBE50F73F3B44E0F237A546D7 + +[0FF1F8628D8FE69582DB54572D2BEA79] +GoodName=Wonder Project J2 - Koruro no Mori no Jozet (J) [!] +CRC=E43C9765 05B1C1BE +Players=1 +SaveType=None +Mempak=Yes +CountPerOp=1 + +[D6E56B92EC7DBFB8B14DD5D8CFF6492E] +GoodName=Wonder Project J2 - Koruro no Mori no Jozet (J) [b1] +CRC=E43C9765 05B1C1BE +RefMD5=0FF1F8628D8FE69582DB54572D2BEA79 + +[F5977968B621E74773E80CC4A33F7D2E] +GoodName=Wonder Project J2 - Koruro no Mori no Jozet (J) [h1C] +CRC=E43C9765 05B1C1BE +RefMD5=0FF1F8628D8FE69582DB54572D2BEA79 + +[3C02F56DD7B1A06BE83A7A288755612F] +GoodName=Wonder Project J2 - Koruro no Mori no Jozet (J) [T+Eng1.0_Ryu] +CRC=4F1E88F7 4A5A3F96 +RefMD5=0FF1F8628D8FE69582DB54572D2BEA79 + +[3AA263ACA66F3A07BB081B575D66DEEB] +GoodName=World Cup 98 (E) (M8) [!] +CRC=F9FC3090 FF014EC2 +Players=4 +SaveType=None +Mempak=Yes + +[E3DB1863E138B3AD5685A16029D0A44C] +GoodName=World Cup 98 (E) (M8) [f1] (NTSC) +CRC=F9FC3090 FF014EC2 +RefMD5=3AA263ACA66F3A07BB081B575D66DEEB + +[4BEF5E9AA9E71205DAC1A7060E778235] +GoodName=World Cup 98 (U) (M8) [!] +CRC=BD636D6A 5D1F54BA +Players=4 +SaveType=None +Mempak=Yes + +[431DE8F6611A8131B536F0EDE1F330D9] +GoodName=World Driver Championship (E) (M5) [!] +CRC=AC062778 DFADFCB8 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[9A2B0F3226FB8D129BEB7509C169476A] +GoodName=World Driver Championship (E) (M5) [h1C] +CRC=AC062778 DFADFCB8 +RefMD5=431DE8F6611A8131B536F0EDE1F330D9 + +[7C567A5BB1AD4CBE414FB6BBFF66E336] +GoodName=World Driver Championship (U) [!] +CRC=308DFEC8 CE2EB5F6 +Players=2 +SaveType=None +Mempak=Yes +Rumble=Yes +CountPerOp=1 + +[4B86C373533D015860467C5DC1F1C662] +GoodName=World Driver Championship (U) [b1] +CRC=308DFEC8 CE2EB5F6 +RefMD5=7C567A5BB1AD4CBE414FB6BBFF66E336 + +[0C26665C2F40A786778EE4370C3A43FC] +GoodName=World Driver Championship (U) [f1] (PAL) +CRC=2A721F06 4097F7B1 +RefMD5=7C567A5BB1AD4CBE414FB6BBFF66E336 + +[628C10A5D2ACC462C5527E6302467440] +GoodName=World Driver Championship (U) [f2] (PAL) +CRC=2A980400 7D805B1C +RefMD5=7C567A5BB1AD4CBE414FB6BBFF66E336 + +[A4599EF88F36E62C1692BCEC416C5477] +GoodName=World Driver Championship (U) [t1] +CRC=C8FEF05D DAA3407D +RefMD5=7C567A5BB1AD4CBE414FB6BBFF66E336 + +[44FC2A7F028F0B6F71B255F672C8B495] +GoodName=Worms - Armageddon (E) (M6) [!] +CRC=2D21C57B 8FE4C58C +Players=4 +SaveType=Eeprom 4KB + +[35FDA68C8481F7C3419CCD91EDBB6A9E] +GoodName=Worms - Armageddon (E) (M6) [f1] (NTSC) +CRC=94FBA5FD BC8FE181 +RefMD5=44FC2A7F028F0B6F71B255F672C8B495 + +[491D4DB6718302489BF05FB962C73651] +GoodName=Worms - Armageddon (U) (M3) [!] +CRC=13E959A0 0E93CAB0 +Players=4 +SaveType=Eeprom 4KB + +[EC2BCB1B7FC7D068BE1F39E79E49A842] +GoodName=Xena Warrior Princess - The Talisman of Fate (E) [!] +CRC=0A1667C7 293346A6 +CountPerOp=4 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[1AC234649D28F09E82C0D11ABB17F03B] +GoodName=Xena Warrior Princess - The Talisman of Fate (U) [!] +CRC=0553AE9D EAD8E0C1 +CountPerOp=3 +Players=4 +SaveType=None +Mempak=Yes +Rumble=Yes + +[687AF471A5A16D665E16AC1E9069D16B] +GoodName=Xena Warrior Princess - The Talisman of Fate (U) [f1] (PAL) +CRC=BC875B60 8C993DF1 +RefMD5=1AC234649D28F09E82C0D11ABB17F03B + +[6CB35999D2E3820391913F0E4B9BC072] +GoodName=Xena Warrior Princess - The Talisman of Fate (U) [t1] +CRC=BEADC61C 8622D9F6 +RefMD5=1AC234649D28F09E82C0D11ABB17F03B + +[9137129A586E1BCAB6AE81BAC6B01275] +GoodName=Xplorer64 BIOS V1.067 (G) +CRC=656C6561 73652031 + +[763E5EACA4606E15A1E4D67DD6D987C0] +GoodName=XtraLife Dextrose Demo by RedboX (PD) [h1C] +CRC=1EDA4DE0 22BF698D + +[46C45620F26E4ED77B918F862FA597CD] +GoodName=XtraLife Dextrose Demo by RedboX (PD) +CRC=1EDA4DE0 22BF698D + +[A954E2BC5D774DC6E1CEBCE529F1CDED] +GoodName=Y2K Demo by WT_Riker (PD) [b1] +CRC=83F9F2CB E7BC4744 + +[76A1480BE9985D30FC580E4216974D3E] +GoodName=Y2K Demo by WT_Riker (PD) +CRC=83F9F2CB E7BC4744 + +[E24942948F7140EE4260268DB763D0FD] +GoodName=Yakouchuu II - Satsujin Kouru (J) [!] +CRC=9F8B96C3 A01194DC +Players=1 +Rumble=Yes +CountPerOp=1 + +[F7AA4F819F41CB4236792A8145684627] +GoodName=Yoshi's Story (Ch) (iQue) [!] + +[DF8164DA753C9EF0B7C2611F584E81A9] +GoodName=Yoshi's Story (Ch) (V2) (iQue) (Manual) [!] + +[D6778D9D560DEC35D8C05AF4738E27AA] +GoodName=Yoshi's Story (Ch) (V4) (iQue) (Manual) [!] + +[85A90C61B65B56334E00950210C6CFC4] +GoodName=Yoshi's Story (Ch) (V6) (iQue) (Manual) [!] + +[DD8A0E5472F13EA87B176F0155FA0C66] +GoodName=Yoshi Story (J) [!] +CRC=2DCFCA60 8354B147 +Players=1 +SaveType=Eeprom 16KB +Rumble=Yes + +[B7B236051E4347428288F8D840BFD2E4] +GoodName=Yoshi Story (J) [b1] +CRC=E3CCFE36 398FBC75 +RefMD5=DD8A0E5472F13EA87B176F0155FA0C66 + +[4BA4B1A2ABAF72EC83A2DB4CB6AEB7D6] +GoodName=Yoshi Story (J) [f1] +CRC=70666F63 FEC28A44 +RefMD5=DD8A0E5472F13EA87B176F0155FA0C66 + +[38F004F68D5F1ABBC4391D156DEBCAEF] +GoodName=Yoshi Story (J) [f2] +CRC=70666F63 FEC28A44 +RefMD5=DD8A0E5472F13EA87B176F0155FA0C66 + +[C43E3E28D84F337FF1BC88FA77996D33] +GoodName=Yoshi Story (J) [f3] +CRC=05BCD54E 97E2A8C9 +RefMD5=DD8A0E5472F13EA87B176F0155FA0C66 + +[20ED9559D47535EA491D3548FB9E15E2] +GoodName=Yoshi Story (J) [f4] +CRC=D4DD9982 FDBA7B67 +RefMD5=DD8A0E5472F13EA87B176F0155FA0C66 + +[3B41BAD41ABF4512FBF62727410EAC71] +GoodName=Yoshi Story (J) [t1] +CRC=369B314B E7780D04 +RefMD5=DD8A0E5472F13EA87B176F0155FA0C66 + +[CF3802A99D8FE412359F1EB018FD991F] +GoodName=Yoshi Story (J) [t2] (Health and Eggs) +CRC=AF5F3773 B29B2C9A +RefMD5=DD8A0E5472F13EA87B176F0155FA0C66 + +[2524E5FB8ED4BB8C831C5AC057E8F344] +GoodName=Yoshi's Story (E) (M3) [!] +CRC=D3F97D49 6924135B +Players=1 +SaveType=Eeprom 16KB +Rumble=Yes + +[6E5E919D0FA292B97AAD08E9200E8C9C] +GoodName=Yoshi's Story (E) (M3) [b1] +CRC=D3F97D49 6924135B +RefMD5=2524E5FB8ED4BB8C831C5AC057E8F344 + +[5D3C7935193A3B7327021B5E4740DEB6] +GoodName=Yoshi's Story (E) (M3) [b2] +CRC=D3F97D49 6924135B +RefMD5=2524E5FB8ED4BB8C831C5AC057E8F344 + +[E2F6EF5D4181558656DDE8B0162D39D3] +GoodName=Yoshi's Story (E) (M3) [b2][f1] +CRC=9CB1BBB0 BC3439C7 +RefMD5=2524E5FB8ED4BB8C831C5AC057E8F344 + +[C80D0A8193D530530AE875F8D9398E82] +GoodName=Yoshi's Story (E) (M3) [b3] +CRC=D3F97D49 6924135B +RefMD5=2524E5FB8ED4BB8C831C5AC057E8F344 + +[ADEE5835A112677CCF74D5F4A1503294] +GoodName=Yoshi's Story (E) (M3) [t1] (Health and Eggs) +CRC=94FEDD3F 95719E88 +RefMD5=2524E5FB8ED4BB8C831C5AC057E8F344 + +[586A092E22604840973B82DFACEAC77A] +GoodName=Yoshi's Story (U) (M2) [!] +CRC=2337D8E8 6B8E7CEC +Players=1 +SaveType=Eeprom 16KB +Rumble=Yes + +[B907C051F1D7D0D15DE65EA87CF3F922] +GoodName=Yoshi's Story (U) (M2) [b1] +CRC=9CB1BBB0 BC3439C7 +RefMD5=586A092E22604840973B82DFACEAC77A + +[B4A2127033CB671EEFE535B08F1AFB38] +GoodName=Yoshi's Story (U) (M2) [b2] +CRC=88047F1D 3B837D28 +RefMD5=586A092E22604840973B82DFACEAC77A + +[D635824B5FC256DA0F2E457663CFF286] +GoodName=Yoshi's Story (U) (M2) [b3] +CRC=CCE336FE 8F3975BC +RefMD5=586A092E22604840973B82DFACEAC77A + +[75F91A5D3012080EE9BF90C017B5128F] +GoodName=Yoshi's Story (U) (M2) [b4] +CRC=395E91DF 441D95C5 +RefMD5=586A092E22604840973B82DFACEAC77A + +[8F47F6A80734D6C8501ADED549FF65C5] +GoodName=Yoshi's Story (U) (M2) [b5] +CRC=E3CCFE36 398FBC75 +RefMD5=586A092E22604840973B82DFACEAC77A + +[0DCF29478A6DB0A3113B9EDD2AE428E1] +GoodName=Yoshi's Story (U) (M2) [f1] +CRC=E3CCFE36 398FBC75 +RefMD5=586A092E22604840973B82DFACEAC77A + +[7CE4559FED0EA7D82670E9A4ECC370CD] +GoodName=Yoshi's Story (U) (M2) [t1] +CRC=88047F1D 3B837D28 +RefMD5=586A092E22604840973B82DFACEAC77A + +[3DA2C5FA29D11D0481B60F6C6B14393A] +GoodName=Yoshi's Story (U) (M2) [t2] (Health and Eggs) +CRC=E606EE26 8783EC43 +RefMD5=586A092E22604840973B82DFACEAC77A + +[5FE7486A5A458D538179DA898B067AD3] +GoodName=Yoshi's Story BootEmu (PD) +CRC=83D8A30C 8552C117 + +[2AE35BDF163613024D876A09F25063F3] +GoodName=Yuke Yuke!! Trouble Makers (J) [!] +CRC=9FE6162D E97E4037 +Players=1 +SaveType=Eeprom 4KB +CountPerOp=1 + +[6F9E56C8A2B6BA5F6DBE5214E352590D] +GoodName=Yuke Yuke!! Trouble Makers (J) [a1] +CRC=9FE6162D E97E4037 +RefMD5=2AE35BDF163613024D876A09F25063F3 + +[BE734B15770D28C0A26D2DB98DF6CCCC] +GoodName=Yuke Yuke!! Trouble Makers (J) [b1] +CRC=9FE6162D E97E4037 +RefMD5=2AE35BDF163613024D876A09F25063F3 + +[BADCEDF5B6BECDBCCA7267BD2D791EB1] +GoodName=Yuke Yuke!! Trouble Makers (J) [o1] +CRC=9FE6162D E97E4037 +RefMD5=2AE35BDF163613024D876A09F25063F3 + +[C66D2037A654378C5CD365B135E36D87] +GoodName=Z64 BIOS V1.05 +CRC=551E06B4 02CD16A8 + +[730209AD52C178551C29074F49AE9B39] +GoodName=Z64 BIOS V1.07 +CRC=551E06B4 02CD16A8 + +[60BC7FE282C6BE6B90EA0B5FC63BC944] +GoodName=Z64 BIOS V1.08 (Ravemax Hack V1.00b) +CRC=00000000 00005053 + +[F5441580B27ECFB94A8C6B7989B1D101] +GoodName=Z64 BIOS V1.08 +CRC=00000000 00005053 + +[60A39BA7F3DCC592112FDF8220335F3D] +GoodName=Z64 BIOS V1.09 +CRC=00000000 00005053 + +[1412DDDCFD2DC960DA7D282D99FC2356] +GoodName=Z64 BIOS V1.10b +CRC=00000000 00005053 + +[40E74DA10255DCF00A45F02BED1AFCAD] +GoodName=Z64 BIOS V1.11 +CRC=00000000 00005053 + +[E81062B36B08078CE4CFF5A362F44764] +GoodName=Z64 BIOS V1.12 +CRC=00000000 00005053 + +[FFAAAFB32A2D87C6B621B62FFC85A2D6] +GoodName=Z64 BIOS V2.00 (Barebones) +CRC=B038EEEB 00BA6901 + +[A1CDE773E4FB8B691098F2B3D5F2DBBA] +GoodName=Z64 BIOS V2.00 +CRC=00000000 00005053 + +[319377A6D811EF8AD7B3E16B537E6346] +GoodName=Z64 BIOS V2.00b (Ravemax Hack) +CRC=00000000 00005053 + +[72775AB85B5106A97DECB0520DFD9180] +GoodName=Z64 BIOS V2.10NTSC +CRC=00000000 00005053 + +[DB67B8D7251314163E4F713724F55C66] +GoodName=Z64 BIOS V2.10PAL +CRC=00000000 00005053 + +[B15D755B8C6A4B5933802E5F227A183C] +GoodName=Z64 BIOS V2.11NTSC +CRC=00000000 00005053 + +[0CC1A139F9C3865FE698C64209C45253] +GoodName=Z64 BIOS V2.11PAL +CRC=00000000 00005053 + +[E76F0536CDAD4C6F89802E15A98AE985] +GoodName=Z64 BIOS V2.12NTSC +CRC=00000000 00005053 + +[CC2433DFB7738D5CB71A75B054E52DD5] +GoodName=Z64 BIOS V2.12PAL +CRC=00000000 00005053 + +[07C468E5050FC619791437930D740B10] +GoodName=Z64 BIOS V2.12b (Nintendo Backup Crew Hack) +CRC=00000000 00005053 + +[0170C86E42E15A364CDC6E176A63A500] +GoodName=Z64 BIOS V2.12b3 +CRC=00000000 00005053 + +[D65B99356296CA8F6B3273540203E0AA] +GoodName=Z64 BIOS V2.12b4 +CRC=00000000 00005053 + +[B6D6EDA244C308E63D36EEC607942605] +GoodName=Z64 BIOS V2.13 +CRC=00000000 00005053 + +[A4B138CAEDCE038D93C5B1FEDD897E7D] +GoodName=Z64 BIOS V2.15 +CRC=00000000 00005053 + +[4F557C3F71C0D04A54776450913E027F] +GoodName=Z64 BIOS V2.16 +CRC=00000000 00005053 + +[8EEE06C88613B1265721B26517B64F2C] +GoodName=Z64 BIOS V2.16b +CRC=00000000 00005053 + +[B29240BC2FFA6C46B83023F2226E3CDE] +GoodName=Z64 BIOS V2.17 [h1] +CRC=00000000 00005053 + +[0658D69EBA236FDF6DA5D491BDC96574] +GoodName=Z64 BIOS V2.17 by zmod.onestop.net (ORB HDisk ZIP250 2.18zd Hack) +CRC=00000000 00005053 + +[568D51E1D4602CD74AC3A2D9719A390A] +GoodName=Z64 BIOS V2.17 by zmod.onestop.net (ORB HDisk ZIP250 Hack) +CRC=00000000 00005053 + +[1630A446857F28D3068907F302B02114] +GoodName=Z64 BIOS V2.17 +CRC=00000000 00005053 + +[7344708B7E0FC0683BBA86D902B9603D] +GoodName=Zelda 64 Boot Emu V1 by Crazy Nation (PD) [a1] +CRC=9A7A9F14 05137CC7 + +[015A3F07366CEF93B5CB38B386E659F4] +GoodName=Zelda 64 Boot Emu V1 by Crazy Nation (PD) +CRC=9A7A9F14 05137CC7 + +[E419774A7113F1B82F6621EA512F10CF] +GoodName=Zelda 64 Boot Emu V2 by Crazy Nation (PD) [a1] +CRC=60005D15 65727EFF + +[01E2C444385597DC4FCF09E45C522B01] +GoodName=Zelda 64 Boot Emu V2 by Crazy Nation (PD) +CRC=60005D15 65727EFF + +[692A33B0D7456FC733A81AB83C20382B] +GoodName=Zool - Majou Tsukai Densetsu (J) [!] +CRC=1C010CCD 22D3B7FA +Players=1 +Mempak=Yes + +[4F8E5341B89E6C2069A319EF2FB58B16] +GoodName=Zool - Majou Tsukai Densetsu (J) [f1] (PAL) +CRC=7711DBA7 4856F7E0 +RefMD5=692A33B0D7456FC733A81AB83C20382B + +[1DDE4D26CEDB2E8565AACB2C8098DF8D] +GoodName=Neon64 GS V1.05 (Gameshark Version) (PD) +CRC=03D7F021 8FDE0000 + +[775E6D9305BF219C0696063C809F2B48] +GoodName=Neon64 GS V1.1 (Gameshark Version) (PD) +CRC=3C0A8030 354A4E78 + +[4C3F1B48E7252391B337D9BAE404CF83] +GoodName=Neon64 GS V1.2 (Gameshark Version) (PD) +CRC=3C0A8030 354A5198 + +[81A2C7E1EC426D3AEE1C4B823A2BC7BF] +GoodName=Neon64 GS V1.2 (Pro Action Replay Version) (PD) +CRC=3C0A802D 354A3458 + +[90FAF5461E5F5CD5B67CE7891B9B055B] +GoodName=Neon64 GS V1.2a (Gameshark Version) (PD) +CRC=3C0A8030 354A51B0 + +[B9A06A029A842207A9E17AA40A702F7B] +GoodName=Neon64 GS V1.2a (Pro Action Replay Version) (PD) +CRC=3C0A802D 354A3470 + +[9BE795563DBA802DD566DF75D6106CFC] +GoodName=Z64 BIOS V2.18 +CRC=00000000 00005053 + +[4B2DBC0D448B7AD8569291E4E44821F0] +GoodName=N64probe by MooglyGuy (PD) +CRC=B216B9F1 AB27D881 + +[D7CB11A82EDAEE3F519346C7EAE201E9] +GoodName=ObjectVIEWER V1.1 by Kid Stardust (PD) +CRC=34E42466 F50868AC + +[A1D23D8C7A3194DCD0AC0CA1AF79136E] +GoodName=TheMuscularDemo by megahawks (PD) +CRC=B0565CCB BDA2C237 + +[DBF04773EC2B8ADF8A94DB7E3E461138] +GoodName=Mupen64Plus Demo by Marshallh (GPL) +CRC=DDBA4DE5 B107004A +Status=5 +Players=0 +SaveType=None + +[46C9461B0B6F232C5A50CA795395D706] +GoodName=DS1 Manager V1.1 by R. Bubba Magillicutty (PD) [T+Ita] +CRC=868214B8 AB2BE6B7 + +[02E344EC824BBA4A4CFFCAC5FEADEA51] +GoodName=F-ZERO Expansion Kit (N64DD) +CRC=2129FFF8 AD000000 + +[685B2F0DECB5BE33D25145E55F24A6D3] +GoodName=F-Zero X Expansion Kit (J) [CART HACK] +CRC=BBFDEC37 D93B9EC0 +Players=1 +Rumble=Yes + +[5932D07D6AAA84B7D74F5251D8942C91] +GoodName=F-Zero X Expansion Kit (U) [CART HACK] +CRC=C6E39C0A D2726676 +Players=1 +Rumble=Yes + +[8D3D9F294B6E174BC7B1D2FD1C727530] +GoodName=N64DD IPLROM (J) +CRC=00000000 00000000 + +[83807A5437A2EA21E2133DBA1E410750] +GoodName=Wonder Project J2 - Koruro no Mori no Jozet (J) [T-Eng0.05] +CRC=3A4B5938 A26F989D +RefMD5=0FF1F8628D8FE69582DB54572D2BEA79 + +[E0530F182EA3BB780A6264B1D06737A1] +GoodName=Z64 BIOS V2.20cf +CRC=00000000 00005053 + +[D3929AADF7640F8C5B4CE8321AD4393A] +GoodName=Zelda no Densetsu - Mujura no Kamen (J) (GC) [!] +CRC=8473D0C1 23120666 +SaveType=Flash RAM +Status=4 +Rumble=Yes +Players=1 + +[15D1A2217CAD61C39CFECBFFA0703E25] +GoodName=Zelda no Densetsu - Mujura no Kamen (J) (V1.0) [!] +CRC=EC417312 EB31DE5F +SaveType=Flash RAM +Status=4 +Rumble=Yes +Players=1 + +[3E60CA693BABFF1F62CF8C0AEC338556] +GoodName=Zelda no Densetsu - Mujura no Kamen (J) (V1.0) [b1] +CRC=EC417312 EB31DE5F +RefMD5=15D1A2217CAD61C39CFECBFFA0703E25 + +[0F6D3EDB5797A775757336549A8A9B94] +GoodName=Zelda no Densetsu - Mujura no Kamen (J) (V1.0) [b1][o1] +CRC=EC417312 EB31DE5F +RefMD5=15D1A2217CAD61C39CFECBFFA0703E25 + +[E0CED30BF10F05EBAF1F1A27563E3E5D] +GoodName=Zelda no Densetsu - Mujura no Kamen (J) (V1.0) [f1] +CRC=EE7AF9EC A750B2D3 +RefMD5=15D1A2217CAD61C39CFECBFFA0703E25 + +[0FA23CD30B68EB86548630FE635BB90E] +GoodName=Zelda no Densetsu - Mujura no Kamen (J) (V1.0) [o1] +CRC=EC417312 EB31DE5F +RefMD5=15D1A2217CAD61C39CFECBFFA0703E25 + +[C38A7F6F6B61862EA383A75CDF888279] +GoodName=Zelda no Densetsu - Mujura no Kamen (J) (V1.1) [!] +CRC=69AE0438 2C63F3F3 +RefMD5=15D1A2217CAD61C39CFECBFFA0703E25 + +; 64DD Games +; +[8D3D9F294B6E174BC7B1D2FD1C727530] +GoodName=64DD IPL (JPN) + +[37C36E4286D36892A9FC70EAFE4104BE] +GoodName=64DD IPL (USA) + +[8485643E5830CD67ED4C0A5FD49E2491] +GoodName=Mario Artist Paint Studio (J) + +[88228E990B58A94E9B3460BEFF632304] +GoodName=Mario Artist Talent Studio (J) + +[114AF722029D6386C3BFEA4CC8FA603C] +GoodName=Mario Artist Communication Kit (J) + +[DA23EE561578B7DAD77ED72728B46D30] +GoodName=Mario Artist Polygon Studio (J) + +[EBBA03F20096FC2BC178FC3A1F4EC2B6] +GoodName=Sim City 64 (J) + +[9F797A9C704B5EBD04D6A2B036309AF2] +GoodName=Nihon Pro Golf Tour 64 (J) + +[E8EB810D996E12CD6C47445F87A94C72] +GoodName=Kyojin no Doshin 1 (J) + +[AFE059AE1210751B6C849CFB482C99DD] +GoodName=Kyojin no Doshin 1 (J) (Store Demo) + +[26087E0750FC6DA0F3DE2A431E34BDDF] +GoodName=Randnet Disk (J) [Rev. 00] + +[33CBC59786063285DC3C090E0ED312E3] +GoodName=Randnet Disk (J) [Rev. 01] + +[FCCA9AF8C1174C40B478EA0E02673B16] +GoodName=Kyojin no Doshin - Kaihou Sensen Chibikkochikko Dai Shuugou (J) + +[CB2FB00C3921245AE04BB38BA01ABE92] +GoodName=F-ZERO X Expansion Kit (J) + +[D9EA905727B44F2774926CB03C2300A7] +GoodName=Super Mario 64 Disk Version (J) (Spaceworld 1996 Demo) + +[84706E10026BD2EE9654DA5E9821598D] +GoodName=Dezaemon 3D Expansion Disk (J) (Proto) +SaveType=SRAM + +[7BB3974754A54BA27A93F96691DC4695] +GoodName=Dezaemon 3D Expansion Disk (J) (Proto) +SaveType=SRAM + +[40AA8EC52C5E025D6C6AD94CEBC2218F] +GoodName=Dezaemon 3D Expansion Disk (J) (Proto) +SaveType=SRAM + +[C108A9B1EB024F0D2317C05976BA49F2] +GoodName=Dezaemon 3D Expansion Disk (J) (Proto) [a1] +SaveType=SRAM + +[4D02F5A719BD455F67721C64B16AE0CB] +GoodName=Mario Artist Paint Studio (J) (1999-02-11 Proto) +CountPerOp=1 + +[A76B619EC832A7E2ABCFBDFEB5375E39] +GoodName=Mario Artist Paint Studio (J) (1999-02-11 Proto) +CountPerOp=1 diff --git a/sw/deployer/src/debug.rs b/sw/deployer/src/debug.rs new file mode 100644 index 0000000..cfa69d1 --- /dev/null +++ b/sw/deployer/src/debug.rs @@ -0,0 +1,396 @@ +use crate::sc64; +use chrono::Local; +use colored::Colorize; +use panic_message::panic_message; +use std::{ + fs::File, + io::{stdin, ErrorKind, Read, Write}, + net::{TcpListener, TcpStream}, + panic, + sync::mpsc::{channel, Receiver, Sender}, + thread::{sleep, spawn}, + time::Duration, +}; + +pub struct Handler { + header: Option>, + line_rx: Receiver, + gdb_tx: Sender>, + gdb_rx: Receiver>, +} + +enum DataType { + Text, + RawBinary, + Header, + Screenshot, + GDB, + Unknown, +} + +impl From for DataType { + fn from(value: u8) -> Self { + match value { + 0x01 => Self::Text, + 0x02 => Self::RawBinary, + 0x03 => Self::Header, + 0x04 => Self::Screenshot, + 0xDB => Self::GDB, + _ => Self::Unknown, + } + } +} + +impl From for u8 { + fn from(value: DataType) -> Self { + match value { + DataType::Text => 0x01, + DataType::RawBinary => 0x02, + DataType::Header => 0x03, + DataType::Screenshot => 0x04, + DataType::GDB => 0xDB, + DataType::Unknown => 0xFF, + } + } +} + +impl From for u32 { + fn from(value: DataType) -> Self { + u8::from(value) as u32 + } +} + +#[derive(Clone, Copy)] +enum ScreenshotPixelFormat { + Rgba16, + Rgba32, +} + +impl TryFrom for ScreenshotPixelFormat { + type Error = String; + fn try_from(value: u32) -> Result { + Ok(match value { + 2 => Self::Rgba16, + 4 => Self::Rgba32, + _ => return Err("Invalid pixel format for screenshot metadata".into()), + }) + } +} + +impl From for u32 { + fn from(value: ScreenshotPixelFormat) -> Self { + match value { + ScreenshotPixelFormat::Rgba16 => 2, + ScreenshotPixelFormat::Rgba32 => 4, + } + } +} + +struct ScreenshotMetadata { + format: ScreenshotPixelFormat, + width: u32, + height: u32, +} + +impl TryFrom> for ScreenshotMetadata { + type Error = String; + fn try_from(value: Vec) -> Result { + if value.len() != 16 { + return Err("Invalid header length for screenshot metadata".into()); + } + if u32::from_be_bytes(value[0..4].try_into().unwrap()) != DataType::Screenshot.into() { + return Err("Invalid header datatype for screenshot metadata".into()); + } + let format = u32::from_be_bytes(value[4..8].try_into().unwrap()); + let width = u32::from_be_bytes(value[8..12].try_into().unwrap()); + let height = u32::from_be_bytes(value[12..16].try_into().unwrap()); + if width > 4096 || height > 4096 { + return Err("Invalid width or height for screenshot metadata".into()); + } + Ok(ScreenshotMetadata { + format: format.try_into()?, + width, + height, + }) + } +} + +impl Handler { + pub fn process_user_input(&self) -> Option { + if let Ok(line) = self.line_rx.try_recv() { + if line.len() == 0 { + return None; + } + let mut data: Vec = Vec::new(); + if line.matches("@").count() != 2 { + data.append(&mut line.as_bytes().to_vec()); + data.append(&mut [b'\0'].to_vec()); + return Some(sc64::DebugPacket { + datatype: DataType::Text.into(), + data, + }); + } else { + let start = line.find("@").unwrap(); + let end = line.rfind("@").unwrap(); + let path = &line[start + 1..end]; + if path.len() == 0 { + println!("Invalid path provided"); + return None; + } + let mut file = match File::open(path) { + Ok(file) => file, + Err(error) => { + println!("Couldn't open file: {error}"); + return None; + } + }; + let length = match file.metadata() { + Ok(metadata) => metadata.len(), + Err(error) => { + println!("Couldn't get file length: {error}"); + return None; + } + }; + let mut data = vec![0u8; length as usize]; + if let Err(error) = file.read_exact(&mut data) { + println!("Couldn't read file contents: {error}"); + return None; + } + if line.starts_with("@") && line.ends_with("@") { + return Some(sc64::DebugPacket { + datatype: DataType::RawBinary.into(), + data, + }); + } else { + let mut combined_data: Vec = Vec::new(); + combined_data.append(&mut line[0..start].as_bytes().to_vec()); + combined_data.append(&mut [b'@'].to_vec()); + combined_data.append(&mut format!("{length}").into_bytes()); + combined_data.append(&mut [b'@'].to_vec()); + combined_data.append(&mut data); + combined_data.append(&mut [b'\0'].to_vec()); + return Some(sc64::DebugPacket { + datatype: DataType::Text.into(), + data: combined_data, + }); + } + } + } + None + } + + pub fn handle_debug_packet(&mut self, debug_packet: sc64::DebugPacket) { + let sc64::DebugPacket { datatype, data } = debug_packet; + match datatype.into() { + DataType::Text => self.handle_datatype_text(&data), + DataType::RawBinary => self.handle_datatype_raw_binary(&data), + DataType::Header => self.handle_datatype_header(&data), + DataType::Screenshot => self.handle_datatype_screenshot(&data), + DataType::GDB => self.handle_datatype_gdb(&data), + _ => { + println!("Unknown debug packet datatype: 0x{datatype:02X}"); + } + } + } + + fn handle_datatype_text(&self, data: &[u8]) { + print!("{}", String::from_utf8_lossy(data)); + } + + fn handle_datatype_raw_binary(&self, data: &[u8]) { + let filename = &self.generate_filename("binaryout", "bin"); + match File::create(filename) { + Ok(mut file) => { + if let Err(error) = file.write_all(data) { + println!("Error during raw binary save: {error}"); + } + println!("Wrote {} bytes to [{}]", data.len(), filename); + } + Err(error) => { + println!("Error during raw binary file creation: {error}"); + } + } + } + + fn handle_datatype_header(&mut self, data: &[u8]) { + self.header = Some(data.to_vec()); + } + + fn handle_datatype_screenshot(&mut self, data: &[u8]) { + let header = match self.header.take() { + Some(header) => header, + None => { + println!("Got screenshot packet without header data"); + return; + } + }; + let ScreenshotMetadata { + format, + height, + width, + } = match header.try_into() { + Ok(data) => data, + Err(error) => { + println!("{error}"); + return; + } + }; + let format_size: u32 = format.into(); + if data.len() as u32 != format_size * width * height { + println!("Data length did not match header data for screenshot datatype"); + return; + } + let mut image = image::RgbaImage::new(width, height); + for (x, y, pixel) in image.enumerate_pixels_mut() { + let location = ((x + (y * width)) * format_size) as usize; + let p = &data[location..location + format_size as usize]; + pixel.0 = match format { + ScreenshotPixelFormat::Rgba16 => { + let r = ((p[0] >> 3) & 0x1F) << 3; + let g = (((p[0] & 0x07) << 2) | ((p[1] >> 6) & 0x03)) << 3; + let b = ((p[1] >> 1) & 0x1F) << 3; + let a = ((p[1]) & 0x01) * 255; + [r, g, b, a] + } + ScreenshotPixelFormat::Rgba32 => [p[0], p[1], p[2], p[3]], + } + } + let filename = &self.generate_filename("screenshot", "png"); + if let Some(error) = image.save(filename).err() { + println!("Error during image save: {error}"); + return; + } + println!("Wrote {width}x{height} pixels to [{filename}]"); + } + + fn handle_datatype_gdb(&self, data: &[u8]) { + self.gdb_tx.send(data.to_vec()).ok(); + } + + fn generate_filename(&self, prefix: &str, extension: &str) -> String { + format!( + "{prefix}-{}.{extension}", + Local::now().format("%y%m%d%H%M%S.%f") + ) + } + + pub fn receive_gdb_packet(&self) -> Option { + if let Some(data) = self.gdb_rx.try_recv().ok() { + Some(sc64::DebugPacket { + datatype: DataType::GDB.into(), + data, + }) + } else { + None + } + } +} + +pub fn new(gdb_port: Option) -> Result { + let (line_tx, line_rx) = channel::(); + let (gdb_tx, gdb_loop_rx) = channel::>(); + let (gdb_loop_tx, gdb_rx) = channel::>(); + + spawn(move || stdin_thread(line_tx)); + + if let Some(port) = gdb_port { + let listener = TcpListener::bind(format!("0.0.0.0:{port}")) + .map_err(|_| sc64::Error::new("Couldn't open GDB TCP socket port"))?; + listener.set_nonblocking(true).map_err(|_| { + sc64::Error::new("Couldn't set GDB TCP socket listener as non-blocking") + })?; + spawn(move || gdb_thread(listener, gdb_loop_tx, gdb_loop_rx)); + } + + Ok(Handler { + header: None, + line_rx, + gdb_tx, + gdb_rx, + }) +} + +fn stdin_thread(line_tx: Sender) { + loop { + let mut line = String::new(); + if stdin().read_line(&mut line).is_ok() { + if line_tx.send(line).is_err() { + return; + } + } + } +} + +fn gdb_thread(listener: TcpListener, gdb_tx: Sender>, gdb_rx: Receiver>) { + match panic::catch_unwind(|| gdb_loop(listener, gdb_tx, gdb_rx)) { + Ok(_) => {} + Err(payload) => { + eprintln!("{}", panic_message(&payload).red()); + } + }; +} + +fn gdb_loop(listener: TcpListener, gdb_tx: Sender>, gdb_rx: Receiver>) { + for tcp_stream in listener.incoming() { + match tcp_stream { + Ok(mut stream) => { + handle_gdb_connection(&mut stream, &gdb_tx, &gdb_rx); + } + Err(error) => { + if error.kind() == ErrorKind::WouldBlock { + sleep(Duration::from_millis(1)); + } else { + panic!("{error}"); + } + } + } + } +} + +fn handle_gdb_connection( + stream: &mut TcpStream, + gdb_tx: &Sender>, + gdb_rx: &Receiver>, +) { + const GDB_DATA_BUFFER: usize = 64 * 1024; + + let mut buffer = vec![0u8; GDB_DATA_BUFFER]; + + let peer = stream.peer_addr().unwrap(); + + println!("[GDB]: New connection ({peer})"); + + loop { + match stream.read(&mut buffer) { + Ok(length) => { + if length > 0 { + gdb_tx.send(buffer[0..length].to_vec()).ok(); + continue; + } else { + println!("[GDB]: Connection closed ({peer})"); + break; + } + } + Err(e) => { + if e.kind() != ErrorKind::WouldBlock { + println!("[GDB]: Connection closed ({peer}), read IO error: {e}"); + break; + } + } + } + + if let Ok(data) = gdb_rx.try_recv() { + match stream.write_all(&data) { + Ok(()) => { + continue; + } + Err(e) => { + println!("[GDB]: Connection closed ({peer}), write IO error: {e}"); + break; + } + } + } + + sleep(Duration::from_millis(1)); + } +} diff --git a/sw/deployer/src/disk.rs b/sw/deployer/src/disk.rs new file mode 100644 index 0000000..127261f --- /dev/null +++ b/sw/deployer/src/disk.rs @@ -0,0 +1,306 @@ +use crate::sc64::Error; +use std::{ + collections::HashMap, + fs::File, + io::{Read, Seek, SeekFrom, Write}, +}; + +const BLOCKS_PER_TRACK: usize = 2; +const SECTORS_PER_BLOCK: usize = 85; +const SYSTEM_SECTOR_LENGTH: usize = 232; +const BAD_TRACKS_PER_ZONE: usize = 12; + +#[derive(Clone, Copy, PartialEq)] +pub enum Format { + Retail, + Development, +} + +struct SystemAreaInfo<'a> { + format: Format, + sector_length: usize, + sys_lba: &'a [usize], + bad_lba: &'a [usize], +} + +const SYSTEM_AREA: [SystemAreaInfo; 2] = [ + SystemAreaInfo { + format: Format::Retail, + sector_length: 232, + sys_lba: &[9, 8, 1, 0], + bad_lba: &[2, 3, 10, 11, 12, 16, 17, 18, 19, 20, 21, 22, 23], + }, + SystemAreaInfo { + format: Format::Development, + sector_length: 192, + sys_lba: &[11, 10, 3, 2], + bad_lba: &[0, 1, 8, 9, 16, 17, 18, 19, 20, 21, 22, 23], + }, +]; + +const ID_LBAS: [usize; 2] = [15, 14]; + +struct DiskZone { + head: usize, + sector_length: usize, + tracks: usize, + track_offset: usize, +} + +macro_rules! zone { + ($h:expr, $l:expr, $t:expr, $o:expr) => { + DiskZone { + head: $h, + sector_length: $l, + tracks: $t, + track_offset: $o, + } + }; +} + +const ZONE_MAPPING: [DiskZone; 16] = [ + zone!(0, 232, 158, 0), + zone!(0, 216, 158, 158), + zone!(0, 208, 149, 316), + zone!(0, 192, 149, 465), + zone!(0, 176, 149, 614), + zone!(0, 160, 149, 763), + zone!(0, 144, 149, 912), + zone!(0, 128, 114, 1061), + zone!(1, 216, 158, 0), + zone!(1, 208, 158, 158), + zone!(1, 192, 149, 316), + zone!(1, 176, 149, 465), + zone!(1, 160, 149, 614), + zone!(1, 144, 149, 763), + zone!(1, 128, 149, 912), + zone!(1, 112, 114, 1061), +]; + +const VZONE_TO_PZONE: [[usize; 16]; 7] = [ + [0, 1, 2, 9, 8, 3, 4, 5, 6, 7, 15, 14, 13, 12, 11, 10], + [0, 1, 2, 3, 10, 9, 8, 4, 5, 6, 7, 15, 14, 13, 12, 11], + [0, 1, 2, 3, 4, 11, 10, 9, 8, 5, 6, 7, 15, 14, 13, 12], + [0, 1, 2, 3, 4, 5, 12, 11, 10, 9, 8, 6, 7, 15, 14, 13], + [0, 1, 2, 3, 4, 5, 6, 13, 12, 11, 10, 9, 8, 7, 15, 14], + [0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8, 15], + [0, 1, 2, 3, 4, 5, 6, 7, 15, 14, 13, 12, 11, 10, 9, 8], +]; + +const ROM_ZONES: [usize; 7] = [5, 7, 9, 11, 13, 15, 16]; + +struct Mapping { + lba: usize, + offset: usize, + length: usize, + writable: bool, +} + +pub struct Disk { + file: File, + format: Format, + mapping: HashMap, +} + +impl Disk { + pub fn get_format(&self) -> &Format { + &self.format + } + + pub fn get_lba(&self, track: u32, head: u32, block: u32) -> Option { + if head == 0 && track < 12 { + return Some((track << 1 | block ^ (track % 2)) as usize); + } + let location = track << 2 | head << 1 | block; + self.mapping + .get(&(location as usize)) + .map(|block| block.lba) + } + + pub fn read_block( + &mut self, + track: u32, + head: u32, + block: u32, + ) -> Result>, Error> { + let location = track << 2 | head << 1 | block; + if let Some(block) = self.mapping.get(&(location as usize)) { + let mut data = vec![0u8; block.length]; + self.file.seek(SeekFrom::Start(block.offset as u64))?; + self.file.read_exact(&mut data)?; + return Ok(Some(data)); + } + Ok(None) + } + + pub fn write_block( + &mut self, + track: u32, + head: u32, + block: u32, + data: &[u8], + ) -> Result, Error> { + let location = track << 2 | head << 1 | block; + if let Some(block) = self.mapping.get(&(location as usize)) { + if block.length == data.len() && block.writable { + self.file.seek(SeekFrom::Start(block.offset as u64))?; + self.file.write_all(data)?; + return Ok(Some(())); + } + } + Ok(None) + } +} + +pub fn open(path: &str) -> Result { + let mut file = File::options().read(true).write(true).open(path)?; + let (format, mapping) = load_ndd(&mut file)?; + Ok(Disk { + file, + format, + mapping, + }) +} + +pub fn open_multiple(paths: &[String]) -> Result, Error> { + let mut disks: Vec = Vec::new(); + for path in paths { + let disk = open(path)?; + disks.push(disk); + } + if !disks.windows(2).all(|d| d[0].format == d[1].format) { + return Err(Error::new("Disk format mismatch")); + } + Ok(disks) +} + +fn load_ndd(file: &mut File) -> Result<(Format, HashMap), Error> { + let mut disk_format: Option = None; + let mut disk_type: usize = 0; + let mut sys_data = vec![0u8; SYSTEM_SECTOR_LENGTH]; + let mut bad_lbas: Vec = Vec::new(); + + for info in SYSTEM_AREA { + bad_lbas.clear(); + for &lba in info.sys_lba { + let data = load_sys_lba(file, lba)?; + if verify_sys_lba(&data, info.sector_length) { + if (data[4] != 0x10) || ((data[5] & 0xF0) != 0x10) { + bad_lbas.push(lba); + } else { + disk_format = Some(info.format); + disk_type = (data[5] & 0x0F) as usize; + sys_data = data[0..SYSTEM_SECTOR_LENGTH].to_vec(); + } + } else { + bad_lbas.push(lba); + } + } + if disk_format.is_some() { + bad_lbas.append(&mut info.bad_lba.to_vec()); + break; + } + } + if disk_format.is_none() { + return Err(Error::new("Provided 64DD disk file is not valid")); + } + if disk_type >= VZONE_TO_PZONE.len() { + return Err(Error::new("Unknown disk type")); + } + + let mut id_lba_valid = false; + for lba in ID_LBAS { + let data = load_sys_lba(file, lba)?; + let valid = verify_sys_lba(&data, SYSTEM_SECTOR_LENGTH); + if !valid { + bad_lbas.push(lba); + } + id_lba_valid |= valid; + } + if !id_lba_valid { + return Err(Error::new("No valid ID LBA found")); + } + + let mut zone_bad_tracks: Vec> = Vec::new(); + + for (zone, info) in ZONE_MAPPING.iter().enumerate() { + let mut bad_tracks: Vec = Vec::new(); + let start = if zone == 0 { 0 } else { sys_data[0x07 + zone] }; + let stop = sys_data[0x07 + zone + 1]; + for offset in start..stop { + bad_tracks.push(sys_data[0x20 + offset as usize] as usize); + } + for track in 0..(BAD_TRACKS_PER_ZONE - bad_tracks.len()) { + bad_tracks.push(info.tracks - track - 1); + } + zone_bad_tracks.push(bad_tracks); + } + + let mut mapping = HashMap::new(); + + let mut lba: usize = 0; + let mut offset: usize = 0; + let mut starting_block: usize = 0; + + for (vzone, &pzone) in VZONE_TO_PZONE[disk_type].iter().enumerate() { + let DiskZone { + head, + sector_length, + tracks, + track_offset, + } = ZONE_MAPPING[pzone]; + + let zone_tracks: Box> = if head == 0 { + Box::new(0..tracks) + } else { + Box::new((0..tracks).rev()) + }; + + for zone_track in zone_tracks { + if !zone_bad_tracks[pzone].contains(&zone_track) { + for block in 0..BLOCKS_PER_TRACK { + let track = track_offset + zone_track; + let location = (track << 2) | (head << 1) | (starting_block ^ block); + let length = sector_length * SECTORS_PER_BLOCK; + if !bad_lbas.contains(&lba) { + let writable = vzone >= ROM_ZONES[disk_type]; + mapping.insert( + location, + Mapping { + lba, + offset, + length, + writable, + }, + ); + } + lba += 1; + offset += length; + } + starting_block ^= 1; + } + } + } + + Ok((disk_format.unwrap(), mapping)) +} + +fn load_sys_lba(file: &mut File, lba: usize) -> Result, Error> { + let length = SYSTEM_SECTOR_LENGTH * SECTORS_PER_BLOCK; + file.seek(SeekFrom::Start((lba * length) as u64))?; + let mut data = vec![0u8; length]; + file.read_exact(&mut data)?; + Ok(data) +} + +fn verify_sys_lba(data: &[u8], sector_length: usize) -> bool { + let sys_data = &data[0..sector_length]; + for sector in 1..SECTORS_PER_BLOCK { + let offset = sector * sector_length; + let verify_data = &data[offset..(offset + sector_length)]; + if sys_data != verify_data { + return false; + } + } + true +} diff --git a/sw/deployer/src/main.rs b/sw/deployer/src/main.rs new file mode 100644 index 0000000..a1c7aff --- /dev/null +++ b/sw/deployer/src/main.rs @@ -0,0 +1,841 @@ +mod debug; +mod disk; +mod n64; +mod sc64; + +use chrono::Local; +use clap::{Args, Parser, Subcommand, ValueEnum}; +use clap_num::maybe_hex_range; +use colored::Colorize; +use panic_message::panic_message; +use std::{ + fs::File, + io::{stdin, stdout, Read, Write}, + path::PathBuf, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, + time::Duration, + {panic, process, thread}, +}; + +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +struct Cli { + #[command(subcommand)] + command: Commands, + + /// Connect to SC64 device on provided serial port + #[arg(short, long)] + port: Option, + + /// Connect to SC64 device on provided remote address + #[arg(short, long, conflicts_with = "port")] + remote: Option, +} + +#[derive(Subcommand)] +enum Commands { + /// List connected SC64 devices + List, + + /// Upload ROM (and save) to the SC64 + Upload(UploadArgs), + + /// Download specific memory region and write it to file + Download { + #[command(subcommand)] + command: DownloadCommands, + }, + + /// Upload ROM (and save), 64DD IPL then run disk server + _64DD(_64DDArgs), + + /// Enter debug mode + Debug(DebugArgs), + + /// Dump data from arbitrary location in SC64 memory space + Dump(DumpArgs), + + /// Print information about connected SC64 device + Info, + + /// Update persistent settings on SC64 device + Set { + #[command(subcommand)] + command: SetCommands, + }, + + /// Print firmware metadata / update or backup SC64 firmware + Firmware { + #[command(subcommand)] + command: FirmwareCommands, + }, + + /// Expose SC64 device over network + Server(ServerArgs), +} + +#[derive(Args)] +struct UploadArgs { + /// Path to the ROM file + rom: PathBuf, + + /// Path to the save file + #[arg(short, long)] + save: Option, + + /// Override autodetected save type + #[arg(short = 't', long)] + save_type: Option, + + /// Use direct boot mode (skip bootloader) + #[arg(short, long)] + direct: bool, + + /// Do not put last 128 kiB of ROM inside flash memory (can corrupt non EEPROM saves) + #[arg(short, long)] + no_shadow: bool, + + /// Force TV type + #[arg(long, conflicts_with = "direct")] + tv: Option, +} + +#[derive(Subcommand)] +enum DownloadCommands { + /// Download save and write it to file + Save(DownloadArgs), +} + +#[derive(Args)] +struct DownloadArgs { + /// Path to the file + path: PathBuf, +} + +#[derive(Args)] +struct _64DDArgs { + /// Path to the 64DD IPL file + ddipl: PathBuf, + + /// Path to the 64DD disk file (.ndd format, can be specified multiple times) + #[arg(required = true)] + disk: Vec, + + /// Path to the ROM file + #[arg(short, long)] + rom: Option, + + /// Path to the save file + #[arg(short, long, requires = "rom")] + save: Option, + + /// Override autodetected save type + #[arg(short = 't', long, requires = "rom")] + save_type: Option, + + /// Use direct boot mode (skip bootloader) + #[arg(short, long)] + direct: bool, + + /// Force TV type + #[arg(long, conflicts_with = "direct")] + tv: Option, +} + +#[derive(Args)] +struct DebugArgs { + /// Enable IS-Viewer64 and set listening address at ROM offset (in most cases it's fixed at 0x03FF0000) + #[arg(long, value_name = "offset", value_parser = |s: &str| maybe_hex_range::(s, 0x00000004, 0x03FF0000))] + isv: Option, + + /// Expose TCP socket port for GDB debugging + #[arg(long, value_name = "port", value_parser = clap::value_parser!(u16).range(1..))] + gdb: Option, +} + +#[derive(Args)] +struct DumpArgs { + /// Starting memory address + #[arg(value_parser = |s: &str| maybe_hex_range::(s, 0, sc64::MEMORY_LENGTH as u32))] + address: u32, + + /// Dump length + #[arg(value_parser = |s: &str| maybe_hex_range::(s, 1, sc64::MEMORY_LENGTH))] + length: usize, + + /// Path to the dump file + path: PathBuf, +} + +#[derive(Subcommand)] +enum SetCommands { + /// Synchronize real time clock (RTC) on the SC64 with local system time + Rtc, + + /// Enable LED I/O activity blinking + BlinkOn, + + /// Disable LED I/O activity blinking + BlinkOff, +} + +#[derive(Subcommand)] +enum FirmwareCommands { + /// Print metadata included inside SC64 firmware file + Info(FirmwareArgs), + + /// Download current SC64 firmware and save it to provided file + Backup(FirmwareArgs), + + /// Update SC64 firmware from provided file + Update(FirmwareArgs), +} + +#[derive(Args)] +struct FirmwareArgs { + /// Path to the firmware file + firmware: PathBuf, +} + +#[derive(Args)] +struct ServerArgs { + /// Listen on provided address:port + #[arg(default_value = "127.0.0.1:9064")] + address: String, +} + +#[derive(Clone, ValueEnum)] +enum SaveType { + None, + Eeprom4k, + Eeprom16k, + Sram, + SramBanked, + Flashram, +} + +impl From for SaveType { + fn from(value: n64::SaveType) -> Self { + match value { + n64::SaveType::None => Self::None, + n64::SaveType::Eeprom4k => Self::Eeprom4k, + n64::SaveType::Eeprom16k => Self::Eeprom16k, + n64::SaveType::Sram => Self::Sram, + n64::SaveType::SramBanked => Self::SramBanked, + n64::SaveType::Flashram => Self::Flashram, + n64::SaveType::Sram128kB => Self::Sram, + } + } +} + +impl From for sc64::SaveType { + fn from(value: SaveType) -> Self { + match value { + SaveType::None => Self::None, + SaveType::Eeprom4k => Self::Eeprom4k, + SaveType::Eeprom16k => Self::Eeprom16k, + SaveType::Sram => Self::Sram, + SaveType::SramBanked => Self::SramBanked, + SaveType::Flashram => Self::Flashram, + } + } +} + +#[derive(Clone, ValueEnum)] +enum TvType { + PAL, + NTSC, + MPAL, +} + +impl From for sc64::TvType { + fn from(value: TvType) -> Self { + match value { + TvType::PAL => Self::PAL, + TvType::NTSC => Self::NTSC, + TvType::MPAL => Self::MPAL, + } + } +} + +enum Connection { + Local(Option), + Remote(String), +} + +fn main() { + let cli = Cli::parse(); + + #[cfg(not(debug_assertions))] + { + panic::set_hook(Box::new(|_| {})); + } + + match panic::catch_unwind(|| handle_command(&cli.command, cli.port, cli.remote)) { + Ok(_) => {} + Err(payload) => { + eprintln!("{}", panic_message(&payload).red()); + process::exit(1); + } + } +} + +fn handle_command(command: &Commands, port: Option, remote: Option) { + let connection = if let Some(remote) = remote { + Connection::Remote(remote) + } else { + Connection::Local(port) + }; + let result = match command { + Commands::List => handle_list_command(), + Commands::Upload(args) => handle_upload_command(connection, args), + Commands::Download { command } => handle_download_command(connection, command), + Commands::_64DD(args) => handle_64dd_command(connection, args), + Commands::Debug(args) => handle_debug_command(connection, args), + Commands::Dump(args) => handle_dump_command(connection, args), + Commands::Info => handle_info_command(connection), + Commands::Set { command } => handle_set_command(connection, command), + Commands::Firmware { command } => handle_firmware_command(connection, command), + Commands::Server(args) => handle_server_command(connection, args), + }; + match result { + Ok(()) => {} + Err(error) => panic!("{error}"), + }; +} + +fn handle_list_command() -> Result<(), sc64::Error> { + let devices = sc64::list_local_devices()?; + + println!("{}", "Found devices:".bold()); + for (i, d) in devices.iter().enumerate() { + println!(" {i}: [{}] at port [{}]", d.serial_number, d.port); + } + + Ok(()) +} + +fn handle_upload_command(connection: Connection, args: &UploadArgs) -> Result<(), sc64::Error> { + let mut sc64 = init_sc64(connection, true)?; + + sc64.reset_state()?; + + let (mut rom_file, rom_name, rom_length) = open_file(&args.rom)?; + + log_wait(format!("Uploading ROM [{rom_name}]"), || { + sc64.upload_rom(&mut rom_file, rom_length, args.no_shadow) + })?; + + let save: SaveType = if let Some(save_type) = args.save_type.clone() { + save_type + } else { + let (save_type, title) = n64::guess_save_type(&mut rom_file)?; + if let Some(title) = title { + println!("ROM title: {title}"); + }; + save_type.into() + }; + let save_type: sc64::SaveType = save.into(); + println!("Save type set to [{save_type}]"); + sc64.set_save_type(save_type)?; + + if args.save.is_some() { + let (mut save_file, save_name, save_length) = open_file(&args.save.as_ref().unwrap())?; + + log_wait(format!("Uploading save [{save_name}]"), || { + sc64.upload_save(&mut save_file, save_length) + })?; + } + + let boot_mode = if args.direct { + sc64::BootMode::DirectRom + } else { + sc64::BootMode::Rom + }; + println!("Boot mode set to [{boot_mode}]"); + sc64.set_boot_mode(boot_mode)?; + + if let Some(tv) = args.tv.clone() { + let tv_type: sc64::TvType = tv.into(); + println!("TV type set to [{tv_type}]"); + sc64.set_tv_type(tv_type)?; + } + + sc64.calculate_cic_parameters()?; + + Ok(()) +} + +fn handle_download_command( + connection: Connection, + command: &DownloadCommands, +) -> Result<(), sc64::Error> { + let mut sc64 = init_sc64(connection, true)?; + + match command { + DownloadCommands::Save(args) => { + let (mut file, name) = create_file(&args.path)?; + + log_wait(format!("Downloading save [{name}]"), || { + sc64.download_save(&mut file) + })?; + } + } + + Ok(()) +} + +fn handle_64dd_command(connection: Connection, args: &_64DDArgs) -> Result<(), sc64::Error> { + const MAX_ROM_LENGTH: usize = 32 * 1024 * 1024; + + let mut sc64 = init_sc64(connection, true)?; + + println!( + "{} {} {}", + "[WARNING]:".bold().bright_yellow(), + "Do not use this mode when real 64DD accessory is connected to the N64.".bright_yellow(), + "This might permanently damage either 64DD or SC64.".bright_yellow() + ); + + sc64.reset_state()?; + + if let Some(rom) = &args.rom { + let (mut rom_file, rom_name, rom_length) = open_file(rom)?; + if rom_length > MAX_ROM_LENGTH { + return Err(sc64::Error::new("ROM file size too big for 64DD mode")); + } + log_wait(format!("Uploading ROM [{rom_name}]"), || { + sc64.upload_rom(&mut rom_file, rom_length, false) + })?; + + let save: SaveType = if let Some(save_type) = args.save_type.clone() { + save_type + } else { + let (save_type, title) = n64::guess_save_type(&mut rom_file)?; + if let Some(title) = title { + println!("ROM title: {title}"); + }; + save_type.into() + }; + let save_type: sc64::SaveType = save.into(); + println!("Save type set to [{save_type}]"); + sc64.set_save_type(save_type)?; + + if args.save.is_some() { + let (mut save_file, save_name, save_length) = open_file(&args.save.as_ref().unwrap())?; + + log_wait(format!("Uploading save [{save_name}]"), || { + sc64.upload_save(&mut save_file, save_length) + })?; + } + } + + let (mut ddipl_file, ddipl_name, ddipl_length) = open_file(&args.ddipl)?; + + log_wait(format!("Uploading DDIPL [{ddipl_name}]"), || { + sc64.upload_ddipl(&mut ddipl_file, ddipl_length) + })?; + + let boot_mode = if args.rom.is_some() { + if args.direct { + sc64::BootMode::DirectRom + } else { + sc64::BootMode::Rom + } + } else { + if args.direct { + sc64::BootMode::DirectDdIpl + } else { + sc64::BootMode::DdIpl + } + }; + println!("Boot mode set to [{boot_mode}]"); + sc64.set_boot_mode(boot_mode)?; + + if let Some(tv) = args.tv.clone() { + let tv_type: sc64::TvType = tv.into(); + println!("TV type set to [{tv_type}]"); + sc64.set_tv_type(tv_type)?; + } + + sc64.calculate_cic_parameters()?; + + let disk_paths: Vec = args + .disk + .iter() + .map(|path| path.to_string_lossy().to_string()) + .collect(); + let disk_names: Vec = args + .disk + .iter() + .map(|path| path.file_name().unwrap().to_string_lossy().to_string()) + .collect(); + + let mut disks = disk::open_multiple(&disk_paths)?; + let mut selected_disk_index: usize = 0; + let mut selected_disk: Option<&mut disk::Disk> = None; + + let drive_type = match disks[0].get_format() { + disk::Format::Retail => sc64::DdDriveType::Retail, + disk::Format::Development => sc64::DdDriveType::Development, + }; + + sc64.configure_64dd(sc64::DdMode::Full, drive_type)?; + + println!( + "{}", + "Press button on the SC64 device to cycle through provided disks".bold() + ); + + let exit = setup_exit_flag(); + while !exit.load(Ordering::Relaxed) { + if let Some(data_packet) = sc64.receive_data_packet()? { + match data_packet { + sc64::DataPacket::Disk(mut packet) => { + let track = packet.info.track; + let head = packet.info.head; + let block = packet.info.block; + if let Some(ref mut disk) = selected_disk { + let reply_packet = match packet.kind { + sc64::DiskPacketKind::Read => { + print!("{}", "[R]".cyan()); + disk.read_block(track, head, block)?.map(|data| { + packet.info.set_data(&data); + packet + }) + } + sc64::DiskPacketKind::Write => { + print!("{}", "[W]".yellow()); + let data = &packet.info.data; + disk.write_block(track, head, block, data)?.map(|_| packet) + } + }; + let lba = if let Some(lba) = disk.get_lba(track, head, block) { + format!("{lba}") + } else { + "Invalid".to_string() + }; + let message = format!(" {track:4}:{head}:{block} / LBA: {lba}"); + if reply_packet.is_some() { + println!("{}", message.green()); + } else { + println!("{}", message.red()); + } + sc64.reply_disk_packet(reply_packet)?; + } else { + sc64.reply_disk_packet(None)?; + } + } + sc64::DataPacket::Button => { + if selected_disk.is_some() { + sc64.set_64dd_disk_state(sc64::DdDiskState::Ejected)?; + selected_disk = None; + println!("64DD disk ejected [{}]", disk_names[selected_disk_index]); + } else { + selected_disk_index += 1; + if selected_disk_index >= disks.len() { + selected_disk_index = 0; + } + selected_disk = Some(&mut disks[selected_disk_index]); + sc64.set_64dd_disk_state(sc64::DdDiskState::Inserted)?; + println!("64DD disk inserted [{}]", disk_names[selected_disk_index]); + } + } + _ => {} + } + } else { + thread::sleep(Duration::from_millis(1)); + } + } + + Ok(()) +} + +fn handle_debug_command(connection: Connection, args: &DebugArgs) -> Result<(), sc64::Error> { + let mut sc64 = init_sc64(connection, true)?; + + let mut debug_handler = debug::new(args.gdb)?; + if let Some(port) = args.gdb { + println!("GDB TCP socket listening at [0.0.0.0:{port}]"); + } + + if args.isv.is_some() { + sc64.configure_is_viewer_64(args.isv)?; + println!( + "IS-Viewer 64 configured and listening at ROM offset [0x{:08X}]", + args.isv.unwrap() + ); + } + + println!("{}", "Debug mode started".bold()); + + let exit = setup_exit_flag(); + while !exit.load(Ordering::Relaxed) { + if let Some(data_packet) = sc64.receive_data_packet()? { + match data_packet { + sc64::DataPacket::IsViewer(message) => { + print!("{message}") + } + sc64::DataPacket::Debug(debug_packet) => { + debug_handler.handle_debug_packet(debug_packet) + } + _ => {} + } + } else if let Some(gdb_packet) = debug_handler.receive_gdb_packet() { + sc64.send_debug_packet(gdb_packet)?; + } else if let Some(debug_packet) = debug_handler.process_user_input() { + sc64.send_debug_packet(debug_packet)?; + } else { + thread::sleep(Duration::from_millis(1)); + } + } + + println!("{}", "Debug mode ended".bold()); + + if args.isv.is_some() { + sc64.configure_is_viewer_64(None)?; + } + + Ok(()) +} + +fn handle_dump_command(connection: Connection, args: &DumpArgs) -> Result<(), sc64::Error> { + let mut sc64 = init_sc64(connection, true)?; + + let (mut dump_file, dump_name) = create_file(&args.path)?; + + log_wait( + format!( + "Dumping from [0x{:08X}] length [0x{:X}] to [{dump_name}]", + args.address, args.length + ), + || sc64.dump_memory(&mut dump_file, args.address, args.length), + )?; + + Ok(()) +} + +fn handle_info_command(connection: Connection) -> Result<(), sc64::Error> { + let mut sc64 = init_sc64(connection, true)?; + + let (major, minor, revision) = sc64.check_firmware_version()?; + let state = sc64.get_device_state()?; + let datetime = state.datetime.format("%Y-%m-%d %H:%M:%S %Z"); + + println!("{}", "SC64 information and current state:".bold()); + println!(" Firmware version: v{}.{}.{}", major, minor, revision); + println!(" RTC datetime: {}", datetime); + println!(" Boot mode: {}", state.boot_mode); + println!(" Save type: {}", state.save_type); + println!(" CIC seed: {}", state.cic_seed); + println!(" TV type: {}", state.tv_type); + println!(" Bootloader switch: {}", state.bootloader_switch); + println!(" ROM write: {}", state.rom_write_enable); + println!(" ROM shadow: {}", state.rom_shadow_enable); + println!(" ROM extended: {}", state.rom_extended_enable); + println!(" IS-Viewer 64 offset: 0x{:08X}", state.isv_address); + println!(" 64DD mode: {}", state.dd_mode); + println!(" 64DD SD card mode: {}", state.dd_sd_enable); + println!(" 64DD drive type: {}", state.dd_drive_type); + println!(" 64DD disk state: {}", state.dd_disk_state); + println!(" Button mode: {}", state.button_mode); + println!(" Button state: {}", state.button_state); + println!(" LED blink: {}", state.led_enable); + println!(" FPGA debug data: {}", state.fpga_debug_data); + println!(" MCU stack usage: {}", state.mcu_stack_usage); + + Ok(()) +} + +fn handle_set_command(connection: Connection, command: &SetCommands) -> Result<(), sc64::Error> { + let mut sc64 = init_sc64(connection, true)?; + + match command { + SetCommands::Rtc => { + let datetime = Local::now(); + sc64.set_datetime(datetime)?; + println!( + "SC64 RTC datetime synchronized to: {}", + datetime.format("%Y-%m-%d %H:%M:%S %Z").to_string().green() + ); + } + + SetCommands::BlinkOn => { + sc64.set_led_blink(true)?; + println!( + "SC64 LED I/O activity blinking set to {}", + "enabled".green() + ); + } + + SetCommands::BlinkOff => { + sc64.set_led_blink(false)?; + println!("SC64 LED I/O activity blinking set to {}", "disabled".red()); + } + } + + Ok(()) +} + +fn handle_firmware_command( + connection: Connection, + command: &FirmwareCommands, +) -> Result<(), sc64::Error> { + match command { + FirmwareCommands::Info(args) => { + let (mut firmware_file, _, firmware_length) = open_file(&args.firmware)?; + + let mut firmware = vec![0u8; firmware_length as usize]; + firmware_file.read_exact(&mut firmware)?; + + let metadata = sc64::firmware::verify(&firmware)?; + println!("{}", "Firmware metadata:".bold()); + println!("{}", format!("{}", metadata).cyan().to_string()); + + Ok(()) + } + + FirmwareCommands::Backup(args) => { + let mut sc64 = init_sc64(connection, false)?; + + let (mut backup_file, backup_name) = create_file(&args.firmware)?; + + sc64.reset_state()?; + + let firmware = log_wait( + format!("Generating firmware backup, this might take a while [{backup_name}]"), + || sc64.backup_firmware(), + )?; + + let metadata = sc64::firmware::verify(&firmware)?; + println!("{}", "Firmware metadata:".bold()); + println!("{}", format!("{}", metadata).cyan().to_string()); + + backup_file.write_all(&firmware)?; + + Ok(()) + } + + FirmwareCommands::Update(args) => { + let mut sc64 = init_sc64(connection, false)?; + + let (mut update_file, update_name, update_length) = open_file(&args.firmware)?; + + let mut firmware = vec![0u8; update_length as usize]; + update_file.read_exact(&mut firmware)?; + + let metadata = sc64::firmware::verify(&firmware)?; + println!("{}", "Firmware metadata:".bold()); + println!("{}", format!("{}", metadata).cyan().to_string()); + println!("{}", "Firmware file verification was successful".green()); + let answer = prompt(format!("{}", "Continue with update process? [y/N] ".bold())); + if answer.to_ascii_lowercase() != "y" { + println!("{}", "Firmware update process aborted".red()); + return Ok(()); + } + println!( + "{}", + "Do not unplug SC64 from the computer, doing so might brick your device".yellow() + ); + + sc64.reset_state()?; + + log_wait( + format!("Updating firmware, this might take a while [{update_name}]"), + || sc64.update_firmware(&firmware), + )?; + + Ok(()) + } + } +} + +fn handle_server_command(connection: Connection, args: &ServerArgs) -> Result<(), sc64::Error> { + let port = if let Connection::Local(port) = connection { + port + } else { + None + }; + + sc64::run_server(port, args.address.clone(), |event| match event { + sc64::ServerEvent::Listening(address) => { + println!("{}: Listening on address [{}]", "[Server]".bold(), address) + } + sc64::ServerEvent::Connection(peer) => { + println!("{}: New connection from [{}]", "[Server]".bold(), peer); + } + sc64::ServerEvent::Disconnected(peer) => { + println!("{}: Client disconnected [{}]", "[Server]".bold(), peer); + } + sc64::ServerEvent::Err(error) => { + println!( + "{}: Client disconnected with error: {}", + "[Server]".bold(), + error + ); + } + })?; + + Ok(()) +} + +fn init_sc64(connection: Connection, check_firmware: bool) -> Result { + let mut sc64 = match connection { + Connection::Local(port) => sc64::new_local(port), + Connection::Remote(remote) => sc64::new_remote(remote), + }?; + + if check_firmware { + sc64.check_firmware_version()?; + } + + Ok(sc64) +} + +fn log_wait Result, T, E>(message: String, operation: F) -> Result { + print!("{}... ", message); + stdout().flush().unwrap(); + let result = operation(); + if result.is_ok() { + println!("done"); + } else { + println!("error!"); + } + result +} + +fn prompt(message: String) -> String { + print!("{message}"); + stdout().flush().unwrap(); + let mut answer = String::new(); + stdin().read_line(&mut answer).unwrap(); + answer.trim_end().to_string() +} + +fn open_file(path: &PathBuf) -> Result<(File, String, usize), sc64::Error> { + let name: String = path.file_name().unwrap().to_string_lossy().to_string(); + let file = File::open(path)?; + let length = file.metadata()?.len() as usize; + Ok((file, name, length)) +} + +fn create_file(path: &PathBuf) -> Result<(File, String), sc64::Error> { + let name: String = path.file_name().unwrap().to_string_lossy().to_string(); + let file = File::create(path)?; + Ok((file, name)) +} + +fn setup_exit_flag() -> Arc { + let exit_flag = Arc::new(AtomicBool::new(false)); + let handler_exit_flag = exit_flag.clone(); + + ctrlc::set_handler(move || { + handler_exit_flag.store(true, Ordering::Relaxed); + }) + .unwrap(); + + exit_flag +} diff --git a/sw/deployer/src/n64.rs b/sw/deployer/src/n64.rs new file mode 100644 index 0000000..63537a6 --- /dev/null +++ b/sw/deployer/src/n64.rs @@ -0,0 +1,88 @@ +use include_flate::flate; +use std::io::{Error, Read, Seek, SeekFrom}; + +flate!(static MUPEN64PLUS_INI: str from "data/mupen64plus.ini"); + +pub enum SaveType { + None, + Eeprom4k, + Eeprom16k, + Sram, + SramBanked, + Flashram, + Sram128kB, +} + +const HASH_CHUNK_LENGTH: usize = 1 * 1024 * 1024; + +pub fn guess_save_type( + reader: &mut T, +) -> Result<(SaveType, Option), Error> { + let mut ed64_header = vec![0u8; 4]; + + reader.seek(SeekFrom::Start(0x3C))?; + reader.read_exact(&mut ed64_header)?; + + if &ed64_header[0..2] == b"ED" { + return Ok(( + match ed64_header[3] >> 4 { + 1 => SaveType::Eeprom4k, + 2 => SaveType::Eeprom16k, + 3 => SaveType::Sram, + 4 => SaveType::SramBanked, + 5 => SaveType::Flashram, + 6 => SaveType::Sram128kB, + _ => SaveType::None, + }, + None, + )); + } + + let mut pi_config = vec![0u8; 4]; + + reader.rewind()?; + reader.read_exact(&mut pi_config)?; + + let endian_swapper = match &pi_config[0..4] { + [0x37, 0x80, 0x40, 0x12] => |b: &mut [u8]| b.chunks_exact_mut(2).for_each(|c| c.swap(0, 1)), + [0x40, 0x12, 0x37, 0x80] => |b: &mut [u8]| { + b.chunks_exact_mut(4).for_each(|c| { + c.swap(0, 3); + c.swap(1, 2) + }) + }, + _ => |_: &mut [u8]| {}, + }; + + let mut hasher = md5::Context::new(); + let mut buffer = vec![0u8; HASH_CHUNK_LENGTH]; + + reader.rewind()?; + loop { + let chunk = reader.read(&mut buffer)?; + if chunk > 0 { + endian_swapper(&mut buffer[0..chunk]); + hasher.consume(&buffer[0..chunk]); + } else { + break; + } + } + + let hash = hex::encode_upper(hasher.compute().0); + + let database = ini::Ini::load_from_str(MUPEN64PLUS_INI.as_str()) + .expect("Error during mupen64plus.ini parse operation"); + if let Some(section) = database.section(Some(hash)) { + let save_type = section.get("SaveType").map_or(SaveType::None, |t| match t { + "Eeprom 4KB" => SaveType::Eeprom4k, + "Eeprom 16KB" => SaveType::Eeprom16k, + "SRAM" => SaveType::Sram, + "Flash RAM" => SaveType::Flashram, + _ => SaveType::None, + }); + let title = section.get("GoodName").map(|s| s.to_string()); + return Ok((save_type, title)); + } + + Ok((SaveType::None, None)) +} diff --git a/sw/deployer/src/sc64/cic.rs b/sw/deployer/src/sc64/cic.rs new file mode 100644 index 0000000..abebd68 --- /dev/null +++ b/sw/deployer/src/sc64/cic.rs @@ -0,0 +1,220 @@ +use super::Error; + +pub const IPL3_OFFSET: u32 = 0x40; +pub const IPL3_LENGTH: usize = 0xFC0; + +enum CicType { + _5101, + _6101, + _7102, + X102, + X103, + X105, + X106, + _5167, + NDXJ0, + NDDJ0, + NDDJ1, + NDDJ2, + NDDE0, +} + +impl From for CicType { + fn from(value: u32) -> Self { + match value { + 0x587BD543 => CicType::_5101, + 0x6170A4A1 => CicType::_6101, + 0x009E9EA3 => CicType::_7102, + 0x90BB6CB5 => CicType::X102, + 0x0B050EE0 => CicType::X103, + 0x98BC2C86 => CicType::X105, + 0xACC8580A => CicType::X106, + 0x0E018159 => CicType::_5167, + 0x10C68B18 => CicType::NDXJ0, + 0xBC605D0A => CicType::NDDJ0, + 0x502C4466 => CicType::NDDJ1, + 0x0C965795 => CicType::NDDJ2, + 0x8FEBA21E => CicType::NDDE0, + _ => CicType::X102, + } + } +} + +impl From for u8 { + fn from(value: CicType) -> Self { + match value { + CicType::_5101 => 0xAC, + CicType::_6101 => 0x3F, + CicType::_7102 => 0x3F, + CicType::X102 => 0x3F, + CicType::X103 => 0x78, + CicType::X105 => 0x91, + CicType::X106 => 0x85, + CicType::_5167 => 0xDD, + CicType::NDXJ0 => 0xDD, + CicType::NDDJ0 => 0xDD, + CicType::NDDJ1 => 0xDD, + CicType::NDDJ2 => 0xDD, + CicType::NDDE0 => 0xDE, + } + } +} + +pub fn guess_ipl3_seed(ipl3: &[u8]) -> Result { + if ipl3.len() < IPL3_LENGTH { + return Err(Error::new("Invalid IPL3 length provided")); + } + + let cic_type: CicType = crc32fast::hash(ipl3).into(); + + Ok(cic_type.into()) +} + +pub fn calculate_ipl3_checksum(ipl3: &[u8], seed: u8) -> Result<[u8; 6], Error> { + if ipl3.len() < IPL3_LENGTH { + return Err(Error::new("Invalid IPL3 length provided")); + } + + const MAGIC: u32 = 0x6C078965; + + let get = |offset: u32| { + let o: usize = offset as usize * 4; + return ((ipl3[o] as u32) << 24) + | ((ipl3[o + 1] as u32) << 16) + | ((ipl3[o + 2] as u32) << 8) + | (ipl3[o + 3] as u32); + }; + let add = |a1: u32, a2: u32| u32::wrapping_add(a1, a2); + let sub = |a1: u32, a2: u32| u32::wrapping_sub(a1, a2); + let mul = |a1: u32, a2: u32| u32::wrapping_mul(a1, a2); + let lsh = |a: u32, s: u32| if s >= 32 { 0 } else { u32::wrapping_shl(a, s) }; + let rsh = |a: u32, s: u32| if s >= 32 { 0 } else { u32::wrapping_shr(a, s) }; + let checksum = |a0: u32, a1: u32, a2: u32| { + let prod = (a0 as u64).wrapping_mul(if a1 == 0 { a2 as u64 } else { a1 as u64 }); + let hi = ((prod >> 32) & 0xFFFFFFFF) as u32; + let lo = (prod & 0xFFFFFFFF) as u32; + let diff = hi.wrapping_sub(lo); + return if diff == 0 { a0 } else { diff }; + }; + + let init = add(mul(MAGIC, seed as u32), 1) ^ get(0); + + let mut buffer = vec![init; 16]; + + for i in 1..=1008 as u32 { + let data_prev = get(i.saturating_sub(2)); + let data_curr = get(i - 1); + + buffer[0] = add(buffer[0], checksum(sub(1007, i), data_curr, i)); + buffer[1] = checksum(buffer[1], data_curr, i); + buffer[2] = buffer[2] ^ data_curr; + buffer[3] = add(buffer[3], checksum(add(data_curr, 5), MAGIC, i)); + + let shift = data_prev & 0x1F; + let data_left = lsh(data_curr, 32 - shift); + let data_right = rsh(data_curr, shift); + let b4_shifted = data_left | data_right; + buffer[4] = add(buffer[4], b4_shifted); + + let shift = rsh(data_prev, 27); + let data_left = lsh(data_curr, shift); + let data_right = rsh(data_curr, 32 - shift); + let b5_shifted = data_left | data_right; + buffer[5] = add(buffer[5], b5_shifted); + + if data_curr < buffer[6] { + buffer[6] = add(buffer[3], buffer[6]) ^ add(data_curr, i); + } else { + buffer[6] = add(buffer[4], data_curr) ^ buffer[6]; + } + + let shift = data_prev & 0x1F; + let data_left = lsh(data_curr, shift); + let data_right = rsh(data_curr, 32 - shift); + buffer[7] = checksum(buffer[7], data_left | data_right, i); + + let shift = rsh(data_prev, 27); + let data_left = lsh(data_curr, 32 - shift); + let data_right = rsh(data_curr, shift); + buffer[8] = checksum(buffer[8], data_left | data_right, i); + + if data_prev < data_curr { + buffer[9] = checksum(buffer[9], data_curr, i) + } else { + buffer[9] = add(buffer[9], data_curr); + } + + if i == 1008 { + break; + } + + let data_next = get(i); + + buffer[10] = checksum(add(buffer[10], data_curr), data_next, i); + buffer[11] = checksum(buffer[11] ^ data_curr, data_next, i); + buffer[12] = add(buffer[12], buffer[8] ^ data_curr); + + let shift = data_curr & 0x1F; + let data_left = lsh(data_curr, 32 - shift); + let data_right = rsh(data_curr, shift); + let tmp = data_left | data_right; + let shift = data_next & 0x1F; + let data_left = lsh(data_next, 32 - shift); + let data_right = rsh(data_next, shift); + buffer[13] = add(buffer[13], add(tmp, data_left | data_right)); + + let shift = data_curr & 0x1F; + let data_left = lsh(data_next, 32 - shift); + let data_right = rsh(data_next, shift); + let sum = checksum(buffer[14], b4_shifted, i); + buffer[14] = checksum(sum, data_left | data_right, i); + + let shift = rsh(data_curr, 27); + let data_left = lsh(data_next, shift); + let data_right = rsh(data_next, 32 - shift); + let sum = checksum(buffer[15], b5_shifted, i); + buffer[15] = checksum(sum, data_left | data_right, i); + } + + let mut final_buffer = vec![buffer[0]; 4]; + + for i in 0..16 as u32 { + let data = buffer[i as usize]; + + let shift = data & 0x1F; + let data_left = lsh(data, 32 - shift); + let data_right = rsh(data, shift); + let b0_shifted = add(final_buffer[0], data_left | data_right); + final_buffer[0] = b0_shifted; + + if data < b0_shifted { + final_buffer[1] = add(final_buffer[1], data); + } else { + final_buffer[1] = checksum(final_buffer[1], data, i); + } + + if rsh(data & 0x02, 1) == (data & 0x01) { + final_buffer[2] = add(final_buffer[2], data); + } else { + final_buffer[2] = checksum(final_buffer[2], data, i); + } + + if (data & 0x01) == 0x01 { + final_buffer[3] = final_buffer[3] ^ data; + } else { + final_buffer[3] = checksum(final_buffer[3], data, i); + } + } + + let sum = checksum(final_buffer[0], final_buffer[1], 16); + let xor = final_buffer[3] ^ final_buffer[2]; + + Ok([ + (sum >> 8) as u8, + (sum >> 0) as u8, + (xor >> 24) as u8, + (xor >> 16) as u8, + (xor >> 8) as u8, + (xor >> 0) as u8, + ]) +} diff --git a/sw/deployer/src/sc64/error.rs b/sw/deployer/src/sc64/error.rs new file mode 100644 index 0000000..f96444f --- /dev/null +++ b/sw/deployer/src/sc64/error.rs @@ -0,0 +1,34 @@ +use std::fmt::{Display, Formatter, Result}; + +#[derive(Debug, Clone)] +pub struct Error { + description: String, +} + +impl Error { + pub fn new(description: &str) -> Self { + Error { + description: format!("{}", description), + } + } +} + +impl std::error::Error for Error {} + +impl Display for Error { + fn fmt(&self, f: &mut Formatter) -> Result { + write!(f, "SC64 error: {}", self.description.as_str()) + } +} + +impl From for Error { + fn from(value: std::io::Error) -> Self { + Error::new(format!("IO error: {}", value).as_str()) + } +} + +impl From for Error { + fn from(value: serialport::Error) -> Self { + Error::new(format!("SerialPort error: {}", value.description).as_str()) + } +} diff --git a/sw/deployer/src/sc64/firmware.rs b/sw/deployer/src/sc64/firmware.rs new file mode 100644 index 0000000..8c74526 --- /dev/null +++ b/sw/deployer/src/sc64/firmware.rs @@ -0,0 +1,149 @@ +use super::Error; +use std::{ + fmt::Display, + io::{Cursor, Read, Seek, SeekFrom}, +}; + +enum ChunkId { + UpdateInfo, + McuData, + FpgaData, + BootloaderData, + PrimerData, +} + +impl TryFrom for ChunkId { + type Error = Error; + fn try_from(value: u32) -> Result { + Ok(match value { + 1 => Self::UpdateInfo, + 2 => Self::McuData, + 3 => Self::FpgaData, + 4 => Self::BootloaderData, + 5 => Self::PrimerData, + _ => return Err(Error::new("Unknown chunk id inside firmware update file")), + }) + } +} + +impl Display for ChunkId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + ChunkId::UpdateInfo => "Update info", + ChunkId::McuData => "MCU data", + ChunkId::FpgaData => "FPGA data", + ChunkId::BootloaderData => "Bootloader data", + ChunkId::PrimerData => "Primer data", + }) + } +} + +pub struct Firmware { + update_info: Option, + mcu_data: Option>, + fpga_data: Option>, + bootloader_data: Option>, + primer_data: Option>, +} + +impl Display for Firmware { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if let Some(update_info) = &self.update_info { + f.write_fmt(format_args!("{}", &update_info))?; + } else { + f.write_str("No update info data included")?; + } + if let Some(data) = &self.mcu_data { + f.write_fmt(format_args!( + "\nMCU data present, length: 0x{:X}", + data.len() + ))?; + } else { + f.write_str("\nNo MCU data included")?; + } + if let Some(data) = &self.fpga_data { + f.write_fmt(format_args!( + "\nFPGA data present, length: 0x{:X}", + data.len() + ))?; + } else { + f.write_str("\nNo FPGA data included")?; + } + if let Some(data) = &self.bootloader_data { + f.write_fmt(format_args!( + "\nBootloader data present, length: 0x{:X}", + data.len() + ))?; + } else { + f.write_str("\nNo bootloader data included")?; + } + if let Some(data) = &self.primer_data { + f.write_fmt(format_args!( + "\nPrimer data present, length: 0x{:X}", + data.len() + ))?; + } else { + f.write_str("\nNo primer data included")?; + } + Ok(()) + } +} + +const SC64_FIRMWARE_UPDATE_TOKEN: &[u8; 16] = b"SC64 Update v2.0"; + +pub fn verify(data: &[u8]) -> Result { + let mut buffer = vec![0u8; 16]; + + let mut reader = Cursor::new(data); + + reader.read(&mut buffer)?; + if buffer != SC64_FIRMWARE_UPDATE_TOKEN { + return Err(Error::new("Invalid firmware update header")); + } + + let mut firmware = Firmware { + update_info: None, + mcu_data: None, + fpga_data: None, + bootloader_data: None, + primer_data: None, + }; + + loop { + let bytes = reader.read(&mut buffer)?; + if bytes == 16 { + let id: ChunkId = u32::from_le_bytes(buffer[0..4].try_into().unwrap()).try_into()?; + let aligned_length = u32::from_le_bytes(buffer[4..8].try_into().unwrap()); + let checksum = u32::from_le_bytes(buffer[8..12].try_into().unwrap()); + let data_length = u32::from_le_bytes(buffer[12..16].try_into().unwrap()); + + let mut data = vec![0u8; data_length as usize]; + reader.read(&mut data)?; + + let align = aligned_length - 4 - 4 - data_length; + reader.seek(SeekFrom::Current(align as i64))?; + + if crc32fast::hash(&data) != checksum { + return Err(Error::new( + format!("Invalid checksum for chunk [{id}]").as_str(), + )); + } + + match id { + ChunkId::UpdateInfo => { + firmware.update_info = Some(String::from_utf8_lossy(&data).to_string()) + } + ChunkId::McuData => firmware.mcu_data = Some(data), + ChunkId::FpgaData => firmware.fpga_data = Some(data), + ChunkId::BootloaderData => firmware.bootloader_data = Some(data), + ChunkId::PrimerData => firmware.primer_data = Some(data), + } + } else if bytes == 0 { + break; + } else { + return Err(Error::new("Unexpected end of data in firmware update")); + } + } + + Ok(firmware) +} diff --git a/sw/deployer/src/sc64/link.rs b/sw/deployer/src/sc64/link.rs new file mode 100644 index 0000000..cbdee88 --- /dev/null +++ b/sw/deployer/src/sc64/link.rs @@ -0,0 +1,505 @@ +use super::error::Error; +use std::{ + collections::VecDeque, + io::{BufRead, BufReader, BufWriter, ErrorKind, Read, Write}, + net::{TcpListener, TcpStream}, + time::{Duration, Instant}, +}; + +enum DataType { + Command, + Response, + Packet, + KeepAlive, +} + +impl From for u32 { + fn from(value: DataType) -> Self { + match value { + DataType::Command => 1, + DataType::Response => 2, + DataType::Packet => 3, + DataType::KeepAlive => 0xCAFEBEEF, + } + } +} + +impl TryFrom for DataType { + type Error = Error; + fn try_from(value: u32) -> Result { + Ok(match value { + 1 => Self::Command, + 2 => Self::Response, + 3 => Self::Packet, + 0xCAFEBEEF => Self::KeepAlive, + _ => return Err(Error::new("Unknown data type")), + }) + } +} + +pub struct Command<'a> { + pub id: u8, + pub args: [u32; 2], + pub data: &'a [u8], +} + +pub struct Response { + pub id: u8, + pub data: Vec, + pub error: bool, +} + +pub struct Packet { + pub id: u8, + pub data: Vec, +} + +trait Backend { + fn send_command(&mut self, command: &Command) -> Result<(), Error>; + fn process_incoming_data( + &mut self, + data_type: DataType, + packets: &mut VecDeque, + ) -> Result, Error>; +} + +struct SerialBackend { + serial: Box, +} + +impl SerialBackend { + fn reset(&mut self) -> Result<(), Error> { + const WAIT_DURATION: Duration = Duration::from_millis(10); + const RETRY_COUNT: i32 = 100; + + self.serial.write_data_terminal_ready(true)?; + for n in 0..=RETRY_COUNT { + self.serial.clear(serialport::ClearBuffer::All)?; + std::thread::sleep(WAIT_DURATION); + if self.serial.read_data_set_ready()? { + break; + } + if n == RETRY_COUNT { + return Err(Error::new("Couldn't reset SC64 device (on)")); + } + } + + self.serial.write_data_terminal_ready(false)?; + for n in 0..=RETRY_COUNT { + std::thread::sleep(WAIT_DURATION); + if !self.serial.read_data_set_ready()? { + break; + } + if n == RETRY_COUNT { + return Err(Error::new("Couldn't reset SC64 device (off)")); + } + } + + Ok(()) + } +} + +impl Backend for SerialBackend { + fn send_command(&mut self, command: &Command) -> Result<(), Error> { + self.serial.write_all(b"CMD")?; + self.serial.write_all(&command.id.to_be_bytes())?; + self.serial.write_all(&command.args[0].to_be_bytes())?; + self.serial.write_all(&command.args[1].to_be_bytes())?; + + self.serial.write_all(&command.data)?; + + self.serial.flush()?; + + Ok(()) + } + + fn process_incoming_data( + &mut self, + data_type: DataType, + packets: &mut VecDeque, + ) -> Result, Error> { + let mut buffer = [0u8; 4]; + + while matches!(data_type, DataType::Response) + || self.serial.bytes_to_read()? as usize >= buffer.len() + { + self.serial.read_exact(&mut buffer)?; + let (packet_token, error) = (match &buffer[0..3] { + b"CMP" => Ok((false, false)), + b"PKT" => Ok((true, false)), + b"ERR" => Ok((false, true)), + _ => Err(Error::new("Unknown response token")), + })?; + let id = buffer[3]; + + self.serial.read_exact(&mut buffer)?; + let length = u32::from_be_bytes(buffer) as usize; + + let mut data = vec![0u8; length]; + self.serial.read_exact(&mut data)?; + + if packet_token { + packets.push_back(Packet { id, data }); + if matches!(data_type, DataType::Packet) { + break; + } + } else { + return Ok(Some(Response { id, error, data })); + } + } + + Ok(None) + } +} + +fn new_serial_backend(port: &str) -> Result { + let serial = serialport::new(port, 115_200) + .timeout(Duration::from_secs(10)) + .open()?; + let mut backend = SerialBackend { serial }; + backend.reset()?; + Ok(backend) +} + +struct TcpBackend { + stream: TcpStream, + reader: BufReader, + writer: BufWriter, +} + +impl TcpBackend { + fn bytes_to_read(&mut self) -> Result { + self.stream.set_nonblocking(true)?; + let result = self.reader.fill_buf(); + let length = match result { + Ok(buffer) => buffer.len(), + Err(error) => { + if error.kind() == ErrorKind::WouldBlock { + 0 + } else { + return Err(error.into()); + } + } + }; + self.stream.set_nonblocking(false)?; + return Ok(length); + } +} + +impl Backend for TcpBackend { + fn send_command(&mut self, command: &Command) -> Result<(), Error> { + let payload_data_type: u32 = DataType::Command.into(); + self.writer.write_all(&payload_data_type.to_be_bytes())?; + + self.writer.write_all(&command.id.to_be_bytes())?; + self.writer.write_all(&command.args[0].to_be_bytes())?; + self.writer.write_all(&command.args[1].to_be_bytes())?; + + let command_data_length = command.data.len() as u32; + self.writer.write_all(&command_data_length.to_be_bytes())?; + self.writer.write_all(&command.data)?; + + self.writer.flush()?; + + Ok(()) + } + + fn process_incoming_data( + &mut self, + data_type: DataType, + packets: &mut VecDeque, + ) -> Result, Error> { + let mut buffer = [0u8; 4]; + + while matches!(data_type, DataType::Response) || self.bytes_to_read()? >= 4 { + self.reader.read_exact(&mut buffer)?; + let payload_data_type: DataType = u32::from_be_bytes(buffer).try_into()?; + + match payload_data_type { + DataType::Response => { + let mut response_info = vec![0u8; 2]; + self.reader.read_exact(&mut response_info)?; + + self.reader.read_exact(&mut buffer)?; + let response_data_length = u32::from_be_bytes(buffer) as usize; + + let mut data = vec![0u8; response_data_length]; + self.reader.read_exact(&mut data)?; + + return Ok(Some(Response { + id: response_info[0], + error: response_info[1] != 0, + data, + })); + } + DataType::Packet => { + let mut packet_info = vec![0u8; 1]; + self.reader.read_exact(&mut packet_info)?; + + self.reader.read_exact(&mut buffer)?; + let packet_data_length = u32::from_be_bytes(buffer) as usize; + + let mut data = vec![0u8; packet_data_length]; + self.reader.read_exact(&mut data)?; + + packets.push_back(Packet { + id: packet_info[0], + data, + }); + if matches!(data_type, DataType::Packet) { + break; + } + } + DataType::KeepAlive => {} + _ => return Err(Error::new("Unexpected payload data type received")), + }; + } + + Ok(None) + } +} + +fn new_tcp_backend(address: &str) -> Result { + let stream = match TcpStream::connect(address) { + Ok(stream) => { + stream.set_write_timeout(Some(Duration::from_secs(10)))?; + stream.set_read_timeout(Some(Duration::from_secs(10)))?; + stream + } + Err(error) => { + return Err(Error::new( + format!("Couldn't connect to [{address}]: {error}").as_str(), + )) + } + }; + let reader = BufReader::new(stream.try_clone()?); + let writer = BufWriter::new(stream.try_clone()?); + Ok(TcpBackend { + stream, + reader, + writer, + }) +} + +pub struct Link { + backend: Box, + packets: VecDeque, +} + +impl Link { + pub fn execute_command(&mut self, command: &Command) -> Result, Error> { + self.execute_command_raw(command, false, false) + } + + pub fn execute_command_raw( + &mut self, + command: &Command, + no_response: bool, + ignore_error: bool, + ) -> Result, Error> { + self.backend.send_command(command)?; + if no_response { + return Ok(vec![]); + } + let response = self.receive_response()?; + if command.id != response.id { + return Err(Error::new("Command response ID didn't match")); + } + if !ignore_error && response.error { + return Err(Error::new("Command response error")); + } + Ok(response.data) + } + + fn receive_response(&mut self) -> Result { + match self + .backend + .process_incoming_data(DataType::Response, &mut self.packets) + { + Ok(response) => match response { + Some(response) => Ok(response), + None => Err(Error::new("No response was received")), + }, + Err(error) => Err(Error::new( + format!("Command response error: {error}").as_str(), + )), + } + } + + pub fn receive_packet(&mut self) -> Result, Error> { + if self.packets.len() == 0 { + let response = self + .backend + .process_incoming_data(DataType::Packet, &mut self.packets)?; + if response.is_some() { + return Err(Error::new("Unexpected command response in data stream")); + } + } + Ok(self.packets.pop_front()) + } +} + +pub fn new_local(port: &str) -> Result { + Ok(Link { + backend: Box::new(new_serial_backend(port)?), + packets: VecDeque::new(), + }) +} + +pub fn new_remote(address: &str) -> Result { + Ok(Link { + backend: Box::new(new_tcp_backend(address)?), + packets: VecDeque::new(), + }) +} + +pub struct LocalDevice { + pub port: String, + pub serial_number: String, +} + +pub fn list_local_devices() -> Result, Error> { + const SC64_VID: u16 = 0x0403; + const SC64_PID: u16 = 0x6014; + const SC64_SID: &str = "SC64"; + + let mut serial_devices: Vec = Vec::new(); + + for device in serialport::available_ports()?.into_iter() { + if let serialport::SerialPortType::UsbPort(info) = device.port_type { + let serial_number = info.serial_number.unwrap_or("".to_string()); + if info.vid == SC64_VID && info.pid == SC64_PID && serial_number.starts_with(SC64_SID) { + serial_devices.push(LocalDevice { + port: device.port_name, + serial_number, + }); + } + } + } + + if serial_devices.len() == 0 { + return Err(Error::new("No SC64 devices found")); + } + + return Ok(serial_devices); +} + +pub enum ServerEvent { + Listening(String), + Connection(String), + Disconnected(String), + Err(String), +} + +pub fn run_server( + port: &str, + address: String, + event_callback: fn(ServerEvent), +) -> Result<(), Error> { + let listener = TcpListener::bind(address)?; + + event_callback(ServerEvent::Listening(listener.local_addr()?.to_string())); + + for stream in listener.incoming() { + match stream { + Ok(mut stream) => match server_accept_connection(port, event_callback, &mut stream) { + Ok(()) => {} + Err(error) => event_callback(ServerEvent::Err(error.to_string())), + }, + Err(error) => return Err(error.into()), + } + } + + Ok(()) +} + +fn server_accept_connection( + port: &str, + event_callback: fn(ServerEvent), + stream: &mut TcpStream, +) -> Result<(), Error> { + let peer = stream.peer_addr()?.to_string(); + + stream.set_write_timeout(Some(Duration::from_secs(10)))?; + stream.set_read_timeout(Some(Duration::from_secs(10)))?; + + let mut reader = BufReader::new(stream.try_clone()?); + let mut writer = BufWriter::new(stream.try_clone()?); + + let mut serial_backend = new_serial_backend(port)?; + serial_backend.reset()?; + + let mut packets: VecDeque = VecDeque::new(); + + let mut buffer = [0u8; 4]; + + let mut keepalive = Instant::now(); + + event_callback(ServerEvent::Connection(peer.clone())); + + loop { + stream.set_nonblocking(true)?; + match reader.read_exact(&mut buffer) { + Ok(()) => { + stream.set_nonblocking(false)?; + + let data_type: DataType = u32::from_be_bytes(buffer).try_into()?; + + if !matches!(data_type, DataType::Command) { + return Err(Error::new("Received data type wasn't a command data type")); + } + + let mut id_buffer = [0u8; 1]; + let mut args = [0u32; 2]; + + reader.read_exact(&mut id_buffer)?; + reader.read_exact(&mut buffer)?; + args[0] = u32::from_be_bytes(buffer); + reader.read_exact(&mut buffer)?; + args[1] = u32::from_be_bytes(buffer); + + reader.read_exact(&mut buffer)?; + let command_data_length = u32::from_be_bytes(buffer) as usize; + let mut data = vec![0u8; command_data_length]; + reader.read_exact(&mut data)?; + + serial_backend.send_command(&Command { + id: id_buffer[0], + args, + data: &data, + })?; + + continue; + } + Err(error) => { + if error.kind() != ErrorKind::WouldBlock { + event_callback(ServerEvent::Disconnected(peer.clone())); + return Ok(()); + } + stream.set_nonblocking(false)?; + } + } + if let Some(response) = + serial_backend.process_incoming_data(DataType::Packet, &mut packets)? + { + writer.write_all(&u32::to_be_bytes(DataType::Response.into()))?; + writer.write_all(&[response.id])?; + writer.write_all(&[response.error as u8])?; + writer.write_all(&(response.data.len() as u32).to_be_bytes())?; + writer.write_all(&response.data)?; + writer.flush()?; + } else if let Some(packet) = packets.pop_front() { + writer.write_all(&u32::to_be_bytes(DataType::Packet.into()))?; + writer.write_all(&[packet.id])?; + writer.write_all(&(packet.data.len() as u32).to_be_bytes())?; + writer.write_all(&packet.data)?; + writer.flush()?; + } else if keepalive.elapsed() > Duration::from_secs(5) { + keepalive = Instant::now(); + writer.write_all(&u32::to_be_bytes(DataType::KeepAlive.into()))?; + writer.flush()?; + } else { + std::thread::sleep(Duration::from_millis(1)); + } + } +} diff --git a/sw/deployer/src/sc64/mod.rs b/sw/deployer/src/sc64/mod.rs new file mode 100644 index 0000000..39c6592 --- /dev/null +++ b/sw/deployer/src/sc64/mod.rs @@ -0,0 +1,788 @@ +mod cic; +mod error; +pub mod firmware; +mod link; +mod types; +mod utils; + +pub use self::{ + error::Error, + link::{list_local_devices, ServerEvent}, + types::{ + BootMode, ButtonMode, ButtonState, CicSeed, DataPacket, DdDiskState, DdDriveType, DdMode, + DebugPacket, DiskPacket, DiskPacketKind, FpgaDebugData, McuStackUsage, SaveType, Switch, + TvType, + }, +}; + +use self::{ + cic::{calculate_ipl3_checksum, guess_ipl3_seed, IPL3_LENGTH, IPL3_OFFSET}, + link::{Command, Link}, + types::{ + get_config, get_setting, Config, ConfigId, FirmwareStatus, Setting, SettingId, UpdateStatus, + }, + utils::{convert_from_datetime, convert_to_datetime}, +}; +use chrono::{DateTime, Local}; +use std::{ + io::{Read, Seek, Write}, + time::Instant, + {cmp::min, time::Duration}, +}; + +pub struct SC64 { + link: Link, +} + +pub struct DeviceState { + pub bootloader_switch: Switch, + pub rom_write_enable: Switch, + pub rom_shadow_enable: Switch, + pub dd_mode: DdMode, + pub isv_address: u32, + pub boot_mode: BootMode, + pub save_type: SaveType, + pub cic_seed: CicSeed, + pub tv_type: TvType, + pub dd_sd_enable: Switch, + pub dd_drive_type: DdDriveType, + pub dd_disk_state: DdDiskState, + pub button_state: ButtonState, + pub button_mode: ButtonMode, + pub rom_extended_enable: Switch, + pub led_enable: Switch, + pub datetime: DateTime, + pub fpga_debug_data: FpgaDebugData, + pub mcu_stack_usage: McuStackUsage, +} + +const SC64_V2_IDENTIFIER: &[u8; 4] = b"SCv2"; + +const SUPPORTED_MAJOR_VERSION: u16 = 2; +const SUPPORTED_MINOR_VERSION: u16 = 12; + +const SDRAM_ADDRESS: u32 = 0x0000_0000; +const SDRAM_LENGTH: usize = 64 * 1024 * 1024; + +const ROM_SHADOW_ADDRESS: u32 = 0x04FE_0000; +const ROM_SHADOW_LENGTH: usize = 128 * 1024; + +const ROM_EXTENDED_ADDRESS: u32 = 0x0400_0000; +const ROM_EXTENDED_LENGTH: usize = 14 * 1024 * 1024; + +const MAX_ROM_LENGTH: usize = 78 * 1024 * 1024; + +const DDIPL_ADDRESS: u32 = 0x03BC_0000; +const DDIPL_LENGTH: usize = 4 * 1024 * 1024; + +const SAVE_ADDRESS: u32 = 0x03FE_0000; +const EEPROM_ADDRESS: u32 = 0x0500_2000; + +const EEPROM_4K_LENGTH: usize = 512; +const EEPROM_16K_LENGTH: usize = 2 * 1024; +const SRAM_LENGTH: usize = 32 * 1024; +const SRAM_BANKED_LENGTH: usize = 3 * 32 * 1024; +const FLASHRAM_LENGTH: usize = 128 * 1024; + +const BOOTLOADER_ADDRESS: u32 = 0x04E0_0000; + +const FIRMWARE_ADDRESS: u32 = 0x0010_0000; // Arbitrary offset in SDRAM memory +const FIRMWARE_UPDATE_TIMEOUT: Duration = Duration::from_secs(90); + +const ISV_BUFFER_LENGTH: usize = 64 * 1024; + +pub const MEMORY_LENGTH: usize = 0x0500_2980; + +const MEMORY_CHUNK_LENGTH: usize = 1 * 1024 * 1024; + +impl SC64 { + fn command_identifier_get(&mut self) -> Result<[u8; 4], Error> { + let data = self.link.execute_command(&Command { + id: b'v', + args: [0, 0], + data: &[], + })?; + if data.len() != 4 { + return Err(Error::new( + "Invalid data length received for identifier get command", + )); + } + Ok(data[0..4].try_into().unwrap()) + } + + fn command_version_get(&mut self) -> Result<(u16, u16, u32), Error> { + let data = self.link.execute_command(&Command { + id: b'V', + args: [0, 0], + data: &[], + })?; + if data.len() != 8 { + return Err(Error::new( + "Invalid data length received for version get command", + )); + } + let major = u16::from_be_bytes(data[0..2].try_into().unwrap()); + let minor = u16::from_be_bytes(data[2..4].try_into().unwrap()); + let revision = u32::from_be_bytes(data[4..8].try_into().unwrap()); + Ok((major, minor, revision)) + } + + fn command_state_reset(&mut self) -> Result<(), Error> { + self.link.execute_command(&Command { + id: b'R', + args: [0, 0], + data: &[], + })?; + Ok(()) + } + + fn command_cic_params_set( + &mut self, + disable: bool, + seed: u8, + checksum: &[u8; 6], + ) -> Result<(), Error> { + let args = [ + u32::from_be_bytes([(disable as u8) << 0, seed, checksum[0], checksum[1]]), + u32::from_be_bytes([checksum[2], checksum[3], checksum[4], checksum[5]]), + ]; + self.link.execute_command(&Command { + id: b'B', + args, + data: &[], + })?; + Ok(()) + } + + fn command_config_get(&mut self, config_id: ConfigId) -> Result { + let data = self.link.execute_command(&Command { + id: b'c', + args: [config_id.into(), 0], + data: &[], + })?; + if data.len() != 4 { + return Err(Error::new( + "Invalid data length received for config get command", + )); + } + let value = u32::from_be_bytes(data[0..4].try_into().unwrap()); + Ok((config_id, value).try_into()?) + } + + fn command_config_set(&mut self, config: Config) -> Result<(), Error> { + self.link.execute_command(&Command { + id: b'C', + args: config.into(), + data: &[], + })?; + Ok(()) + } + + fn command_setting_get(&mut self, setting_id: SettingId) -> Result { + let data = self.link.execute_command(&Command { + id: b'a', + args: [setting_id.into(), 0], + data: &[], + })?; + if data.len() != 4 { + return Err(Error::new( + "Invalid data length received for setting get command", + )); + } + let value = u32::from_be_bytes(data[0..4].try_into().unwrap()); + Ok((setting_id, value).try_into()?) + } + + fn command_setting_set(&mut self, setting: Setting) -> Result<(), Error> { + self.link.execute_command(&Command { + id: b'A', + args: setting.into(), + data: &[], + })?; + Ok(()) + } + + fn command_time_get(&mut self) -> Result, Error> { + let data = self.link.execute_command(&Command { + id: b't', + args: [0, 0], + data: &[], + })?; + if data.len() != 8 { + return Err(Error::new( + "Invalid data length received for time get command", + )); + } + Ok(convert_to_datetime(&data[0..8].try_into().unwrap())?) + } + + fn command_time_set(&mut self, datetime: DateTime) -> Result<(), Error> { + self.link.execute_command(&Command { + id: b'T', + args: convert_from_datetime(datetime), + data: &[], + })?; + Ok(()) + } + + fn command_memory_read(&mut self, address: u32, length: usize) -> Result, Error> { + let data = self.link.execute_command(&Command { + id: b'm', + args: [address, length as u32], + data: &[], + })?; + if data.len() != length { + return Err(Error::new( + "Invalid data length received for memory read command", + )); + } + Ok(data) + } + + fn command_memory_write(&mut self, address: u32, data: &[u8]) -> Result<(), Error> { + self.link.execute_command(&Command { + id: b'M', + args: [address, data.len() as u32], + data, + })?; + Ok(()) + } + + fn command_usb_write(&mut self, datatype: u8, data: &[u8]) -> Result<(), Error> { + self.link.execute_command_raw( + &Command { + id: b'U', + args: [datatype as u32, data.len() as u32], + data, + }, + true, + false, + )?; + Ok(()) + } + + fn command_dd_set_block_ready(&mut self, error: bool) -> Result<(), Error> { + self.link.execute_command(&Command { + id: b'D', + args: [error as u32, 0], + data: &[], + })?; + Ok(()) + } + + fn command_flash_wait_busy(&mut self, wait: bool) -> Result { + let data = self.link.execute_command(&Command { + id: b'p', + args: [wait as u32, 0], + data: &[], + })?; + if data.len() != 4 { + return Err(Error::new( + "Invalid data length received for flash wait busy command", + )); + } + let erase_block_size = u32::from_be_bytes(data[0..4].try_into().unwrap()); + Ok(erase_block_size) + } + + fn command_flash_erase_block(&mut self, address: u32) -> Result<(), Error> { + self.link.execute_command(&Command { + id: b'P', + args: [address, 0], + data: &[], + })?; + Ok(()) + } + + fn command_firmware_backup(&mut self, address: u32) -> Result<(FirmwareStatus, u32), Error> { + let data = self.link.execute_command_raw( + &Command { + id: b'f', + args: [address, 0], + data: &[], + }, + false, + true, + )?; + if data.len() != 8 { + return Err(Error::new( + "Invalid data length received for firmware backup command", + )); + } + let status = u32::from_be_bytes(data[0..4].try_into().unwrap()); + let length = u32::from_be_bytes(data[4..8].try_into().unwrap()); + Ok((status.try_into()?, length)) + } + + fn command_firmware_update( + &mut self, + address: u32, + length: usize, + ) -> Result { + let data = self.link.execute_command_raw( + &Command { + id: b'F', + args: [address, length as u32], + data: &[], + }, + false, + true, + )?; + if data.len() != 4 { + return Err(Error::new( + "Invalid data length received for firmware update command", + )); + } + Ok(u32::from_be_bytes(data[0..4].try_into().unwrap()).try_into()?) + } + + fn command_debug_get(&mut self) -> Result { + let data = self.link.execute_command(&Command { + id: b'?', + args: [0, 0], + data: &[], + })?; + Ok(data.try_into()?) + } + + fn command_stack_usage_get(&mut self) -> Result { + let data = self.link.execute_command(&Command { + id: b'%', + args: [0, 0], + data: &[], + })?; + Ok(data.try_into()?) + } +} + +impl SC64 { + pub fn upload_rom( + &mut self, + reader: &mut T, + length: usize, + no_shadow: bool, + ) -> Result<(), Error> { + if length > MAX_ROM_LENGTH { + return Err(Error::new("ROM length too big")); + } + + let mut pi_config = vec![0u8; 4]; + + reader.rewind()?; + reader.read_exact(&mut pi_config)?; + reader.rewind()?; + + let endian_swapper = match &pi_config[0..4] { + [0x37, 0x80, 0x40, 0x12] => { + |b: &mut [u8]| b.chunks_exact_mut(2).for_each(|c| c.swap(0, 1)) + } + [0x40, 0x12, 0x37, 0x80] => |b: &mut [u8]| { + b.chunks_exact_mut(4).for_each(|c| { + c.swap(0, 3); + c.swap(1, 2) + }) + }, + _ => |_: &mut [u8]| {}, + }; + + let rom_shadow_enabled = !no_shadow && length > (SDRAM_LENGTH - ROM_SHADOW_LENGTH); + let rom_extended_enabled = length > SDRAM_LENGTH; + + let sdram_length = if rom_shadow_enabled { + min(length, SDRAM_LENGTH - ROM_SHADOW_LENGTH) + } else { + min(length, SDRAM_LENGTH) + }; + + self.memory_write_chunked(reader, SDRAM_ADDRESS, sdram_length, Some(endian_swapper))?; + + self.command_config_set(Config::RomShadowEnable(rom_shadow_enabled.into()))?; + if rom_shadow_enabled { + let rom_shadow_length = min(length - sdram_length, ROM_SHADOW_LENGTH); + self.flash_program( + reader, + ROM_SHADOW_ADDRESS, + rom_shadow_length, + Some(endian_swapper), + )?; + } + + self.command_config_set(Config::RomExtendedEnable(rom_extended_enabled.into()))?; + if rom_extended_enabled { + let rom_extended_length = min(length - SDRAM_LENGTH, ROM_EXTENDED_LENGTH); + self.flash_program( + reader, + ROM_EXTENDED_ADDRESS, + rom_extended_length, + Some(endian_swapper), + )?; + } + + Ok(()) + } + + pub fn upload_ddipl(&mut self, reader: &mut T, length: usize) -> Result<(), Error> { + if length > DDIPL_LENGTH { + return Err(Error::new("DDIPL length too big")); + } + + self.memory_write_chunked(reader, DDIPL_ADDRESS, length, None) + } + + pub fn upload_save(&mut self, reader: &mut T, length: usize) -> Result<(), Error> { + let save_type = get_config!(self, SaveType)?; + + let (address, save_length) = match save_type { + SaveType::None => { + return Err(Error::new("No save type is enabled")); + } + SaveType::Eeprom4k => (EEPROM_ADDRESS, EEPROM_4K_LENGTH), + SaveType::Eeprom16k => (EEPROM_ADDRESS, EEPROM_16K_LENGTH), + SaveType::Sram => (SAVE_ADDRESS, SRAM_LENGTH), + SaveType::SramBanked => (SAVE_ADDRESS, SRAM_BANKED_LENGTH), + SaveType::Flashram => (SAVE_ADDRESS, FLASHRAM_LENGTH), + }; + + if length != save_length { + return Err(Error::new( + "Save file size did not match currently enabled save type", + )); + } + + self.memory_write_chunked(reader, address, save_length, None) + } + + pub fn download_save(&mut self, writer: &mut T) -> Result<(), Error> { + let save_type = get_config!(self, SaveType)?; + + let (address, save_length) = match save_type { + SaveType::None => { + return Err(Error::new("No save type is enabled")); + } + SaveType::Eeprom4k => (EEPROM_ADDRESS, EEPROM_4K_LENGTH), + SaveType::Eeprom16k => (EEPROM_ADDRESS, EEPROM_16K_LENGTH), + SaveType::Sram => (SAVE_ADDRESS, SRAM_LENGTH), + SaveType::SramBanked => (SAVE_ADDRESS, SRAM_BANKED_LENGTH), + SaveType::Flashram => (SAVE_ADDRESS, FLASHRAM_LENGTH), + }; + + self.memory_read_chunked(writer, address, save_length) + } + + pub fn dump_memory( + &mut self, + writer: &mut T, + address: u32, + length: usize, + ) -> Result<(), Error> { + if address + length as u32 > MEMORY_LENGTH as u32 { + return Err(Error::new("Invalid dump address or length")); + } + self.memory_read_chunked(writer, address, length) + } + + pub fn calculate_cic_parameters(&mut self) -> Result<(), Error> { + let boot_mode = get_config!(self, BootMode)?; + let address = match boot_mode { + BootMode::DirectRom => SDRAM_ADDRESS, + BootMode::DirectDdIpl => DDIPL_ADDRESS, + _ => BOOTLOADER_ADDRESS, + }; + let ipl3 = self.command_memory_read(address + IPL3_OFFSET, IPL3_LENGTH)?; + let seed = guess_ipl3_seed(&ipl3)?; + let checksum = &calculate_ipl3_checksum(&ipl3, seed)?; + self.command_cic_params_set(false, seed, checksum) + } + + pub fn set_boot_mode(&mut self, boot_mode: BootMode) -> Result<(), Error> { + self.command_config_set(Config::BootMode(boot_mode)) + } + + pub fn set_save_type(&mut self, save_type: SaveType) -> Result<(), Error> { + self.command_config_set(Config::SaveType(save_type)) + } + + pub fn set_tv_type(&mut self, tv_type: TvType) -> Result<(), Error> { + self.command_config_set(Config::TvType(tv_type)) + } + + pub fn get_datetime(&mut self) -> Result, Error> { + self.command_time_get() + } + + pub fn set_datetime(&mut self, datetime: DateTime) -> Result<(), Error> { + self.command_time_set(datetime) + } + + pub fn set_led_blink(&mut self, enabled: bool) -> Result<(), Error> { + self.command_setting_set(Setting::LedEnable(enabled.into())) + } + + pub fn get_device_state(&mut self) -> Result { + Ok(DeviceState { + bootloader_switch: get_config!(self, BootloaderSwitch)?, + rom_write_enable: get_config!(self, RomWriteEnable)?, + rom_shadow_enable: get_config!(self, RomShadowEnable)?, + dd_mode: get_config!(self, DdMode)?, + isv_address: get_config!(self, IsvAddress)?, + boot_mode: get_config!(self, BootMode)?, + save_type: get_config!(self, SaveType)?, + cic_seed: get_config!(self, CicSeed)?, + tv_type: get_config!(self, TvType)?, + dd_sd_enable: get_config!(self, DdSdEnable)?, + dd_drive_type: get_config!(self, DdDriveType)?, + dd_disk_state: get_config!(self, DdDiskState)?, + button_state: get_config!(self, ButtonState)?, + button_mode: get_config!(self, ButtonMode)?, + rom_extended_enable: get_config!(self, RomExtendedEnable)?, + led_enable: get_setting!(self, LedEnable)?, + datetime: self.get_datetime()?, + fpga_debug_data: self.command_debug_get()?, + mcu_stack_usage: self.command_stack_usage_get()?, + }) + } + + pub fn configure_64dd( + &mut self, + dd_mode: DdMode, + drive_type: DdDriveType, + ) -> Result<(), Error> { + self.command_config_set(Config::DdMode(dd_mode))?; + self.command_config_set(Config::DdSdEnable(Switch::Off))?; + self.command_config_set(Config::DdDriveType(drive_type))?; + self.command_config_set(Config::DdDiskState(DdDiskState::Ejected))?; + self.command_config_set(Config::ButtonMode(ButtonMode::UsbPacket))?; + Ok(()) + } + + pub fn set_64dd_disk_state(&mut self, disk_state: DdDiskState) -> Result<(), Error> { + self.command_config_set(Config::DdDiskState(disk_state)) + } + + pub fn configure_is_viewer_64(&mut self, offset: Option) -> Result<(), Error> { + if let Some(offset) = offset { + if get_config!(self, RomShadowEnable)?.into() { + if offset > (SAVE_ADDRESS - ISV_BUFFER_LENGTH as u32) { + return Err(Error::new( + format!( + "ROM shadow is enabled, IS-Viewer 64 at offset 0x{offset:08X} won't work" + ) + .as_str(), + )); + } + } + self.command_config_set(Config::RomWriteEnable(Switch::On))?; + self.command_config_set(Config::IsvAddress(offset))?; + } else { + self.command_config_set(Config::RomWriteEnable(Switch::Off))?; + self.command_config_set(Config::IsvAddress(0))?; + } + Ok(()) + } + + pub fn receive_data_packet(&mut self) -> Result, Error> { + if let Some(packet) = self.link.receive_packet()? { + return Ok(Some(packet.try_into()?)); + } + Ok(None) + } + + pub fn reply_disk_packet(&mut self, disk_packet: Option) -> Result<(), Error> { + if let Some(packet) = disk_packet { + match packet.kind { + DiskPacketKind::Read => { + self.command_memory_write(packet.info.address, &packet.info.data)?; + } + DiskPacketKind::Write => {} + } + self.command_dd_set_block_ready(false)?; + } else { + self.command_dd_set_block_ready(true)?; + } + Ok(()) + } + + pub fn send_debug_packet(&mut self, debug_packet: DebugPacket) -> Result<(), Error> { + self.command_usb_write(debug_packet.datatype, &debug_packet.data) + } + + pub fn check_device(&mut self) -> Result<(), Error> { + let identifier = self.command_identifier_get().map_err(|e| { + Error::new(format!("Couldn't get SC64 device identifier: {e}").as_str()) + })?; + if &identifier != SC64_V2_IDENTIFIER { + return Err(Error::new("Unknown identifier received, not a SC64 device")); + } + Ok(()) + } + + pub fn check_firmware_version(&mut self) -> Result<(u16, u16, u32), Error> { + let (major, minor, revision) = self + .command_version_get() + .map_err(|_| Error::new("Outdated SC64 firmware version, please update firmware"))?; + if major != SUPPORTED_MAJOR_VERSION || minor < SUPPORTED_MINOR_VERSION { + return Err(Error::new( + "Unsupported SC64 firmware version, please update firmware", + )); + } + Ok((major, minor, revision)) + } + + pub fn reset_state(&mut self) -> Result<(), Error> { + self.command_state_reset() + } + + pub fn backup_firmware(&mut self) -> Result, Error> { + self.command_state_reset()?; + let (status, length) = self.command_firmware_backup(FIRMWARE_ADDRESS)?; + if !matches!(status, FirmwareStatus::Ok) { + return Err(Error::new( + format!("Firmware backup error: {}", status).as_str(), + )); + } + self.command_memory_read(FIRMWARE_ADDRESS, length as usize) + } + + pub fn update_firmware(&mut self, data: &[u8]) -> Result<(), Error> { + self.command_state_reset()?; + self.command_memory_write(FIRMWARE_ADDRESS, data)?; + let status = self.command_firmware_update(FIRMWARE_ADDRESS, data.len())?; + if !matches!(status, FirmwareStatus::Ok) { + return Err(Error::new( + format!("Firmware update verify error: {}", status).as_str(), + )); + } + let timeout = Instant::now(); + let mut last_update_status = UpdateStatus::Err; + loop { + if let Some(packet) = self.receive_data_packet()? { + if let DataPacket::UpdateStatus(status) = packet { + match status { + UpdateStatus::Done => { + std::thread::sleep(Duration::from_secs(2)); + return Ok(()); + } + UpdateStatus::Err => { + return Err(Error::new( + format!( + "Firmware update error on step {}, device is, most likely, bricked", + last_update_status + ) + .as_str(), + )) + } + current_update_status => last_update_status = current_update_status, + } + } + } + if timeout.elapsed() > FIRMWARE_UPDATE_TIMEOUT { + return Err(Error::new( + format!( + "Firmware update timeout, SC64 did not finish update in {} seconds, last step: {}", + FIRMWARE_UPDATE_TIMEOUT.as_secs(), + last_update_status + ) + .as_str(), + )); + } + std::thread::sleep(Duration::from_millis(1)); + } + } + + fn memory_read_chunked( + &mut self, + writer: &mut dyn Write, + address: u32, + length: usize, + ) -> Result<(), Error> { + let mut memory_address = address; + let mut bytes_left = length; + while bytes_left > 0 { + let bytes = min(MEMORY_CHUNK_LENGTH, bytes_left); + let data = self.command_memory_read(memory_address, bytes)?; + writer.write_all(&data)?; + memory_address += bytes as u32; + bytes_left -= bytes; + } + Ok(()) + } + + fn memory_write_chunked( + &mut self, + reader: &mut dyn Read, + address: u32, + length: usize, + transform: Option, + ) -> Result<(), Error> { + let mut limited_reader = reader.take(length as u64); + let mut memory_address = address; + let mut data: Vec = vec![0u8; MEMORY_CHUNK_LENGTH]; + loop { + let bytes = limited_reader.read(&mut data)?; + if bytes == 0 { + break; + } + if let Some(transform) = transform { + transform(&mut data[0..bytes]); + } + self.command_memory_write(memory_address, &data[0..bytes])?; + memory_address += bytes as u32; + } + Ok(()) + } + + fn flash_erase(&mut self, address: u32, length: usize) -> Result<(), Error> { + let erase_block_size = self.command_flash_wait_busy(false)?; + for offset in (0..length as u32).step_by(erase_block_size as usize) { + self.command_flash_erase_block(address + offset)?; + } + Ok(()) + } + + fn flash_program( + &mut self, + reader: &mut dyn Read, + address: u32, + length: usize, + transform: Option, + ) -> Result<(), Error> { + self.flash_erase(address, length)?; + self.memory_write_chunked(reader, address, length, transform)?; + self.command_flash_wait_busy(true)?; + Ok(()) + } +} + +pub fn new_local(port: Option) -> Result { + let port = if let Some(port) = port { + port + } else { + list_local_devices()?[0].port.clone() + }; + let mut sc64 = SC64 { + link: link::new_local(&port)?, + }; + sc64.check_device()?; + Ok(sc64) +} + +pub fn new_remote(address: String) -> Result { + let mut sc64 = SC64 { + link: link::new_remote(&address)?, + }; + sc64.check_device()?; + Ok(sc64) +} + +pub fn run_server( + port: Option, + address: String, + event_callback: fn(ServerEvent), +) -> Result<(), Error> { + let port = if let Some(port) = port { + port + } else { + list_local_devices()?[0].port.clone() + }; + link::run_server(&port, address, event_callback) +} diff --git a/sw/deployer/src/sc64/types.rs b/sw/deployer/src/sc64/types.rs new file mode 100644 index 0000000..2b9e625 --- /dev/null +++ b/sw/deployer/src/sc64/types.rs @@ -0,0 +1,856 @@ +use super::{link::Packet, Error}; +use encoding_rs::EUC_JP; +use std::fmt::Display; + +#[derive(Clone, Copy)] +pub enum ConfigId { + BootloaderSwitch, + RomWriteEnable, + RomShadowEnable, + DdMode, + IsvAddress, + BootMode, + SaveType, + CicSeed, + TvType, + DdSdEnable, + DdDriveType, + DdDiskState, + ButtonState, + ButtonMode, + RomExtendedEnable, +} + +pub enum Config { + BootloaderSwitch(Switch), + RomWriteEnable(Switch), + RomShadowEnable(Switch), + DdMode(DdMode), + IsvAddress(u32), + BootMode(BootMode), + SaveType(SaveType), + CicSeed(CicSeed), + TvType(TvType), + DdSdEnable(Switch), + DdDriveType(DdDriveType), + DdDiskState(DdDiskState), + ButtonState(ButtonState), + ButtonMode(ButtonMode), + RomExtendedEnable(Switch), +} + +impl From for u32 { + fn from(value: ConfigId) -> Self { + match value { + ConfigId::BootloaderSwitch => 0, + ConfigId::RomWriteEnable => 1, + ConfigId::RomShadowEnable => 2, + ConfigId::DdMode => 3, + ConfigId::IsvAddress => 4, + ConfigId::BootMode => 5, + ConfigId::SaveType => 6, + ConfigId::CicSeed => 7, + ConfigId::TvType => 8, + ConfigId::DdSdEnable => 9, + ConfigId::DdDriveType => 10, + ConfigId::DdDiskState => 11, + ConfigId::ButtonState => 12, + ConfigId::ButtonMode => 13, + ConfigId::RomExtendedEnable => 14, + } + } +} + +impl TryFrom<(ConfigId, u32)> for Config { + type Error = Error; + fn try_from(value: (ConfigId, u32)) -> Result { + let (id, config) = value; + Ok(match id { + ConfigId::BootloaderSwitch => Self::BootloaderSwitch(config.try_into()?), + ConfigId::RomWriteEnable => Self::RomWriteEnable(config.try_into()?), + ConfigId::RomShadowEnable => Self::RomShadowEnable(config.try_into()?), + ConfigId::DdMode => Self::DdMode(config.try_into()?), + ConfigId::IsvAddress => Self::IsvAddress(config), + ConfigId::BootMode => Self::BootMode(config.try_into()?), + ConfigId::SaveType => Self::SaveType(config.try_into()?), + ConfigId::CicSeed => Self::CicSeed(config.try_into()?), + ConfigId::TvType => Self::TvType(config.try_into()?), + ConfigId::DdSdEnable => Self::DdSdEnable(config.try_into()?), + ConfigId::DdDriveType => Self::DdDriveType(config.try_into()?), + ConfigId::DdDiskState => Self::DdDiskState(config.try_into()?), + ConfigId::ButtonState => Self::ButtonState(config.try_into()?), + ConfigId::ButtonMode => Self::ButtonMode(config.try_into()?), + ConfigId::RomExtendedEnable => Self::RomExtendedEnable(config.try_into()?), + }) + } +} + +impl From for [u32; 2] { + fn from(value: Config) -> Self { + match value { + Config::BootloaderSwitch(val) => [ConfigId::BootloaderSwitch.into(), val.into()], + Config::RomWriteEnable(val) => [ConfigId::RomWriteEnable.into(), val.into()], + Config::RomShadowEnable(val) => [ConfigId::RomShadowEnable.into(), val.into()], + Config::DdMode(val) => [ConfigId::DdMode.into(), val.into()], + Config::IsvAddress(val) => [ConfigId::IsvAddress.into(), val.into()], + Config::BootMode(val) => [ConfigId::BootMode.into(), val.into()], + Config::SaveType(val) => [ConfigId::SaveType.into(), val.into()], + Config::CicSeed(val) => [ConfigId::CicSeed.into(), val.into()], + Config::TvType(val) => [ConfigId::TvType.into(), val.into()], + Config::DdSdEnable(val) => [ConfigId::DdSdEnable.into(), val.into()], + Config::DdDriveType(val) => [ConfigId::DdDriveType.into(), val.into()], + Config::DdDiskState(val) => [ConfigId::DdDiskState.into(), val.into()], + Config::ButtonState(val) => [ConfigId::ButtonState.into(), val.into()], + Config::ButtonMode(val) => [ConfigId::ButtonMode.into(), val.into()], + Config::RomExtendedEnable(val) => [ConfigId::RomExtendedEnable.into(), val.into()], + } + } +} + +pub enum Switch { + Off, + On, +} + +impl Display for Switch { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + Switch::Off => "Disabled", + Switch::On => "Enabled", + }) + } +} + +impl TryFrom for Switch { + type Error = Error; + fn try_from(value: u32) -> Result { + Ok(match value { + 0 => Self::Off, + _ => Self::On, + }) + } +} + +impl From for u32 { + fn from(value: Switch) -> Self { + match value { + Switch::Off => 0, + Switch::On => 1, + } + } +} + +impl From for Switch { + fn from(value: bool) -> Self { + match value { + false => Self::Off, + true => Self::On, + } + } +} + +impl From for bool { + fn from(value: Switch) -> Self { + match value { + Switch::Off => false, + Switch::On => true, + } + } +} + +pub enum DdMode { + None, + Regs, + DdIpl, + Full, +} + +impl Display for DdMode { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + DdMode::None => "Disabled", + DdMode::Regs => "Only registers", + DdMode::DdIpl => "Only 64DD IPL", + DdMode::Full => "Registers + 64DD IPL", + }) + } +} + +impl TryFrom for DdMode { + type Error = Error; + fn try_from(value: u32) -> Result { + Ok(match value { + 0 => Self::None, + 1 => Self::Regs, + 2 => Self::DdIpl, + 3 => Self::Full, + _ => return Err(Error::new("Unknown 64DD mode code")), + }) + } +} + +impl From for u32 { + fn from(value: DdMode) -> Self { + match value { + DdMode::None => 0, + DdMode::Regs => 1, + DdMode::DdIpl => 2, + DdMode::Full => 3, + } + } +} + +pub enum BootMode { + Menu, + Rom, + DdIpl, + DirectRom, + DirectDdIpl, +} + +impl Display for BootMode { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + Self::Menu => "Bootloader -> Menu from SD card", + Self::Rom => "Bootloader -> ROM", + Self::DdIpl => "Bootloader -> 64DD IPL", + Self::DirectRom => "ROM (direct)", + Self::DirectDdIpl => "64DD IPL (direct)", + }) + } +} + +impl TryFrom for BootMode { + type Error = Error; + fn try_from(value: u32) -> Result { + Ok(match value { + 0 => Self::Menu, + 1 => Self::Rom, + 2 => Self::DdIpl, + 3 => Self::DirectRom, + 4 => Self::DirectDdIpl, + _ => return Err(Error::new("Unknown boot mode code")), + }) + } +} + +impl From for u32 { + fn from(value: BootMode) -> Self { + match value { + BootMode::Menu => 0, + BootMode::Rom => 1, + BootMode::DdIpl => 2, + BootMode::DirectRom => 3, + BootMode::DirectDdIpl => 4, + } + } +} + +pub enum SaveType { + None, + Eeprom4k, + Eeprom16k, + Sram, + Flashram, + SramBanked, +} + +impl Display for SaveType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + Self::None => "None", + Self::Eeprom4k => "EEPROM 4k", + Self::Eeprom16k => "EEPROM 16k", + Self::Sram => "SRAM", + Self::SramBanked => "SRAM banked", + Self::Flashram => "FlashRAM", + }) + } +} + +impl TryFrom for SaveType { + type Error = Error; + fn try_from(value: u32) -> Result { + Ok(match value { + 0 => Self::None, + 1 => Self::Eeprom4k, + 2 => Self::Eeprom16k, + 3 => Self::Sram, + 4 => Self::Flashram, + 5 => Self::SramBanked, + _ => return Err(Error::new("Unknown save type code")), + }) + } +} + +impl From for u32 { + fn from(value: SaveType) -> Self { + match value { + SaveType::None => 0, + SaveType::Eeprom4k => 1, + SaveType::Eeprom16k => 2, + SaveType::Sram => 3, + SaveType::Flashram => 4, + SaveType::SramBanked => 5, + } + } +} + +pub enum CicSeed { + Seed(u8), + Auto, +} + +impl Display for CicSeed { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if let CicSeed::Seed(seed) = self { + f.write_fmt(format_args!("0x{seed:02X}")) + } else { + f.write_str("Auto") + } + } +} + +impl TryFrom for CicSeed { + type Error = Error; + fn try_from(value: u32) -> Result { + Ok(if value <= 0xFF { + Self::Seed(value as u8) + } else if value == 0xFFFF { + Self::Auto + } else { + return Err(Error::new("Unknown CIC seed code")); + }) + } +} + +impl From for u32 { + fn from(value: CicSeed) -> Self { + match value { + CicSeed::Seed(seed) => seed.into(), + CicSeed::Auto => 0xFFFF, + } + } +} + +pub enum TvType { + PAL, + NTSC, + MPAL, + Auto, +} + +impl Display for TvType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + Self::PAL => "PAL", + Self::NTSC => "NTSC", + Self::MPAL => "MPAL", + Self::Auto => "Auto", + }) + } +} + +impl TryFrom for TvType { + type Error = Error; + fn try_from(value: u32) -> Result { + Ok(match value { + 0 => Self::PAL, + 1 => Self::NTSC, + 2 => Self::MPAL, + 3 => Self::Auto, + _ => return Err(Error::new("Unknown TV type code")), + }) + } +} + +impl From for u32 { + fn from(value: TvType) -> Self { + match value { + TvType::PAL => 0, + TvType::NTSC => 1, + TvType::MPAL => 2, + TvType::Auto => 3, + } + } +} + +pub enum DdDriveType { + Retail, + Development, +} + +impl Display for DdDriveType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + DdDriveType::Retail => "Retail", + DdDriveType::Development => "Development", + }) + } +} + +impl TryFrom for DdDriveType { + type Error = Error; + fn try_from(value: u32) -> Result { + Ok(match value { + 0 => Self::Retail, + 1 => Self::Development, + _ => return Err(Error::new("Unknown 64DD drive type code")), + }) + } +} + +impl From for u32 { + fn from(value: DdDriveType) -> Self { + match value { + DdDriveType::Retail => 0, + DdDriveType::Development => 1, + } + } +} + +pub enum DdDiskState { + Ejected, + Inserted, + Changed, +} + +impl Display for DdDiskState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + DdDiskState::Ejected => "Ejected", + DdDiskState::Inserted => "Inserted", + DdDiskState::Changed => "Changed", + }) + } +} + +impl TryFrom for DdDiskState { + type Error = Error; + fn try_from(value: u32) -> Result { + Ok(match value { + 0 => Self::Ejected, + 1 => Self::Inserted, + 2 => Self::Changed, + _ => return Err(Error::new("Unknown 64DD disk state code")), + }) + } +} + +impl From for u32 { + fn from(value: DdDiskState) -> Self { + match value { + DdDiskState::Ejected => 0, + DdDiskState::Inserted => 1, + DdDiskState::Changed => 2, + } + } +} + +pub enum ButtonState { + NotPressed, + Pressed, +} + +impl Display for ButtonState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + ButtonState::NotPressed => "Not pressed", + ButtonState::Pressed => "Pressed", + }) + } +} + +impl TryFrom for ButtonState { + type Error = Error; + fn try_from(value: u32) -> Result { + Ok(match value { + 0 => Self::NotPressed, + _ => Self::Pressed, + }) + } +} + +impl From for u32 { + fn from(value: ButtonState) -> Self { + match value { + ButtonState::NotPressed => 0, + ButtonState::Pressed => 1, + } + } +} + +impl From for ButtonState { + fn from(value: bool) -> Self { + match value { + false => Self::NotPressed, + true => Self::Pressed, + } + } +} + +impl From for bool { + fn from(value: ButtonState) -> Self { + match value { + ButtonState::NotPressed => false, + ButtonState::Pressed => true, + } + } +} + +pub enum ButtonMode { + None, + N64Irq, + UsbPacket, + DdDiskSwap, +} + +impl Display for ButtonMode { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + ButtonMode::None => "User", + ButtonMode::N64Irq => "N64 IRQ trigger", + ButtonMode::UsbPacket => "Send USB packet", + ButtonMode::DdDiskSwap => "Swap 64DD disk", + }) + } +} + +impl TryFrom for ButtonMode { + type Error = Error; + fn try_from(value: u32) -> Result { + Ok(match value { + 0 => Self::None, + 1 => Self::N64Irq, + 2 => Self::UsbPacket, + 3 => Self::DdDiskSwap, + _ => return Err(Error::new("Unknown button mode code")), + }) + } +} + +impl From for u32 { + fn from(value: ButtonMode) -> Self { + match value { + ButtonMode::None => 0, + ButtonMode::N64Irq => 1, + ButtonMode::UsbPacket => 2, + ButtonMode::DdDiskSwap => 3, + } + } +} + +#[derive(Clone, Copy)] +pub enum SettingId { + LedEnable, +} + +pub enum Setting { + LedEnable(Switch), +} + +impl From for u32 { + fn from(value: SettingId) -> Self { + match value { + SettingId::LedEnable => 0, + } + } +} + +impl TryFrom<(SettingId, u32)> for Setting { + type Error = Error; + fn try_from(value: (SettingId, u32)) -> Result { + let (id, setting) = value; + Ok(match id { + SettingId::LedEnable => Self::LedEnable(setting.try_into()?), + }) + } +} + +impl From for [u32; 2] { + fn from(value: Setting) -> Self { + match value { + Setting::LedEnable(val) => [SettingId::LedEnable.into(), val.into()], + } + } +} + +pub enum DataPacket { + Button, + Debug(DebugPacket), + Disk(DiskPacket), + IsViewer(String), + UpdateStatus(UpdateStatus), +} + +impl TryFrom for DataPacket { + type Error = Error; + fn try_from(value: Packet) -> Result { + Ok(match value.id { + b'B' => Self::Button, + b'U' => Self::Debug(value.data.try_into()?), + b'D' => Self::Disk(value.data.try_into()?), + b'I' => Self::IsViewer(EUC_JP.decode(&value.data).0.into()), + b'F' => { + if value.data.len() != 4 { + return Err(Error::new( + "Incorrect data length for update status data packet", + )); + } + Self::UpdateStatus( + u32::from_be_bytes(value.data[0..4].try_into().unwrap()).try_into()?, + ) + } + _ => return Err(Error::new("Unknown data packet code")), + }) + } +} + +pub struct DebugPacket { + pub datatype: u8, + pub data: Vec, +} + +impl TryFrom> for DebugPacket { + type Error = Error; + fn try_from(value: Vec) -> Result { + if value.len() < 4 { + return Err(Error::new("Couldn't extract header from debug packet")); + } + let header = u32::from_be_bytes(value[0..4].try_into().unwrap()); + let datatype = ((header >> 24) & 0xFF) as u8; + let length = (header & 0x00FFFFFF) as usize; + let data = value[4..].to_vec(); + if data.len() != length { + return Err(Error::new("Debug packet length did not match")); + } + Ok(Self { datatype, data }) + } +} + +pub enum DiskPacketKind { + Read, + Write, +} + +pub struct DiskPacket { + pub kind: DiskPacketKind, + pub info: DiskBlock, +} + +impl TryFrom> for DiskPacket { + type Error = Error; + fn try_from(value: Vec) -> Result { + if value.len() < 12 { + return Err(Error::new("Couldn't extract block info from disk packet")); + } + let command = u32::from_be_bytes(value[0..4].try_into().unwrap()); + let address = u32::from_be_bytes(value[4..8].try_into().unwrap()); + let track_head_block = u32::from_be_bytes(value[8..12].try_into().unwrap()); + let disk_block = DiskBlock { + address, + track: (track_head_block >> 2) & 0xFFF, + head: (track_head_block >> 1) & 0x01, + block: track_head_block & 0x01, + data: value[12..].to_vec(), + }; + Ok(match command { + 1 => DiskPacket { + kind: DiskPacketKind::Read, + info: disk_block, + }, + 2 => DiskPacket { + kind: DiskPacketKind::Write, + info: disk_block, + }, + _ => return Err(Error::new("Unknown disk packet command code")), + }) + } +} + +pub struct DiskBlock { + pub address: u32, + pub track: u32, + pub head: u32, + pub block: u32, + pub data: Vec, +} + +impl DiskBlock { + pub fn set_data(&mut self, data: &[u8]) { + self.data = data.to_vec(); + } +} + +pub enum FirmwareStatus { + Ok, + ErrToken, + ErrChecksum, + ErrSize, + ErrUnknownChunk, + ErrRead, + ErrAddress, +} + +impl Display for FirmwareStatus { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + FirmwareStatus::Ok => "OK", + FirmwareStatus::ErrToken => "Invalid firmware header", + FirmwareStatus::ErrChecksum => "Invalid chunk checksum", + FirmwareStatus::ErrSize => "Invalid chunk size", + FirmwareStatus::ErrUnknownChunk => "Unknown chunk in firmware", + FirmwareStatus::ErrRead => "Firmware read error", + FirmwareStatus::ErrAddress => "Invalid address or length provided", + }) + } +} + +impl TryFrom for FirmwareStatus { + type Error = Error; + fn try_from(value: u32) -> Result { + Ok(match value { + 0 => Self::Ok, + 1 => Self::ErrToken, + 2 => Self::ErrChecksum, + 3 => Self::ErrSize, + 4 => Self::ErrUnknownChunk, + 5 => Self::ErrRead, + 6 => Self::ErrAddress, + _ => return Err(Error::new("Unknown firmware status code")), + }) + } +} + +pub enum UpdateStatus { + MCU, + FPGA, + Bootloader, + Done, + Err, +} + +impl Display for UpdateStatus { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + UpdateStatus::MCU => "Microcontroller", + UpdateStatus::FPGA => "FPGA", + UpdateStatus::Bootloader => "Bootloader", + UpdateStatus::Done => "Done", + UpdateStatus::Err => "Error", + }) + } +} + +impl TryFrom for UpdateStatus { + type Error = Error; + fn try_from(value: u32) -> Result { + Ok(match value { + 1 => Self::MCU, + 2 => Self::FPGA, + 3 => Self::Bootloader, + 0x80 => Self::Done, + 0xFF => Self::Err, + _ => return Err(Error::new("Unknown update status code")), + }) + } +} + +pub struct FpgaDebugData { + pub last_pi_address: u32, + pub read_fifo_wait: bool, + pub read_fifo_failure: bool, + pub write_fifo_wait: bool, + pub write_fifo_failure: bool, +} + +impl TryFrom> for FpgaDebugData { + type Error = Error; + fn try_from(value: Vec) -> Result { + if value.len() != 8 { + return Err(Error::new("Invalid data length for FPGA debug data")); + } + Ok(FpgaDebugData { + last_pi_address: u32::from_be_bytes(value[0..4].try_into().unwrap()), + read_fifo_wait: (value[7] & (1 << 0)) != 0, + read_fifo_failure: (value[7] & (1 << 1)) != 0, + write_fifo_wait: (value[7] & (1 << 2)) != 0, + write_fifo_failure: (value[7] & (1 << 3)) != 0, + }) + } +} + +impl Display for FpgaDebugData { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_fmt(format_args!("PI address: 0x{:08X}", self.last_pi_address))?; + if self.read_fifo_wait { + f.write_str(" RW")?; + } + if self.read_fifo_failure { + f.write_str(" RF")?; + } + if self.write_fifo_wait { + f.write_str(" WW")?; + } + if self.write_fifo_failure { + f.write_str(" WF")?; + } + Ok(()) + } +} + +pub struct McuStackUsage { + pub cic: u32, + pub rtc: u32, + pub led: u32, + pub gvr: u32, +} + +impl TryFrom> for McuStackUsage { + type Error = Error; + fn try_from(value: Vec) -> Result { + if value.len() != 16 { + return Err(Error::new("Invalid data length for MCU stack usage")); + } + Ok(McuStackUsage { + cic: u32::from_be_bytes(value[0..4].try_into().unwrap()), + rtc: u32::from_be_bytes(value[4..8].try_into().unwrap()), + led: u32::from_be_bytes(value[8..12].try_into().unwrap()), + gvr: u32::from_be_bytes(value[12..16].try_into().unwrap()), + }) + } +} + +impl Display for McuStackUsage { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_fmt(format_args!( + "CIC: {}, RTC: {}, LED: {}, GVR: {}", + self.cic, self.rtc, self.led, self.gvr + )) + } +} + +macro_rules! get_config { + ($sc64:ident, $config:ident) => {{ + if let Config::$config(value) = $sc64.command_config_get(ConfigId::$config)? { + Ok(value) + } else { + Err(Error::new("Unexpected config type")) + } + }}; +} + +macro_rules! get_setting { + ($sc64:ident, $setting:ident) => {{ + // Note: remove 'allow(irrefutable_let_patterns)' below when more settings are added + #[allow(irrefutable_let_patterns)] + if let Setting::$setting(value) = $sc64.command_setting_get(SettingId::$setting)? { + Ok(value) + } else { + Err(Error::new("Unexpected setting type")) + } + }}; +} + +pub(crate) use get_config; +pub(crate) use get_setting; diff --git a/sw/deployer/src/sc64/utils.rs b/sw/deployer/src/sc64/utils.rs new file mode 100644 index 0000000..5e2c36f --- /dev/null +++ b/sw/deployer/src/sc64/utils.rs @@ -0,0 +1,39 @@ +use super::Error; +use chrono::{DateTime, Datelike, Local, NaiveDateTime, TimeZone, Timelike}; + +pub fn u8_from_bcd(value: u8) -> u8 { + (((value & 0xF0) >> 4) * 10) + (value & 0x0F) +} + +pub fn bcd_from_u8(value: u8) -> u8 { + (((value / 10) & 0x0F) << 4) | ((value % 10) & 0x0F) +} + +pub fn convert_to_datetime(data: &[u8; 8]) -> Result, Error> { + let hour = u8_from_bcd(data[1]); + let minute = u8_from_bcd(data[2]); + let second = u8_from_bcd(data[3]); + let year = u8_from_bcd(data[5]) as u32 + 2000; + let month = u8_from_bcd(data[6]); + let day = u8_from_bcd(data[7]); + let native = &NaiveDateTime::parse_from_str( + &format!("{year:02}-{month:02}-{day:02}T{hour:02}:{minute:02}:{second:02}"), + "%Y-%m-%dT%H:%M:%S", + ) + .map_err(|_| Error::new("Couldn't convert from bytes to DateTime"))?; + Ok(Local.from_local_datetime(native).unwrap()) +} + +pub fn convert_from_datetime(datetime: DateTime) -> [u32; 2] { + let weekday = bcd_from_u8((datetime.weekday() as u8) + 1); + let hour = bcd_from_u8(datetime.hour() as u8); + let minute = bcd_from_u8(datetime.minute() as u8); + let second = bcd_from_u8(datetime.second() as u8); + let year = bcd_from_u8((datetime.year() - 2000) as u8); + let month = bcd_from_u8(datetime.month() as u8); + let day = bcd_from_u8(datetime.day() as u8); + [ + u32::from_be_bytes([weekday, hour, minute, second]), + u32::from_be_bytes([0, year, month, day]), + ] +} diff --git a/sw/pc/.gitignore b/sw/pc/.gitignore deleted file mode 100644 index 0ad4956..0000000 --- a/sw/pc/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -/__pycache__ -/build -/dist -*.bin -*.eep -*.fla -*.n64 -*.spec -*.srm -*.v64 -*.z64 diff --git a/sw/pc/sc64.py b/sw/pc/sc64.py deleted file mode 100755 index adc091d..0000000 --- a/sw/pc/sc64.py +++ /dev/null @@ -1,1422 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import os -import queue -import serial -import socket -import sys -import time -from binascii import crc32 -from datetime import datetime -from enum import Enum, IntEnum -from io import BufferedReader -from serial.tools import list_ports -from threading import Thread -from typing import Callable, Optional -from PIL import Image - - - -class BadBlockError(Exception): - pass - - -class DD64Image: - __DISK_HEADS = 2 - __DISK_TRACKS = 1175 - __DISK_BLOCKS_PER_TRACK = 2 - __DISK_SECTORS_PER_BLOCK = 85 - __DISK_BAD_TRACKS_PER_ZONE = 12 - __DISK_SYSTEM_SECTOR_SIZE = 232 - __DISK_ZONES = [ - (0, 232, 158, 0), - (0, 216, 158, 158), - (0, 208, 149, 316), - (0, 192, 149, 465), - (0, 176, 149, 614), - (0, 160, 149, 763), - (0, 144, 149, 912), - (0, 128, 114, 1061), - (1, 216, 158, 157), - (1, 208, 158, 315), - (1, 192, 149, 464), - (1, 176, 149, 613), - (1, 160, 149, 762), - (1, 144, 149, 911), - (1, 128, 149, 1060), - (1, 112, 114, 1174), - ] - __DISK_VZONE_TO_PZONE = [ - [0, 1, 2, 9, 8, 3, 4, 5, 6, 7, 15, 14, 13, 12, 11, 10], - [0, 1, 2, 3, 10, 9, 8, 4, 5, 6, 7, 15, 14, 13, 12, 11], - [0, 1, 2, 3, 4, 11, 10, 9, 8, 5, 6, 7, 15, 14, 13, 12], - [0, 1, 2, 3, 4, 5, 12, 11, 10, 9, 8, 6, 7, 15, 14, 13], - [0, 1, 2, 3, 4, 5, 6, 13, 12, 11, 10, 9, 8, 7, 15, 14], - [0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8, 15], - [0, 1, 2, 3, 4, 5, 6, 7, 15, 14, 13, 12, 11, 10, 9, 8], - ] - __DISK_DRIVE_TYPES = [( - 'development', - 192, - [11, 10, 3, 2], - [0, 1, 8, 9, 16, 17, 18, 19, 20, 21, 22, 23], - ), ( - 'retail', - 232, - [9, 8, 1, 0], - [2, 3, 10, 11, 12, 16, 17, 18, 19, 20, 21, 22, 23], - )] - - __file: Optional[BufferedReader] - __drive_type: Optional[str] - __block_info_table: list[tuple[int, int]] - loaded: bool = False - - def __init__(self) -> None: - self.__file = None - self.__drive_type = None - block_info_table_length = self.__DISK_HEADS * self.__DISK_TRACKS * self.__DISK_BLOCKS_PER_TRACK - self.__block_info_table = [None] * block_info_table_length - - def __del__(self) -> None: - self.unload() - - def __check_system_block(self, lba: int, sector_size: int, check_disk_type: bool) -> tuple[bool, bytes]: - self.__file.seek(lba * self.__DISK_SYSTEM_SECTOR_SIZE * self.__DISK_SECTORS_PER_BLOCK) - system_block_data = self.__file.read(sector_size * self.__DISK_SECTORS_PER_BLOCK) - system_data = system_block_data[:sector_size] - for sector in range(1, self.__DISK_SECTORS_PER_BLOCK): - sector_data = system_block_data[(sector * sector_size):][:sector_size] - if (system_data != sector_data): - return (False, None) - if (check_disk_type): - if (system_data[4] != 0x10): - return (False, None) - if ((system_data[5] & 0xF0) != 0x10): - return (False, None) - return (True, system_data) - - def __parse_disk(self) -> None: - disk_system_data = None - disk_id_data = None - disk_bad_lbas = [] - - drive_index = 0 - while (disk_system_data == None) and (drive_index < len(self.__DISK_DRIVE_TYPES)): - (drive_type, system_sector_size, system_data_lbas, bad_lbas) = self.__DISK_DRIVE_TYPES[drive_index] - disk_bad_lbas.clear() - disk_bad_lbas.extend(bad_lbas) - for system_lba in system_data_lbas: - (valid, system_data) = self.__check_system_block(system_lba, system_sector_size, check_disk_type=True) - if (valid): - self.__drive_type = drive_type - disk_system_data = system_data - else: - disk_bad_lbas.append(system_lba) - drive_index += 1 - - for id_lba in [15, 14]: - (valid, id_data) = self.__check_system_block(id_lba, self.__DISK_SYSTEM_SECTOR_SIZE, check_disk_type=False) - if (valid): - disk_id_data = id_data - else: - disk_bad_lbas.append(id_lba) - - if not (disk_system_data and disk_id_data): - raise ValueError('Provided 64DD disk file is not valid') - - disk_zone_bad_tracks = [] - - for zone in range(len(self.__DISK_ZONES)): - zone_bad_tracks = [] - start = 0 if zone == 0 else system_data[0x07 + zone] - stop = system_data[0x07 + zone + 1] - for offset in range(start, stop): - zone_bad_tracks.append(system_data[0x20 + offset]) - for ignored_track in range(self.__DISK_BAD_TRACKS_PER_ZONE - len(zone_bad_tracks)): - zone_bad_tracks.append(self.__DISK_ZONES[zone][2] - ignored_track - 1) - disk_zone_bad_tracks.append(zone_bad_tracks) - - disk_type = disk_system_data[5] & 0x0F - - current_lba = 0 - starting_block = 0 - disk_file_offset = 0 - - for zone in self.__DISK_VZONE_TO_PZONE[disk_type]: - (head, sector_size, tracks, track) = self.__DISK_ZONES[zone] - - for zone_track in range(tracks): - current_zone_track = ( - (tracks - 1) - zone_track) if head else zone_track - - if (current_zone_track in disk_zone_bad_tracks[zone]): - track += (-1) if head else 1 - continue - - for block in range(self.__DISK_BLOCKS_PER_TRACK): - index = (track << 2) | (head << 1) | (starting_block ^ block) - if (current_lba not in disk_bad_lbas): - self.__block_info_table[index] = (disk_file_offset, sector_size * self.__DISK_SECTORS_PER_BLOCK) - else: - self.__block_info_table[index] = None - disk_file_offset += sector_size * self.__DISK_SECTORS_PER_BLOCK - current_lba += 1 - - track += (-1) if head else 1 - starting_block ^= 1 - - def __check_track_head_block(self, track: int, head: int, block: int) -> None: - if (track < 0 or track >= self.__DISK_TRACKS): - raise ValueError('Track outside of possible range') - if (head < 0 or head >= self.__DISK_HEADS): - raise ValueError('Head outside of possible range') - if (block < 0 or block >= self.__DISK_BLOCKS_PER_TRACK): - raise ValueError('Block outside of possible range') - - def __get_table_index(self, track: int, head: int, block: int) -> int: - return (track << 2) | (head << 1) | (block) - - def __get_block_info(self, track: int, head: int, block: int) -> Optional[tuple[int, int]]: - if (self.__file.closed): - return None - self.__check_track_head_block(track, head, block) - index = self.__get_table_index(track, head, block) - return self.__block_info_table[index] - - def load(self, path: str) -> None: - self.unload() - self.__file = open(path, 'rb+') - self.__parse_disk() - self.loaded = True - - def unload(self) -> None: - self.loaded = False - if (self.__file != None and not self.__file.closed): - self.__file.close() - self.__drive_type = None - - def get_block_info_table(self) -> list[tuple[int, int]]: - return self.__block_info_table - - def get_drive_type(self) -> str: - return self.__drive_type - - def read_block(self, track: int, head: int, block: int) -> bytes: - info = self.__get_block_info(track, head, block) - if (info == None): - raise BadBlockError - (offset, block_size) = info - self.__file.seek(offset) - return self.__file.read(block_size) - - def write_block(self, track: int, head: int, block: int, data: bytes) -> None: - info = self.__get_block_info(track, head, block) - if (info == None): - raise BadBlockError - (offset, block_size) = info - if (len(data) != block_size): - raise ValueError(f'Provided data block size is different than expected ({len(data)} != {block_size})') - self.__file.seek(offset) - self.__file.write(data) - - -class ConnectionException(Exception): - pass - - -class SC64Serial: - __disconnect = False - __serial: Optional[serial.Serial] = None - __thread_read = None - __thread_write = None - __queue_output = queue.Queue() - __queue_input = queue.Queue() - __queue_packet = queue.Queue() - - __VID = 0x0403 - __PID = 0x6014 - - __CHUNK_SIZE = (64 * 1024) - - def __init__(self) -> None: - ports = list_ports.comports() - device_found = False - - if (self.__serial != None and self.__serial.is_open): - raise ConnectionException('Serial port is already open') - - for p in ports: - if (p.vid == self.__VID and p.pid == self.__PID and p.serial_number.startswith('SC64')): - try: - self.__serial = serial.Serial(p.device, timeout=1.0, write_timeout=1.0) - self.__reset_link() - except (serial.SerialException, ConnectionException): - if (self.__serial): - self.__serial.close() - continue - device_found = True - break - - if (not device_found): - raise ConnectionException('No SC64 device was found') - - self.__thread_read = Thread(target=self.__serial_process_input, daemon=True) - self.__thread_write = Thread(target=self.__serial_process_output, daemon=True) - - self.__thread_read.start() - self.__thread_write.start() - - def __del__(self) -> None: - self.__disconnect = True - if (self.__thread_read != None and self.__thread_read.is_alive()): - self.__thread_read.join(1) - if (self.__thread_write != None and self.__thread_write.is_alive()): - self.__thread_write.join(1) - if (self.__serial != None and self.__serial.is_open): - self.__serial.close() - - def __reset_link(self) -> None: - self.__serial.reset_output_buffer() - - retry_counter = 0 - self.__serial.dtr = 1 - while (self.__serial.dsr == 0): - time.sleep(0.1) - retry_counter += 1 - if (retry_counter >= 10): - raise ConnectionException('Could not reset SC64 device') - - self.__serial.reset_input_buffer() - - retry_counter = 0 - self.__serial.dtr = 0 - while (self.__serial.dsr == 1): - time.sleep(0.1) - retry_counter += 1 - if (retry_counter >= 10): - raise ConnectionException('Could not reset SC64 device') - - def __write(self, data: bytes) -> None: - try: - if (self.__disconnect): - raise ConnectionException - for offset in range(0, len(data), self.__CHUNK_SIZE): - self.__serial.write(data[offset:offset + self.__CHUNK_SIZE]) - self.__serial.flush() - except (serial.SerialException, serial.SerialTimeoutException): - raise ConnectionException - - def __read(self, length: int) -> bytes: - try: - data = b'' - while (len(data) < length and not self.__disconnect): - data += self.__serial.read(length - len(data)) - if (self.__disconnect): - raise ConnectionException - return data - except serial.SerialException: - raise ConnectionException - - def __read_int(self) -> int: - return int.from_bytes(self.__read(4), byteorder='big') - - def __serial_process_output(self) -> None: - while (not self.__disconnect and self.__serial != None and self.__serial.is_open): - try: - packet: bytes = self.__queue_output.get(timeout=0.1) - self.__write(packet) - self.__queue_output.task_done() - except queue.Empty: - continue - except ConnectionException: - break - - def __serial_process_input(self) -> None: - while (not self.__disconnect and self.__serial != None and self.__serial.is_open): - try: - token = self.__read(4) - if (len(token) == 4): - identifier = token[0:3] - command = token[3:4] - if (identifier == b'PKT'): - data = self.__read(self.__read_int()) - self.__queue_packet.put((command, data)) - elif (identifier == b'CMP' or identifier == b'ERR'): - data = self.__read(self.__read_int()) - success = identifier == b'CMP' - self.__queue_input.put((command, data, success)) - else: - raise ConnectionException - except ConnectionException: - break - - def __check_threads(self) -> None: - if (not (self.__thread_write.is_alive() and self.__thread_read.is_alive())): - raise ConnectionException('Serial link is closed') - - def __queue_cmd(self, cmd: bytes, args: list[int]=[0, 0], data: bytes=b'') -> None: - if (len(cmd) != 1): - raise ValueError('Length of command is different than 1 byte') - if (len(args) != 2): - raise ValueError('Number of arguments is different than 2') - packet: bytes = b'CMD' - packet += cmd[0:1] - for arg in args: - packet += arg.to_bytes(4, byteorder='big') - packet += data - self.__queue_output.put(packet) - - def __pop_response(self, cmd: bytes, timeout: float, raise_on_err: bool) -> bytes: - try: - (response_cmd, data, success) = self.__queue_input.get(timeout=timeout) - self.__queue_input.task_done() - if (cmd != response_cmd): - raise ConnectionException('CMD wrong command response') - if (raise_on_err and success == False): - raise ConnectionException('CMD response error') - return data - except queue.Empty: - raise ConnectionException('CMD response timeout') - - def execute_cmd(self, cmd: bytes, args: list[int]=[0, 0], data: bytes=b'', response: bool=True, timeout: float=5.0, raise_on_err: bool=True) -> Optional[bytes]: - self.__check_threads() - self.__queue_cmd(cmd, args, data) - if (response): - return self.__pop_response(cmd, timeout, raise_on_err) - return None - - def get_packet(self, timeout: float=0.1) -> Optional[tuple[bytes, bytes]]: - self.__check_threads() - try: - packet = self.__queue_packet.get(timeout=timeout) - self.__queue_packet.task_done() - return packet - except queue.Empty: - return None - - -class SC64: - class __Address(IntEnum): - MEMORY = 0x0000_0000 - SDRAM = 0x0000_0000 - FLASH = 0x0400_0000 - BUFFER = 0x0500_0000 - EEPROM = 0x0500_2000 - END = 0x0500_297F - FIRMWARE = 0x0200_0000 - DDIPL = 0x03BC_0000 - SAVE = 0x03FE_0000 - EXTENDED = 0x0400_0000 - BOOTLOADER = 0x04E0_0000 - SHADOW = 0x04FE_0000 - - class __Length(IntEnum): - MEMORY = 0x0500_2980 - SDRAM = (64 * 1024 * 1024) - FLASH = (16 * 1024 * 1024) - BUFFER = (8 * 1024) - EEPROM = (2 * 1024) - DDIPL = (4 * 1024 * 1024) - SAVE = (128 * 1024) - EXTENDED = (14 * 1024 * 1024) - BOOTLOADER = (1920 * 1024) - SHADOW = (128 * 1024) - - class __SaveLength(IntEnum): - NONE = 0 - EEPROM_4K = 512 - EEPROM_16K = (2 * 1024) - SRAM = (32 * 1024) - FLASHRAM = (128 * 1024) - SRAM_BANKED = (3 * 32 * 1024) - - class __CfgId(IntEnum): - BOOTLOADER_SWITCH = 0 - ROM_WRITE_ENABLE = 1 - ROM_SHADOW_ENABLE = 2 - DD_MODE = 3 - ISV_ADDRESS = 4 - BOOT_MODE = 5 - SAVE_TYPE = 6 - CIC_SEED = 7 - TV_TYPE = 8 - DD_SD_ENABLE = 9 - DD_DRIVE_TYPE = 10 - DD_DISK_STATE = 11 - BUTTON_STATE = 12 - BUTTON_MODE = 13 - ROM_EXTENDED_ENABLE = 14 - - class __SettingId(IntEnum): - LED_ENABLE = 0 - - class __UpdateError(IntEnum): - OK = 0 - TOKEN = 1 - CHECKSUM = 2 - SIZE = 3 - UNKNOWN_CHUNK = 4 - READ = 5 - - class __UpdateStatus(IntEnum): - MCU = 1 - FPGA = 2 - BOOTLOADER = 3 - DONE = 0x80 - ERROR = 0xFF - - class __DDMode(IntEnum): - NONE = 0 - REGS = 1 - DDIPL = 2 - FULL = 3 - - class __DDDriveType(IntEnum): - RETAIL = 0 - DEVELOPMENT = 1 - - class __DDDiskState(IntEnum): - EJECTED = 0 - INSERTED = 1 - CHANGED = 2 - - class __ButtonMode(IntEnum): - NONE = 0 - N64_IRQ = 1 - USB_PACKET = 2 - DD_DISK_SWAP = 3 - - class BootMode(IntEnum): - MENU = 0 - ROM = 1 - DDIPL = 2 - DIRECT_ROM = 3 - DIRECT_DDIPL = 4 - - class SaveType(IntEnum): - NONE = 0 - EEPROM_4K = 1 - EEPROM_16K = 2 - SRAM = 3 - FLASHRAM = 4 - SRAM_BANKED = 5 - - class CICSeed(IntEnum): - DEFAULT = 0x3F - X103 = 0x78 - X105 = 0x91 - X106 = 0x85 - ALECK = 0xAC - DD_JP = 0xDD - DD_US = 0xDE - AUTO = 0xFFFF - - class TVType(IntEnum): - PAL = 0 - NTSC = 1 - MPAL = 2 - AUTO = 3 - - class __DebugDatatype(IntEnum): - TEXT = 1 - RAWBINARY = 2 - HEADER = 3 - SCREENSHOT = 4 - GDB = 0xDB - - __SUPPORTED_MAJOR_VERSION = 2 - __SUPPORTED_MINOR_VERSION = 12 - - __isv_line_buffer: bytes = b'' - __debug_header: Optional[bytes] = None - __gdb_client: Optional[socket.socket] = None - - def __init__(self) -> None: - self.__link = SC64Serial() - identifier = self.__link.execute_cmd(cmd=b'v') - if (identifier != b'SCv2'): - raise ConnectionException('Unknown SC64 v2 identifier') - - def __get_int(self, data: bytes) -> int: - return int.from_bytes(data[:4], byteorder='big') - - def check_firmware_version(self) -> tuple[str, bool]: - try: - version = self.__link.execute_cmd(cmd=b'V') - major = self.__get_int(version[0:2]) - minor = self.__get_int(version[2:4]) - if (major != self.__SUPPORTED_MAJOR_VERSION): - raise ConnectionException() - if (minor < self.__SUPPORTED_MINOR_VERSION): - raise ConnectionException() - return (f'{major}.{minor}', minor > self.__SUPPORTED_MINOR_VERSION) - except ConnectionException: - raise ConnectionException(f'Unsupported SC64 version [{major}.{minor}], please update firmware') - - def __set_config(self, config: __CfgId, value: int) -> None: - try: - self.__link.execute_cmd(cmd=b'C', args=[config, value]) - except ConnectionException: - raise ValueError(f'Could not set config {config.name} to {value:08X}') - - def __get_config(self, config: __CfgId) -> int: - try: - data = self.__link.execute_cmd(cmd=b'c', args=[config, 0]) - except ConnectionException: - raise ValueError(f'Could not get config {config.name}') - return self.__get_int(data) - - def __set_setting(self, setting: __SettingId, value: int) -> None: - try: - self.__link.execute_cmd(cmd=b'A', args=[setting, value]) - except ConnectionException: - raise ValueError(f'Could not set setting {setting.name} to {value:08X}') - - def __get_setting(self, setting: __SettingId) -> int: - try: - data = self.__link.execute_cmd(cmd=b'a', args=[setting, 0]) - except ConnectionException: - raise ValueError(f'Could not get setting {setting.name}') - return self.__get_int(data) - - def __write_memory(self, address: int, data: bytes) -> None: - if (len(data) > 0): - self.__link.execute_cmd(cmd=b'M', args=[address, len(data)], data=data, timeout=20.0) - - def __read_memory(self, address: int, length: int) -> bytes: - if (length > 0): - return self.__link.execute_cmd(cmd=b'm', args=[address, length], timeout=20.0) - return bytes([]) - - def __dd_set_block_ready(self, error: int) -> None: - self.__link.execute_cmd(cmd=b'D', args=[error, 0]) - - def __flash_wait_busy(self) -> None: - self.__link.execute_cmd(cmd=b'p', args=[True, 0]) - - def __flash_get_erase_block_size(self) -> int: - data = self.__link.execute_cmd(cmd=b'p', args=[False, 0]) - return self.__get_int(data[0:4]) - - def __flash_erase_block(self, address: int) -> None: - self.__link.execute_cmd(cmd=b'P', args=[address, 0]) - - def __erase_flash_region(self, address: int, length: int) -> None: - if (address < self.__Address.FLASH): - raise ValueError('Flash erase address or length outside of possible range') - if ((address + length) > (self.__Address.FLASH + self.__Length.FLASH)): - raise ValueError('Flash erase address or length outside of possible range') - erase_block_size = self.__flash_get_erase_block_size() - if (address % erase_block_size != 0): - raise ValueError('Flash erase address not aligned to block size') - for offset in range(address, address + length, erase_block_size): - self.__flash_erase_block(offset) - - def __program_flash(self, address: int, data: bytes): - program_chunk_size = (128 * 1024) - if (self.__read_memory(address, len(data)) != data): - self.__erase_flash_region(address, len(data)) - for offset in range(0, len(data), program_chunk_size): - self.__write_memory(address + offset, data[offset:offset + program_chunk_size]) - self.__flash_wait_busy() - if (self.__read_memory(address, len(data)) != data): - raise ConnectionException('Flash memory program failure') - - def autodetect_save_type(self, data: bytes) -> SaveType: - if (len(data) < 0x40): - return self.SaveType.NONE - - if (data[0x3C:0x3E] == b'ED'): - save = (data[0x3F] >> 4) & 0x0F - if (save < 0 or save > 6): - return self.SaveType.NONE - save_type_mapping = [ - self.SaveType.NONE, - self.SaveType.EEPROM_4K, - self.SaveType.EEPROM_16K, - self.SaveType.SRAM, - self.SaveType.SRAM_BANKED, - self.SaveType.FLASHRAM, - self.SaveType.SRAM, - ] - return save_type_mapping[save] - - # Original ROM database sourced from ares emulator: https://github.com/ares-emulator/ares/blob/master/mia/medium/nintendo-64.cpp - - rom_id = data[0x3B:0x3E] - region = data[0x3E] - revision = data[0x3F] - - save_type_mapping = [ - ([ - b'NTW', b'NHF', b'NOS', b'NTC', b'NER', b'NAG', b'NAB', b'NS3', b'NTN', b'NBN', b'NBK', b'NFH', - b'NMU', b'NBC', b'NBH', b'NHA', b'NBM', b'NBV', b'NBD', b'NCT', b'NCH', b'NCG', b'NP2', b'NXO', - b'NCU', b'NCX', b'NDY', b'NDQ', b'NDR', b'NN6', b'NDU', b'NJM', b'NFW', b'NF2', b'NKA', b'NFG', - b'NGL', b'NGV', b'NGE', b'NHP', b'NPG', b'NIJ', b'NIC', b'NFY', b'NKI', b'NLL', b'NLR', b'NKT', - b'CLB', b'NLB', b'NMW', b'NML', b'NTM', b'NMI', b'NMG', b'NMO', b'NMS', b'NMR', b'NCR', b'NEA', - b'NPW', b'NPY', b'NPT', b'NRA', b'NWQ', b'NSU', b'NSN', b'NK2', b'NSV', b'NFX', b'NFP', b'NS6', - b'NNA', b'NRS', b'NSW', b'NSC', b'NSA', b'NB6', b'NSS', b'NTX', b'NT6', b'NTP', b'NTJ', b'NRC', - b'NTR', b'NTB', b'NGU', b'NIR', b'NVL', b'NVY', b'NWC', b'NAD', b'NWU', b'NYK', b'NMZ', b'NSM', - b'NWR', - ], self.SaveType.EEPROM_4K), - ([ - b'NB7', b'NGT', b'NFU', b'NCW', b'NCZ', b'ND6', b'NDO', b'ND2', b'N3D', b'NMX', b'NGC', b'NIM', - b'NNB', b'NMV', b'NM8', b'NEV', b'NPP', b'NUB', b'NPD', b'NRZ', b'NR7', b'NEP', b'NYS', - ], self.SaveType.EEPROM_16K), - ([ - b'NTE', b'NVB', b'NB5', b'CFZ', b'NFZ', b'NSI', b'NG6', b'NGP', b'NYW', b'NHY', b'NIB', b'NPS', - b'NPA', b'NP4', b'NJ5', b'NP6', b'NPE', b'NJG', b'CZL', b'NZL', b'NKG', b'NMF', b'NRI', b'NUT', - b'NUM', b'NOB', b'CPS', b'NPM', b'NRE', b'NAL', b'NT3', b'NS4', b'NA2', b'NVP', b'NWL', b'NW2', - b'NWX', - ], self.SaveType.SRAM), - ([ - b'CDZ', - ], self.SaveType.SRAM_BANKED), - ([ - b'NCC', b'NDA', b'NAF', b'NJF', b'NKJ', b'NZS', b'NM6', b'NCK', b'NMQ', b'NPN', b'NPF', b'NPO', - b'CP2', b'NP3', b'NRH', b'NSQ', b'NT9', b'NW4', b'NDP', - ], self.SaveType.FLASHRAM), - ] - - for (rom_id_table, save) in save_type_mapping: - if (rom_id in rom_id_table): - return save - - special_mapping = [ - (b'NKD', b'J', None, self.SaveType.EEPROM_4K), - (b'NWT', b'J', None, self.SaveType.EEPROM_4K), - (b'ND3', b'J', None, self.SaveType.EEPROM_16K), - (b'ND4', b'J', None, self.SaveType.EEPROM_16K), - (b'N3H', b'J', None, self.SaveType.SRAM), - (b'NK4', b'J', 2, self.SaveType.SRAM), - ] - - for (special_rom_id, special_region, special_revision, save) in special_mapping: - if (rom_id != special_rom_id): - continue - if (region != special_region): - continue - if (special_revision != None and revision >= special_revision): - continue - return save - - return self.SaveType.NONE - - def reset_state(self) -> None: - self.__link.execute_cmd(cmd=b'R') - - def get_state(self): - return { - 'bootloader_switch': bool(self.__get_config(self.__CfgId.BOOTLOADER_SWITCH)), - 'rom_write_enable': bool(self.__get_config(self.__CfgId.ROM_WRITE_ENABLE)), - 'rom_shadow_enable': bool(self.__get_config(self.__CfgId.ROM_SHADOW_ENABLE)), - 'dd_mode': self.__DDMode(self.__get_config(self.__CfgId.DD_MODE)), - 'isv_address': self.__get_config(self.__CfgId.ISV_ADDRESS), - 'boot_mode': self.BootMode(self.__get_config(self.__CfgId.BOOT_MODE)), - 'save_type': self.SaveType(self.__get_config(self.__CfgId.SAVE_TYPE)), - 'cic_seed': self.CICSeed(self.__get_config(self.__CfgId.CIC_SEED)), - 'tv_type': self.TVType(self.__get_config(self.__CfgId.TV_TYPE)), - 'dd_sd_enable': bool(self.__get_config(self.__CfgId.DD_SD_ENABLE)), - 'dd_drive_type': self.__DDDriveType(self.__get_config(self.__CfgId.DD_DRIVE_TYPE)), - 'dd_disk_state': self.__DDDiskState(self.__get_config(self.__CfgId.DD_DISK_STATE)), - 'button_state': bool(self.__get_config(self.__CfgId.BUTTON_STATE)), - 'button_mode': self.__ButtonMode(self.__get_config(self.__CfgId.BUTTON_MODE)), - 'rom_extended_enable': bool(self.__get_config(self.__CfgId.ROM_EXTENDED_ENABLE)), - 'led_enable': bool(self.__get_setting(self.__SettingId.LED_ENABLE)), - } - - def debug_send(self, datatype: __DebugDatatype, data: bytes) -> None: - if (len(data) > (8 * 1024 * 1024)): - raise ValueError('Debug data size too big') - self.__link.execute_cmd(cmd=b'U', args=[datatype, len(data)], data=data, response=False) - - def download_memory(self, address: int, length: int) -> bytes: - if ((address < 0) or (length < 0) or ((address + length) > self.__Address.END)): - raise ValueError('Invalid address or length') - return self.__read_memory(address, length) - - def upload_rom(self, data: bytes, use_shadow: bool=True) -> None: - rom_length = len(data) - if (rom_length > (self.__Length.SDRAM + self.__Length.EXTENDED)): - raise ValueError('ROM size too big') - sdram_length = self.__Length.SDRAM - shadow_enabled = use_shadow and rom_length > (self.__Length.SDRAM - self.__Length.SHADOW) - extended_enabled = rom_length > self.__Length.SDRAM - if (shadow_enabled): - sdram_length = (self.__Length.SDRAM - self.__Length.SHADOW) - shadow_data = data[sdram_length:sdram_length + self.__Length.SHADOW] - self.__program_flash(self.__Address.SHADOW, shadow_data) - self.__set_config(self.__CfgId.ROM_SHADOW_ENABLE, shadow_enabled) - if (extended_enabled): - extended_data = data[self.__Length.SDRAM:] - self.__program_flash(self.__Address.EXTENDED, extended_data) - self.__set_config(self.__CfgId.ROM_EXTENDED_ENABLE, extended_enabled) - self.__write_memory(self.__Address.SDRAM, data[:sdram_length]) - - def upload_ddipl(self, data: bytes) -> None: - if (len(data) > self.__Length.DDIPL): - raise ValueError('DDIPL size too big') - self.__write_memory(self.__Address.DDIPL, data) - - def upload_save(self, data: bytes) -> None: - save_type = self.SaveType(self.__get_config(self.__CfgId.SAVE_TYPE)) - if (save_type == self.SaveType.NONE): - raise ValueError('No save type set inside SC64 device') - if (len(data) != self.__SaveLength[save_type.name]): - raise ValueError('Wrong save data length') - address = self.__Address.SAVE - if (save_type == self.SaveType.EEPROM_4K or save_type == self.SaveType.EEPROM_16K): - address = self.__Address.EEPROM - self.__write_memory(address, data) - - def download_save(self) -> bytes: - save_type = self.SaveType(self.__get_config(self.__CfgId.SAVE_TYPE)) - if (save_type == self.SaveType.NONE): - raise ValueError('No save type set inside SC64 device') - address = self.__Address.SAVE - length = self.__SaveLength[save_type.name] - if (save_type == self.SaveType.EEPROM_4K or save_type == self.SaveType.EEPROM_16K): - address = self.__Address.EEPROM - return self.__read_memory(address, length) - - def upload_bootloader(self, data: bytes) -> None: - if (len(data) > self.__Length.BOOTLOADER): - raise ValueError('Bootloader size too big') - padded_data = data + (b'\xFF' * (self.__Length.BOOTLOADER - len(data))) - if (self.__read_memory(self.__Address.BOOTLOADER, self.__Length.BOOTLOADER) != padded_data): - self.__erase_flash_region(self.__Address.BOOTLOADER, self.__Length.BOOTLOADER) - self.__write_memory(self.__Address.BOOTLOADER, data) - self.__flash_wait_busy() - if (self.__read_memory(self.__Address.BOOTLOADER, self.__Length.BOOTLOADER) != padded_data): - raise ConnectionException('Bootloader program failure') - - def set_rtc(self, t: datetime) -> None: - to_bcd = lambda v: ((int((v / 10) % 10) << 4) | int(int(v) % 10)) - data = bytes([ - to_bcd(t.weekday() + 1), - to_bcd(t.hour), - to_bcd(t.minute), - to_bcd(t.second), - 0, - to_bcd(t.year), - to_bcd(t.month), - to_bcd(t.day), - ]) - self.__link.execute_cmd(cmd=b'T', args=[self.__get_int(data[0:4]), self.__get_int(data[4:8])]) - - def set_boot_mode(self, mode: BootMode) -> None: - self.__set_config(self.__CfgId.BOOT_MODE, mode) - - def set_cic_seed(self, seed: int) -> None: - if (seed != self.CICSeed.AUTO): - if (seed < 0 or seed > 0xFF): - raise ValueError('CIC seed outside of allowed values') - self.__set_config(self.__CfgId.CIC_SEED, seed) - - def set_tv_type(self, type: TVType) -> bool: - self.__set_config(self.__CfgId.TV_TYPE, type) - boot_mode = self.__get_config(self.__CfgId.BOOT_MODE) - direct = (boot_mode == self.BootMode.DIRECT_ROM) or (boot_mode == self.BootMode.DIRECT_DDIPL) - return direct - - def set_save_type(self, type: SaveType) -> None: - self.__set_config(self.__CfgId.SAVE_TYPE, type) - - def set_led_enable(self, enabled: bool) -> None: - self.__set_setting(self.__SettingId.LED_ENABLE, enabled) - - def update_firmware(self, data: bytes, status_callback: Optional[Callable[[str], None]]=None) -> None: - address = self.__Address.FIRMWARE - self.__write_memory(address, data) - response = self.__link.execute_cmd(cmd=b'F', args=[address, len(data)], raise_on_err=False) - error = self.__UpdateError(self.__get_int(response[0:4])) - if (error != self.__UpdateError.OK): - raise ConnectionException(f'Bad update image [{error.name}]') - status = None - while status != self.__UpdateStatus.DONE: - packet = self.__link.get_packet(timeout=60.0) - if (packet == None): - raise ConnectionException('Update timeout') - (cmd, data) = packet - if (cmd != b'F'): - raise ConnectionException('Wrong update status packet') - status = self.__UpdateStatus(self.__get_int(data)) - if (status_callback): - status_callback(status.name) - if (status == self.__UpdateStatus.ERROR): - raise ConnectionException('Update error, device is most likely bricked') - time.sleep(2) - - def backup_firmware(self) -> bytes: - address = self.__Address.FIRMWARE - info = self.__link.execute_cmd(cmd=b'f', args=[address, 0], timeout=60.0, raise_on_err=False) - error = self.__UpdateError(self.__get_int(info[0:4])) - length = self.__get_int(info[4:8]) - if (error != self.__UpdateError.OK): - raise ConnectionException('Error while getting firmware backup') - return self.__read_memory(address, length) - - def update_cic_parameters(self, seed: Optional[int]=None, disabled: Optional[bool]=False) -> tuple[int, int, bool, bool]: - if ((seed != None) and (seed < 0 or seed > 0xFF)): - raise ValueError('CIC seed outside of allowed values') - boot_mode = self.__get_config(self.__CfgId.BOOT_MODE) - address = self.__Address.BOOTLOADER - if (boot_mode == self.BootMode.DIRECT_ROM): - address = self.__Address.SDRAM - elif (boot_mode == self.BootMode.DIRECT_DDIPL): - address = self.__Address.DDIPL - ipl3 = self.__read_memory(address, 4096)[0x40:0x1000] - seed = seed if (seed != None) else self.__guess_ipl3_seed(ipl3) - checksum = self.__calculate_ipl3_checksum(ipl3, seed) - data = [(1 << 0) if disabled else 0, seed, *checksum.to_bytes(6, byteorder='big')] - self.__link.execute_cmd(cmd=b'B', args=[self.__get_int(data[0:4]), self.__get_int(data[4:8])]) - direct = (boot_mode == self.BootMode.DIRECT_ROM) or (boot_mode == self.BootMode.DIRECT_DDIPL) - return (seed, checksum, boot_mode == self.BootMode.DIRECT_DDIPL, direct) - - def __guess_ipl3_seed(self, ipl3: bytes) -> int: - checksum = crc32(ipl3) - seed_mapping = { - 0x587BD543: 0xAC, # 5101 - 0x6170A4A1: 0x3F, # 6101 - 0x009E9EA3: 0x3F, # 7102 - 0x90BB6CB5: 0x3F, # 6102/7101 - 0x0B050EE0: 0x78, # x103 - 0x98BC2C86: 0x91, # x105 - 0xACC8580A: 0x85, # x106 - 0x0E018159: 0xDD, # 5167 - 0x10C68B18: 0xDD, # NDXJ0 - 0xBC605D0A: 0xDD, # NDDJ0 - 0x502C4466: 0xDD, # NDDJ1 - 0x0C965795: 0xDD, # NDDJ2 - 0x8FEBA21E: 0xDE, # NDDE0 - } - return seed_mapping[checksum] if checksum in seed_mapping else 0x3F - - def __calculate_ipl3_checksum(self, ipl3: bytes, seed: int) -> int: - _CHECKSUM_MAGIC = 0x6C078965 - - _add = lambda a1, a2: ((a1 + a2) & 0xFFFFFFFF) - _sub = lambda a1, a2: ((a1 - a2) & 0xFFFFFFFF) - _mul = lambda a1, a2: ((a1 * a2) & 0xFFFFFFFF) - _xor = lambda a1, a2: ((a1 ^ a2) & 0xFFFFFFFF) - _lsh = lambda a, s: (((a & 0xFFFFFFFF) << s) & 0xFFFFFFFF) - _rsh = lambda a, s: (((a & 0xFFFFFFFF) >> s) & 0xFFFFFFFF) - - def _get(offset: int) -> int: - offset *= 4 - return int.from_bytes(ipl3[offset:(offset + 4)], byteorder='big') - - def _checksum(a0: int, a1: int, a2: int) -> int: - prod = (a0 * (a2 if (a1 == 0) else a1)) - hi = ((prod >> 32) & 0xFFFFFFFF) - lo = (prod & 0xFFFFFFFF) - diff = ((hi - lo) & 0xFFFFFFFF) - return ((a0 if (diff == 0) else diff) & 0xFFFFFFFF) - - if (seed < 0x00 or seed > 0xFF): - raise ValueError('Invalid seed') - - buffer = [_xor(_add(_mul(_CHECKSUM_MAGIC, seed), 1), _get(0))] * 16 - - for i in range(1, 1009): - data_prev = data_curr if (i > 1) else _get(0) - data_curr = _get(i - 1) - data_next = _get(i) - - buffer[0] = _add(buffer[0], _checksum(_sub(1007, i), data_curr, i)) - buffer[1] = _checksum(buffer[1], data_curr, i) - buffer[2] = _xor(buffer[2], data_curr) - buffer[3] = _add(buffer[3], _checksum(_add(data_curr, 5), _CHECKSUM_MAGIC, i)) - - shift = (data_prev & 0x1F) - data_left = _lsh(data_curr, (32 - shift)) - data_right = _rsh(data_curr, shift) - b4_shifted = (data_left | data_right) - buffer[4] = _add(buffer[4], b4_shifted) - - shift = _rsh(data_prev, 27) - data_left = _lsh(data_curr, shift) - data_right = _rsh(data_curr, (32 - shift)) - b5_shifted = (data_left | data_right) - buffer[5] = _add(buffer[5], b5_shifted) - - if (data_curr < buffer[6]): - buffer[6] = _xor(_add(buffer[3], buffer[6]), _add(data_curr, i)) - else: - buffer[6] = _xor(_add(buffer[4], data_curr), buffer[6]) - - shift = (data_prev & 0x1F) - data_left = _lsh(data_curr, shift) - data_right = _rsh(data_curr, (32 - shift)) - buffer[7] = _checksum(buffer[7], (data_left | data_right), i) - - shift = _rsh(data_prev, 27) - data_left = _lsh(data_curr, (32 - shift)) - data_right = _rsh(data_curr, shift) - buffer[8] = _checksum(buffer[8], (data_left | data_right), i) - - if (data_prev < data_curr): - buffer[9] = _checksum(buffer[9], data_curr, i) - else: - buffer[9] = _add(buffer[9], data_curr) - - if (i == 1008): - break - - buffer[10] = _checksum(_add(buffer[10], data_curr), data_next, i) - buffer[11] = _checksum(_xor(buffer[11], data_curr), data_next, i) - buffer[12] = _add(buffer[12], _xor(buffer[8], data_curr)) - - shift = (data_curr & 0x1F) - data_left = _lsh(data_curr, (32 - shift)) - data_right = _rsh(data_curr, shift) - tmp = (data_left | data_right) - shift = (data_next & 0x1F) - data_left = _lsh(data_next, (32 - shift)) - data_right = _rsh(data_next, shift) - buffer[13] = _add(buffer[13], _add(tmp, (data_left | data_right))) - - shift = (data_curr & 0x1F) - data_left = _lsh(data_next, (32 - shift)) - data_right = _rsh(data_next, shift) - sum = _checksum(buffer[14], b4_shifted, i) - buffer[14] = _checksum(sum, (data_left | data_right), i) - - shift = _rsh(data_curr, 27) - data_left = _lsh(data_next, shift) - data_right = _rsh(data_next, (32 - shift)) - sum = _checksum(buffer[15], b5_shifted, i) - buffer[15] = _checksum(sum, (data_left | data_right), i) - - final_buffer = [buffer[0]] * 4 - - for i in range(16): - data = buffer[i] - - shift = (data & 0x1F) - data_left = _lsh(data, (32 - shift)) - data_right = _rsh(data, shift) - b0_shifted = _add(final_buffer[0], (data_left | data_right)) - final_buffer[0] = b0_shifted - - if (data < b0_shifted): - final_buffer[1] = _add(final_buffer[1], data) - else: - final_buffer[1] = _checksum(final_buffer[1], data, i) - - if (_rsh((data & 0x02), 1) == (data & 0x01)): - final_buffer[2] = _add(final_buffer[2], data) - else: - final_buffer[2] = _checksum(final_buffer[2], data, i) - - if (data & 0x01): - final_buffer[3] = _xor(final_buffer[3], data) - else: - final_buffer[3] = _checksum(final_buffer[3], data, i) - - sum = _checksum(final_buffer[0], final_buffer[1], 16) - xor = _xor(final_buffer[3], final_buffer[2]) - - return ((sum << 32) | xor) & 0xFFFF_FFFFFFFF - - def __generate_filename(self, prefix: str, extension: str) -> str: - return f'{prefix}-{datetime.now().strftime("%y%m%d%H%M%S.%f")}.{extension}' - - def __handle_dd_packet(self, dd: Optional[DD64Image], data: bytes) -> None: - CMD_READ_BLOCK = 1 - CMD_WRITE_BLOCK = 2 - cmd = self.__get_int(data[0:]) - address = self.__get_int(data[4:]) - track_head_block = self.__get_int(data[8:]) - track = (track_head_block >> 2) & 0xFFF - head = (track_head_block >> 1) & 0x1 - block = track_head_block & 0x1 - try: - if (not dd or not dd.loaded): - raise BadBlockError - if (cmd == CMD_READ_BLOCK): - block_data = dd.read_block(track, head, block) - self.__write_memory(address, block_data) - self.__dd_set_block_ready(0) - elif (cmd == CMD_WRITE_BLOCK): - block_data = data[12:] - dd.write_block(track, head, block, block_data) - self.__dd_set_block_ready(0) - else: - self.__dd_set_block_ready(1) - except BadBlockError: - self.__dd_set_block_ready(1) - - def __handle_isv_packet(self, data: bytes) -> None: - self.__isv_line_buffer += data - while (b'\n' in self.__isv_line_buffer): - (line, self.__isv_line_buffer) = self.__isv_line_buffer.split(b'\n', 1) - print(line.decode('EUC-JP', errors='backslashreplace')) - - def __handle_usb_packet(self, data: bytes) -> None: - header = self.__get_int(data[0:4]) - datatype = self.__DebugDatatype((header >> 24) & 0xFF) - length = (header & 0xFFFFFF) - packet = data[4:] - if (len(packet) != length): - print(f'Debug packet length and data length did not match') - elif (datatype == self.__DebugDatatype.TEXT): - print(packet.decode('UTF-8', errors='backslashreplace'), end='') - elif (datatype == self.__DebugDatatype.RAWBINARY): - filename = self.__generate_filename('binaryout', 'bin') - with open(filename, 'wb') as f: - f.write(packet) - print(f'Wrote {len(packet)} bytes to {filename}') - elif (datatype == self.__DebugDatatype.HEADER): - if (len(packet) == 16): - self.__debug_header = packet - else: - print(f'Size of header packet is invalid: {len(packet)}') - elif (datatype == self.__DebugDatatype.SCREENSHOT): - filename = self.__generate_filename('screenshot', 'png') - if (self.__debug_header != None): - header_datatype = self.__get_int(self.__debug_header[0:4]) - pixel_format = self.__get_int(self.__debug_header[4:8]) - image_w = self.__get_int(self.__debug_header[8:12]) - image_h = self.__get_int(self.__debug_header[12:16]) - if (header_datatype == 0x04 and pixel_format != 0 and image_w != 0 and image_h != 0): - mode = 'RGBA' if pixel_format == 4 else 'I;16' - screenshot = Image.frombytes(mode, (image_w, image_h), packet) - screenshot.save(filename) - print(f'Wrote {image_w}x{image_h} pixels to {filename}') - else: - print('Screenshot header data is invalid') - else: - print('Got screenshot packet without header data') - elif (datatype == self.__DebugDatatype.GDB): - self.__handle_gdb_datatype(packet) - - def __handle_gdb_socket(self, gdb_port: int) -> None: - MAX_PACKET_SIZE = 65536 - gdb_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - gdb_socket.bind(('localhost', gdb_port)) - gdb_socket.listen() - while (True): - (self.__gdb_client, address) = gdb_socket.accept() - client_address = f'{address[0]}:{address[1]}' - print(f'[GDB]: New connection ({client_address})') - try: - connected = True - while (connected): - data = self.__gdb_client.recv(MAX_PACKET_SIZE) - if (data): - self.debug_send(self.__DebugDatatype.GDB, data) - else: - connected = False - except: - pass - finally: - self.__gdb_client.close() - print(f'[GDB]: Connection closed ({client_address})') - - def __handle_gdb_datatype(self, data: bytes) -> None: - if (self.__gdb_client): - try: - self.__gdb_client.sendall(data) - except: - pass - - def __handle_debug_input(self) -> None: - running = True - while (running): - try: - command = input() - if (len(command) > 0): - data = b'' - datatype = self.__DebugDatatype.TEXT - if (command.count('@') != 2): - data += f'{command}\0'.encode() - else: - start = command.index('@') - end = command.rindex('@') - filename = command[(start + 1):end] - if (len(filename) == 0): - raise FileNotFoundError - with open(filename, 'rb') as f: - file_data = f.read() - if (command.startswith('@') and command.endswith('@')): - datatype = self.__DebugDatatype.RAWBINARY - data += file_data - else: - data += f'{command[:start]}@{len(file_data)}@'.encode() - data += file_data - data += b'\0' - self.debug_send(datatype, data) - except ValueError as e: - print(f'Error: {e}') - except FileNotFoundError as e: - print(f'Error: Cannot open file {e.filename}') - except EOFError: - running = False - - def debug_loop(self, isv: int=0, disks: Optional[list[str]]=None, gdb_port: Optional[int]=None) -> None: - dd = None - current_image = 0 - next_image = 0 - - self.__set_config(self.__CfgId.ROM_WRITE_ENABLE, 1 if (isv != 0) else 0) - self.__set_config(self.__CfgId.ISV_ADDRESS, isv) - if (isv != 0): - print(f'IS-Viewer64 support set to [ENABLED] at ROM offset [0x{(isv):08X}]') - if (self.__get_config(self.__CfgId.ROM_SHADOW_ENABLE)): - print('ROM shadow enabled - IS-Viewer64 will NOT work (use --no-shadow option while uploading ROM to disable it)') - - if (disks): - dd = DD64Image() - drive_type = None - for path in disks: - try: - dd.load(path) - if (drive_type == None): - drive_type = dd.get_drive_type() - elif (drive_type != dd.get_drive_type()): - raise ValueError('Disk drive type mismatch') - dd.unload() - except ValueError as e: - dd = None - print(f'64DD disabled, incorrect disk images provided: {e}') - break - if (dd): - self.__set_config(self.__CfgId.DD_MODE, self.__DDMode.FULL) - self.__set_config(self.__CfgId.DD_SD_ENABLE, False) - self.__set_config(self.__CfgId.DD_DRIVE_TYPE, { - 'retail': self.__DDDriveType.RETAIL, - 'development': self.__DDDriveType.DEVELOPMENT - }[drive_type]) - self.__set_config(self.__CfgId.DD_DISK_STATE, self.__DDDiskState.EJECTED) - self.__set_config(self.__CfgId.BUTTON_MODE, self.__ButtonMode.USB_PACKET) - print('64DD enabled, loaded disks:') - for disk in disks: - print(f' - {os.path.basename(disk)}') - print('Press button on SC64 device to cycle through provided disks') - - if (gdb_port): - gdb_thread = Thread(target=lambda: self.__handle_gdb_socket(gdb_port), daemon=True) - gdb_thread.start() - print(f'GDB server started and listening on port [{gdb_port}]') - - print('\nDebug loop started, press Ctrl-C to exit\n') - - try: - thread_input = Thread(target=self.__handle_debug_input, daemon=True) - thread_input.start() - while (thread_input.is_alive()): - packet = self.__link.get_packet() - if (packet != None): - (cmd, data) = packet - if (cmd == b'D'): - self.__handle_dd_packet(dd, data) - if (cmd == b'I'): - self.__handle_isv_packet(data) - if (cmd == b'U'): - self.__handle_usb_packet(data) - if (cmd == b'B'): - if (not dd.loaded): - dd.load(disks[next_image]) - self.__set_config(self.__CfgId.DD_DISK_STATE, self.__DDDiskState.INSERTED) - current_image = next_image - next_image += 1 - if (next_image >= len(disks)): - next_image = 0 - print(f'64DD disk inserted - {os.path.basename(disks[current_image])}') - else: - self.__set_config(self.__CfgId.DD_DISK_STATE, self.__DDDiskState.EJECTED) - dd.unload() - print(f'64DD disk ejected - {os.path.basename(disks[current_image])}') - except KeyboardInterrupt: - pass - finally: - print('\nDebug loop stopped\n') - - if (dd and dd.loaded): - self.__set_config(self.__CfgId.DD_DISK_STATE, self.__DDDiskState.EJECTED) - if (isv != 0): - self.__set_config(self.__CfgId.ISV_ADDRESS, 0) - - -class EnumAction(argparse.Action): - def __init__(self, **kwargs): - type = kwargs.pop('type', None) - if type is None: - raise ValueError('No type was provided') - if not issubclass(type, Enum): - raise TypeError('Provided type is not an Enum subclass') - items = (choice.lower().replace('_', '-') for (choice, _) in type.__members__.items()) - kwargs.setdefault('choices', tuple(items)) - super(EnumAction, self).__init__(**kwargs) - self.__enum = type - - def __call__(self, parser, namespace, values, option_string): - key = str(values).upper().replace('-', '_') - value = self.__enum[key] - setattr(namespace, self.dest, value) - - - -if __name__ == '__main__': - def download_memory_type(argument: str): - params = argument.split(',') - if (len(params) < 2 or len(params) > 3): - raise argparse.ArgumentError() - address = int(params[0], 0) - length = int(params[1], 0) - file = params[2] if len(params) >= 3 else 'sc64dump.bin' - return (address, length, file) - - parser = argparse.ArgumentParser(description='SC64 control software') - parser.add_argument('rom', nargs='?', help='upload ROM from specified file') - parser.add_argument('--backup-firmware', metavar='file', help='backup SC64 firmware and write it to specified file') - parser.add_argument('--update-firmware', metavar='file', help='update SC64 firmware from specified file') - parser.add_argument('--reset-state', action='store_true', help='reset SC64 internal state') - parser.add_argument('--print-state', action='store_true', help='print SC64 internal state') - parser.add_argument('--led-blink', metavar='{yes,no}', help='enable or disable LED I/O activity blinking') - parser.add_argument('--rtc', action='store_true', help='update clock in SC64 to system time') - parser.add_argument('--boot', type=SC64.BootMode, action=EnumAction, help='set boot mode') - parser.add_argument('--tv', type=SC64.TVType, action=EnumAction, help='force TV type to set value, ignored when one of direct boot modes are selected') - parser.add_argument('--no-shadow', action='store_false', help='do not put last 128 kB of ROM inside flash memory (can corrupt non EEPROM saves)') - parser.add_argument('--save-type', type=SC64.SaveType, action=EnumAction, help='set save type') - parser.add_argument('--save', metavar='file', help='upload save from specified file') - parser.add_argument('--backup-save', metavar='file', help='download save and write it to specified file') - parser.add_argument('--ddipl', metavar='file', help='upload 64DD IPL from specified file') - parser.add_argument('--disk', metavar='file', action='append', help='path to 64DD disk (.ndd format), can be specified multiple times') - parser.add_argument('--isv', metavar='offset', type=lambda x: int(x, 0), default=0, help='enable IS-Viewer64 support at provided ROM offset') - parser.add_argument('--gdb', metavar='port', type=int, help='expose TCP socket port for GDB debugging') - parser.add_argument('--debug', action='store_true', help='run debug loop') - parser.add_argument('--download-memory', metavar='address,length,[file]', type=download_memory_type, help='download specified memory region and write it to file') - - if (len(sys.argv) <= 1): - parser.print_help() - parser.exit() - - args = parser.parse_args() - - def fix_rom_endianness(rom: bytes) -> bytes: - data = bytearray(rom) - pi_config = int.from_bytes(rom[0:4], byteorder='big') - if (pi_config == 0x37804012): - data[0::2], data[1::2] = data[1::2], data[0::2] - elif (pi_config == 0x40123780): - data[0::4], data[1::4], data[2::4], data[3::4] = data[3::4], data[2::4], data[1::4], data[0::4] - return bytes(data) - - try: - sc64 = SC64() - autodetected_save_type = None - - if (args.backup_firmware): - with open(args.backup_firmware, 'wb') as f: - print('Generating backup, this might take a while... ', end='', flush=True) - f.write(sc64.backup_firmware()) - print('done') - - if (args.update_firmware): - with open(args.update_firmware, 'rb') as f: - print('Updating firmware, this might take a while... ', end='', flush=True) - status_callback = lambda status: print(f'{status} ', end='', flush=True) - sc64.update_firmware(f.read(), status_callback) - print('done') - - (version, script_outdated) = sc64.check_firmware_version() - - print(f'\x1b[32mSC64 firmware version: [{version}]\x1b[0m') - if (script_outdated): - print('\x1b[33m') - print('[ SC64 firmware is newer than last known version ]') - print('[ Consider downloading latest sc64 executable from ]') - print('[ https://github.com/Polprzewodnikowy/SummerCart64/releases ]') - print('\x1b[0m') - - if (args.reset_state): - sc64.reset_state() - print('SC64 internal state reset') - - if (args.led_blink): - blink = (args.led_blink == 'yes') - sc64.set_led_enable(blink) - print(f'LED blinking set to [{"ENABLED" if blink else "DISABLED"}]') - - if (args.rtc): - value = datetime.now() - sc64.set_rtc(value) - print(f'RTC set to [{value.strftime("%Y-%m-%d %H:%M:%S")}]') - - if (args.rom): - with open(args.rom, 'rb') as f: - rom_data = fix_rom_endianness(f.read()) - print(f'Uploading ROM ({len(rom_data) / (1 * 1024 * 1024):.2f} MiB)... ', end='', flush=True) - sc64.upload_rom(rom_data, use_shadow=args.no_shadow) - autodetected_save_type = sc64.autodetect_save_type(rom_data) - print('done') - - if (args.ddipl): - with open(args.ddipl, 'rb') as f: - print('Uploading 64DD IPL... ', end='', flush=True) - sc64.upload_ddipl(f.read()) - print('done') - - if (args.rom or args.ddipl or args.boot != None): - mode = args.boot - if (mode == None): - mode = SC64.BootMode.ROM if args.rom else SC64.BootMode.DDIPL - sc64.set_boot_mode(mode) - print(f'Boot mode set to [{mode.name}]') - (seed, checksum, dd_mode, direct) = sc64.update_cic_parameters() - if (direct): - print('CIC parameters set to [', end='') - print(f'{"DDIPL" if dd_mode else "ROM"}, ', end='') - print(f'seed: 0x{seed:02X}, checksum: 0x{checksum:012X}', end='') - print(']') - - if (args.rom or args.ddipl or args.tv != None): - tv = args.tv if args.tv else SC64.TVType.AUTO - direct = sc64.set_tv_type(tv) - if (args.tv != None): - print(f'TV type set to [{args.tv.name}]{" (ignored)" if direct else ""}') - - if (args.save_type != None or autodetected_save_type != None): - save_type = args.save_type if args.save_type != None else autodetected_save_type - sc64.set_save_type(save_type) - print(f'Save type set to [{save_type.name}]{" (autodetected)" if autodetected_save_type != None else ""}') - - if (args.save): - with open(args.save, 'rb') as f: - print('Uploading save... ', end='', flush=True) - sc64.upload_save(f.read()) - print('done') - - if (args.print_state): - state = sc64.get_state() - print('Current SC64 internal state:') - for key, value in state.items(): - if (hasattr(value, 'name')): - value = getattr(value, 'name') - print(f' {key}: {value}') - - if (args.debug or args.isv or args.disk or args.gdb): - sc64.debug_loop(isv=args.isv, disks=args.disk, gdb_port=args.gdb) - - if (args.backup_save): - with open(args.backup_save, 'wb') as f: - print('Downloading save... ', end='', flush=True) - f.write(sc64.download_save()) - print('done') - - if (args.download_memory != None): - (address, length, file) = args.download_memory - with open(file, 'wb') as f: - print('Downloading memory... ', end='', flush=True) - f.write(sc64.download_memory(address, length)) - print('done') - except ValueError as e: - print(f'\n\x1b[31mValue error: {e}\x1b[0m\n') - except ConnectionException as e: - print(f'\n\x1b[31mSC64 error: {e}\x1b[0m\n') - except Exception as e: - print(f'\n\x1b[31mUnhandled error "{e.__class__.__name__}": {e}\x1b[0m\n') diff --git a/sw/pc/primer.py b/sw/tools/primer.py similarity index 73% rename from sw/pc/primer.py rename to sw/tools/primer.py index e2be968..495413b 100644 --- a/sw/pc/primer.py +++ b/sw/tools/primer.py @@ -1,533 +1,696 @@ -#!/usr/bin/env python3 - -import io -import os -import serial -import signal -import sys -import time -from binascii import crc32 -from sc64 import SC64 -from sys import exit -from typing import Callable, Optional - - - -class Utils: - __progress_active = False - - @staticmethod - def log(message: str='') -> None: - print(message) - - @staticmethod - def log_no_end(message: str='') -> None: - print(message, end='', flush=True) - - @staticmethod - def info(message: str='') -> None: - print(f'\033[92m{message}\033[0m') - - @staticmethod - def warning(message: str='') -> None: - print(f'\033[93m{message}\033[0m') - - @staticmethod - def die(reason: str) -> None: - print(f'\033[91m{reason}\033[0m') - exit(-1) - - @property - def get_progress_active(self): - return self.__progress_active - - def progress(self, length: int, position: int, description: str) -> None: - value = ((position / length) * 100.0) - if (position == 0): - self.__progress_active = True - Utils.log_no_end(f'\r{value:5.1f}%: [{description}]') - if (position == length): - Utils.log() - self.__progress_active = False - - def exit_warning(self): - if (self.__progress_active): - Utils.log() - Utils.warning('Ctrl-C is prohibited during bring-up procedure') - - -class SC64UpdateDataException(Exception): - pass - -class SC64UpdateData: - __UPDATE_TOKEN = b'SC64 Update v2.0' - __CHUNK_ID_UPDATE_INFO = 1 - __CHUNK_ID_MCU_DATA = 2 - __CHUNK_ID_FPGA_DATA = 3 - __CHUNK_ID_BOOTLOADER_DATA = 4 - __CHUNK_ID_PRIMER_DATA = 5 - - __update_info: Optional[str] - __mcu_data: Optional[bytes] - __fpga_data: Optional[bytes] - __bootloader_data: Optional[bytes] - __primer_data: Optional[bytes] - - def __load_int(self, f: io.BufferedReader) -> int: - try: - data = f.read(4) - if (len(data) != 4): - raise ValueError('Read size did not match requested amount') - value = int.from_bytes(data, byteorder='little') - except ValueError as e: - raise SC64UpdateDataException(f'Error while reading chunk header: {e}') - return value - - def __load_chunk(self, f: io.BufferedReader) -> tuple[int, bytes]: - id = self.__load_int(f) - aligned_length = self.__load_int(f) - checksum = self.__load_int(f) - data_length = self.__load_int(f) - - data = f.read(data_length) - - align = (aligned_length - 4 - 4 - data_length) - f.seek(align, io.SEEK_CUR) - - if (crc32(data) != checksum): - raise SC64UpdateDataException(f'Invalid checksum for chunk id [{id}] inside update file') - - return (id, data) - - def load(self, path: str, require_all: bool=False) -> None: - self.__update_info = None - self.__mcu_data = None - self.__fpga_data = None - self.__bootloader_data = None - self.__primer_data = None - - try: - with open(path, 'rb') as f: - if (f.read(len(self.__UPDATE_TOKEN)) != self.__UPDATE_TOKEN): - raise SC64UpdateDataException('Invalid update file header') - - while (f.peek(1) != b''): - (id, data) = self.__load_chunk(f) - if (id == self.__CHUNK_ID_UPDATE_INFO): - self.__update_info = data.decode('ascii') - elif (id == self.__CHUNK_ID_MCU_DATA): - self.__mcu_data = data - elif (id == self.__CHUNK_ID_FPGA_DATA): - self.__fpga_data = data - elif (id == self.__CHUNK_ID_BOOTLOADER_DATA): - self.__bootloader_data = data - elif (id == self.__CHUNK_ID_PRIMER_DATA): - self.__primer_data = data - else: - raise SC64UpdateDataException('Unknown chunk inside update file') - - if (require_all): - if (not self.__update_info): - raise SC64UpdateDataException('No update info inside update file') - if (not self.__mcu_data): - raise SC64UpdateDataException('No MCU data inside update file') - if (not self.__fpga_data): - raise SC64UpdateDataException('No FPGA data inside update file') - if (not self.__bootloader_data): - raise SC64UpdateDataException('No bootloader data inside update file') - if (not self.__primer_data): - raise SC64UpdateDataException('No primer data inside update file') - - except IOError as e: - raise SC64UpdateDataException(f'IO error while loading update data: {e}') - - def get_update_info(self) -> Optional[str]: - return self.__update_info - - def get_mcu_data(self) -> Optional[bytes]: - return self.__mcu_data - - def get_fpga_data(self) -> Optional[bytes]: - return self.__fpga_data - - def get_bootloader_data(self) -> Optional[bytes]: - return self.__bootloader_data - - def get_primer_data(self) -> Optional[bytes]: - return self.__primer_data - - -class STM32BootloaderException(Exception): - pass - -class STM32Bootloader: - __INIT = b'\x7F' - __ACK = b'\x79' - __NACK = b'\x1F' - - __MEMORY_RW_MAX_SIZE = 256 - __FLASH_LOAD_ADDRESS = 0x08000000 - __FLASH_MAX_LOAD_SIZE = 0x8000 - __RAM_LOAD_ADDRESS = 0x20001000 - __RAM_MAX_LOAD_SIZE = 0x1000 - - DEV_ID_STM32G030XX = b'\x04\x66' - - __connected = False - - def __init__(self, write: Callable[[bytes], None], read: Callable[[int], bytes], progress: Callable[[int, int, str], None]): - self.__write = write - self.__read = read - self.__progress = progress - - def __append_xor(self, data: bytes) -> bytes: - xor = (0xFF if (len(data) == 1) else 0x00) - for b in data: - xor ^= b - return bytes([*data, xor]) - - def __check_ack(self) -> None: - response = self.__read(1) - if (response == None): - raise STM32BootloaderException('No ACK/NACK byte received') - if (response == self.__NACK): - raise STM32BootloaderException('NACK byte received') - if (response != self.__ACK): - raise STM32BootloaderException('Unknown ACK/NACK byte received') - - def __cmd_send(self, cmd: bytes) -> None: - if (len(cmd) != 1): - raise ValueError('Command must contain only one byte') - self.__write(self.__append_xor(cmd)) - self.__check_ack() - - def __data_write(self, data: bytes) -> None: - self.__write(self.__append_xor(data)) - self.__check_ack() - - def __data_read(self) -> bytes: - length = self.__read(1) - if (len(length) != 1): - raise STM32BootloaderException('Did not receive length byte') - length = length[0] - data = self.__read(length + 1) - self.__check_ack() - return data - - def __get_id(self) -> bytes: - self.__cmd_send(b'\x02') - return self.__data_read() - - def __read_memory(self, address: int, length: int) -> bytes: - if (length == 0 or length > self.__MEMORY_RW_MAX_SIZE): - raise ValueError('Wrong data size for read memory command') - self.__cmd_send(b'\x11') - self.__data_write(address.to_bytes(4, byteorder='big')) - self.__data_write(bytes([length - 1])) - return self.__read(length) - - def __go(self, address: int) -> None: - self.__cmd_send(b'\x21') - self.__data_write(address.to_bytes(4, byteorder='big')) - self.__connected = False - - def __write_memory(self, address: int, data: bytes) -> None: - length = len(data) - if (length == 0 or length > self.__MEMORY_RW_MAX_SIZE): - raise ValueError('Wrong data size for write memory command') - if (((address % 4) != 0) or ((length % 4) != 0)): - raise ValueError('Write memory command requires 4 byte alignment') - self.__cmd_send(b'\x31') - self.__data_write(address.to_bytes(4, byteorder='big')) - self.__data_write(bytes([length - 1, *data])) - - def __mass_erase(self) -> None: - self.__cmd_send(b'\x44') - self.__data_write(b'\xFF\xFF') - - def __load_memory(self, address: int, data: bytes, description: str='') -> None: - length = len(data) - self.__progress(length, 0, description) - for offset in range(0, length, self.__MEMORY_RW_MAX_SIZE): - chunk = data[offset:offset + self.__MEMORY_RW_MAX_SIZE] - self.__write_memory(address + offset, chunk) - verify = self.__read_memory(address + offset, len(chunk)) - if (chunk != verify): - raise STM32BootloaderException('Memory verify failed') - self.__progress(length, offset, description) - self.__progress(length, length, description) - - def connect(self, id: int) -> None: - if (not self.__connected): - self.__write(self.__INIT) - self.__check_ack() - self.__connected = True - dev_id = self.__get_id() - if (dev_id != id): - raise STM32BootloaderException('Unknown chip detected') - - def load_ram_and_run(self, data: bytes, description: str='') -> None: - if (len(data) > self.__RAM_MAX_LOAD_SIZE): - raise STM32BootloaderException('RAM image too big') - self.__load_memory(self.__RAM_LOAD_ADDRESS, data, description) - self.__go(self.__RAM_LOAD_ADDRESS) - - def load_flash_and_run(self, data: bytes, description: str='') -> None: - if (len(data) > self.__FLASH_MAX_LOAD_SIZE): - raise STM32BootloaderException('Flash image too big') - self.__mass_erase() - try: - self.__load_memory(self.__FLASH_LOAD_ADDRESS, data, description) - self.__go(self.__FLASH_LOAD_ADDRESS) - except STM32BootloaderException as e: - self.__mass_erase() - raise STM32BootloaderException(e) - - -class LCMXO2PrimerException(Exception): - pass - -class LCMXO2Primer: - __PRIMER_ID_LCMXO2 = b'MXO2' - - __CMD_GET_PRIMER_ID = b'?' - __CMD_PROBE_FPGA = b'#' - __CMD_RESTART = b'$' - __CMD_GET_DEVICE_ID = b'I' - __CMD_ENABLE_FLASH = b'E' - __CMD_ERASE_FLASH = b'X' - __CMD_RESET_ADDRESS = b'A' - __CMD_WRITE_PAGE = b'W' - __CMD_READ_PAGE = b'R' - __CMD_PROGRAM_DONE = b'F' - __CMD_INIT_FEATBITS = b'Q' - __CMD_REFRESH = b'B' - - __FLASH_PAGE_SIZE = 16 - __FLASH_NUM_PAGES = 11260 - - __FPGA_PROBE_VALUE = b'\x64' - - DEV_ID_LCMXO2_7000HC = b'\x01\x2B\xD0\x43' - - def __init__(self, write: Callable[[bytes], None], read: Callable[[int], bytes], progress: Callable[[int, int, str], None]): - self.__write = write - self.__read = read - self.__progress = progress - - def __cmd_execute(self, cmd: bytes, data: bytes=b'') -> bytes: - if (len(cmd) != 1): - raise ValueError('Command must contain only one byte') - if (len(data) >= 256): - raise ValueError('Data size too big') - - packet = b'CMD' + cmd - packet += len(data).to_bytes(1, byteorder='little') - packet += data - packet += crc32(packet).to_bytes(4, byteorder='little') - self.__write(packet) - - response = self.__read(5) - if (len(response) != 5): - raise LCMXO2PrimerException(f'No response received [{cmd}]') - length = int.from_bytes(response[4:5], byteorder='little') - response += self.__read(length) - calculated_checksum = crc32(response) - received_checksum = int.from_bytes(self.__read(4), byteorder='little') - - if (response[0:3] != b'RSP'): - raise LCMXO2PrimerException(f'Invalid response token [{response[0:3]} / {cmd}]') - if (response[3:4] != cmd): - raise LCMXO2PrimerException(f'Invalid response command [{cmd} / {response[3]}]') - if (calculated_checksum != received_checksum): - raise LCMXO2PrimerException(f'Invalid response checksum [{cmd}]') - - return response[5:] - - def connect(self, id: bytes) -> None: - primer_id = self.__cmd_execute(self.__CMD_GET_PRIMER_ID) - if (primer_id != self.__PRIMER_ID_LCMXO2): - raise LCMXO2PrimerException('Invalid primer ID received') - - dev_id = self.__cmd_execute(self.__CMD_GET_DEVICE_ID) - if (dev_id != id): - raise LCMXO2PrimerException('Invalid FPGA device id received') - - def load_flash_and_run(self, data: bytes, description: str) -> None: - erase_description = f'{description} / Erase' - program_description = f'{description} / Program' - verify_description = f'{description} / Verify' - - length = len(data) - if (length > (self.__FLASH_PAGE_SIZE * self.__FLASH_NUM_PAGES)): - raise LCMXO2PrimerException('FPGA data size too big') - if ((length % self.__FLASH_PAGE_SIZE) != 0): - raise LCMXO2PrimerException('FPGA data size not aligned to page size') - - self.__cmd_execute(self.__CMD_ENABLE_FLASH) - - self.__progress(length, 0, erase_description) - self.__cmd_execute(self.__CMD_ERASE_FLASH) - self.__progress(length, length, erase_description) - - try: - self.__cmd_execute(self.__CMD_RESET_ADDRESS) - self.__progress(length, 0, program_description) - for offset in range(0, length, self.__FLASH_PAGE_SIZE): - page_data = data[offset:(offset + self.__FLASH_PAGE_SIZE)] - self.__cmd_execute(self.__CMD_WRITE_PAGE, page_data) - self.__progress(length, offset, program_description) - self.__progress(length, length, program_description) - - self.__cmd_execute(self.__CMD_RESET_ADDRESS) - self.__progress(length, 0, verify_description) - for offset in range(0, length, self.__FLASH_PAGE_SIZE): - page_data = data[offset:(offset + self.__FLASH_PAGE_SIZE)] - verify_data = self.__cmd_execute(self.__CMD_READ_PAGE) - self.__progress(length, offset, verify_description) - if (page_data != verify_data): - raise LCMXO2PrimerException('FPGA verification error') - self.__progress(length, length, verify_description) - - self.__cmd_execute(self.__CMD_INIT_FEATBITS) - - self.__cmd_execute(self.__CMD_PROGRAM_DONE) - - self.__cmd_execute(self.__CMD_REFRESH) - - if (self.__cmd_execute(self.__CMD_PROBE_FPGA) != self.__FPGA_PROBE_VALUE): - raise LCMXO2PrimerException('Invalid FPGA ID value received') - - except LCMXO2PrimerException as e: - self.__cmd_execute(self.__CMD_ENABLE_FLASH) - self.__cmd_execute(self.__CMD_ERASE_FLASH) - self.__cmd_execute(self.__CMD_REFRESH) - self.__cmd_execute(self.__CMD_RESTART) - raise LCMXO2PrimerException(e) - - self.__cmd_execute(self.__CMD_RESTART) - - -class SC64BringUp: - __SERIAL_BAUD: int = 115200 - __SERIAL_TIMEOUT: float = 6.0 - __INTERVAL_TIME: float = 0.5 - - def __init__(self, progress: Callable[[int, int, str], None]) -> None: - self.__progress = progress - - def load_update_data(self, path: str) -> None: - self.__sc64_update_data = SC64UpdateData() - self.__sc64_update_data.load(path, require_all=True) - - def get_update_info(self) -> str: - return self.__sc64_update_data.get_update_info() - - def start_bring_up(self, port: str, only_bootloader: bool=False) -> None: - link = None - try: - if (not only_bootloader): - link = serial.Serial( - port, - baudrate=self.__SERIAL_BAUD, - parity=serial.PARITY_EVEN, - timeout=self.__SERIAL_TIMEOUT, - write_timeout=self.__SERIAL_TIMEOUT - ) - - stm32_bootloader = STM32Bootloader(link.write, link.read, self.__progress) - lcmxo2_primer = LCMXO2Primer(link.write, link.read, self.__progress) - - stm32_bootloader.connect(stm32_bootloader.DEV_ID_STM32G030XX) - stm32_bootloader.load_ram_and_run(self.__sc64_update_data.get_primer_data(), 'FPGA primer -> STM32 RAM') - time.sleep(self.__INTERVAL_TIME) - link.read_all() - - lcmxo2_primer.connect(lcmxo2_primer.DEV_ID_LCMXO2_7000HC) - lcmxo2_primer.load_flash_and_run(self.__sc64_update_data.get_fpga_data(), 'FPGA configuration -> LCMXO2 FLASH') - time.sleep(self.__INTERVAL_TIME) - link.read_all() - - stm32_bootloader.connect(stm32_bootloader.DEV_ID_STM32G030XX) - stm32_bootloader.load_flash_and_run(self.__sc64_update_data.get_mcu_data(), 'MCU software -> STM32 FLASH') - time.sleep(self.__INTERVAL_TIME) - link.read_all() - - bootloader_description = 'Bootloader -> SC64 FLASH' - bootloader_data = self.__sc64_update_data.get_bootloader_data() - bootloader_length = len(bootloader_data) - self.__progress(bootloader_length, 0, bootloader_description) - SC64().upload_bootloader(bootloader_data) - self.__progress(bootloader_length, bootloader_length, bootloader_description) - finally: - if (link and link.is_open): - link.close() - - -if __name__ == '__main__': - nargs = len(sys.argv) - if (nargs < 3 or nargs > 4): - Utils.die(f'Usage: {sys.argv[0]} serial_port update_file [--only-bootloader]') - - port = sys.argv[1] - update_data_path = sys.argv[2] - only_bootloader = False - if (nargs == 4): - if (sys.argv[3] == '--only-bootloader'): - only_bootloader = True - else: - Utils.die(f'Unknown argument: {sys.argv[3]}') - - utils = Utils() - sc64_bring_up = SC64BringUp(progress=utils.progress) - - Utils.log() - Utils.info('[ Welcome to SC64 flashcart board bring-up! ]') - Utils.log() - - Utils.log(f'Serial port: {port}') - Utils.log(f'Update data path: {os.path.abspath(update_data_path)}') - try: - sc64_bring_up.load_update_data(update_data_path) - except SC64UpdateDataException as e: - Utils.die(f'Provided \'{update_data_path}\' file is invalid: {e}') - Utils.log_no_end('Update info: ') - Utils.log(sc64_bring_up.get_update_info()) - Utils.log() - - if (only_bootloader): - Utils.log('Running in "only bootloader" mode') - Utils.log() - - Utils.warning('[ CAUTION ]') - Utils.warning('Configure FTDI chip with provided ft232h_config.xml before continuing') - Utils.warning('Connect SC64 USB port to the same computer you\'re running this script') - Utils.warning('Make sure SC64 USB port is recognized in system before continuing') - Utils.log() - - Utils.warning('[ IMPORTANT ]') - Utils.warning('Unplug SC64 board from power and reconnect it before proceeding') - Utils.log() - - try: - if (input('Type YES to continue: ') != 'YES'): - Utils.die('No confirmation received. Exiting') - Utils.log() - except KeyboardInterrupt: - Utils.log() - Utils.die('Aborted') - - original_sigint_handler = signal.getsignal(signal.SIGINT) - try: - signal.signal(signal.SIGINT, lambda *kwargs: utils.exit_warning()) - sc64_bring_up.start_bring_up(port, only_bootloader) - except (serial.SerialException, STM32BootloaderException, LCMXO2PrimerException) as e: - if (utils.get_progress_active): - Utils.log() - Utils.die(f'Error while running bring-up: {e}') - finally: - signal.signal(signal.SIGINT, original_sigint_handler) - - Utils.log() - Utils.info('[ SC64 flashcart board bring-up finished successfully! ]') - Utils.log() +#!/usr/bin/env python3 + +import io +import os +import queue +import serial +import signal +import sys +import time +from binascii import crc32 +from enum import IntEnum +from serial.tools import list_ports +from sys import exit +from typing import Callable, Optional + + + +class Utils: + __progress_active = False + + @staticmethod + def log(message: str='') -> None: + print(message) + + @staticmethod + def log_no_end(message: str='') -> None: + print(message, end='', flush=True) + + @staticmethod + def info(message: str='') -> None: + print(f'\033[92m{message}\033[0m') + + @staticmethod + def warning(message: str='') -> None: + print(f'\033[93m{message}\033[0m') + + @staticmethod + def die(reason: str) -> None: + print(f'\033[91m{reason}\033[0m') + exit(-1) + + @property + def get_progress_active(self): + return self.__progress_active + + def progress(self, length: int, position: int, description: str) -> None: + value = ((position / length) * 100.0) + if (position == 0): + self.__progress_active = True + Utils.log_no_end(f'\r{value:5.1f}%: [{description}]') + if (position == length): + Utils.log() + self.__progress_active = False + + def exit_warning(self): + if (self.__progress_active): + Utils.log() + Utils.warning('Ctrl-C is prohibited during bring-up procedure') + + +class SC64UpdateDataException(Exception): + pass + +class SC64UpdateData: + __UPDATE_TOKEN = b'SC64 Update v2.0' + + __CHUNK_ID_UPDATE_INFO = 1 + __CHUNK_ID_MCU_DATA = 2 + __CHUNK_ID_FPGA_DATA = 3 + __CHUNK_ID_BOOTLOADER_DATA = 4 + __CHUNK_ID_PRIMER_DATA = 5 + + __update_info: Optional[str] + __mcu_data: Optional[bytes] + __fpga_data: Optional[bytes] + __bootloader_data: Optional[bytes] + __primer_data: Optional[bytes] + + def __int_to_bytes(self, value: int) -> bytes: + return value.to_bytes(4, byteorder='little') + + def __align(self, value: int) -> int: + if (value % 16 != 0): + value += (16 - (value % 16)) + return value + + def __load_int(self, f: io.BufferedReader) -> int: + try: + data = f.read(4) + if (len(data) != 4): + raise ValueError('Read size did not match requested amount') + value = int.from_bytes(data, byteorder='little') + except ValueError as e: + raise SC64UpdateDataException(f'Error while reading chunk header: {e}') + return value + + def __load_chunk(self, f: io.BufferedReader) -> tuple[int, bytes]: + id = self.__load_int(f) + aligned_length = self.__load_int(f) + checksum = self.__load_int(f) + data_length = self.__load_int(f) + + data = f.read(data_length) + + align = (aligned_length - 4 - 4 - data_length) + f.seek(align, io.SEEK_CUR) + + if (crc32(data) != checksum): + raise SC64UpdateDataException(f'Invalid checksum for chunk id [{id}] inside update file') + + return (id, data) + + def load(self, path: str, require_all: bool=False) -> None: + self.__update_info = None + self.__mcu_data = None + self.__fpga_data = None + self.__bootloader_data = None + self.__primer_data = None + + try: + with open(path, 'rb') as f: + if (f.read(len(self.__UPDATE_TOKEN)) != self.__UPDATE_TOKEN): + raise SC64UpdateDataException('Invalid update file header') + + while (f.peek(1) != b''): + (id, data) = self.__load_chunk(f) + if (id == self.__CHUNK_ID_UPDATE_INFO): + self.__update_info = data.decode('ascii') + elif (id == self.__CHUNK_ID_MCU_DATA): + self.__mcu_data = data + elif (id == self.__CHUNK_ID_FPGA_DATA): + self.__fpga_data = data + elif (id == self.__CHUNK_ID_BOOTLOADER_DATA): + self.__bootloader_data = data + elif (id == self.__CHUNK_ID_PRIMER_DATA): + self.__primer_data = data + else: + raise SC64UpdateDataException('Unknown chunk inside update file') + + if (require_all): + if (not self.__update_info): + raise SC64UpdateDataException('No update info inside update file') + if (not self.__mcu_data): + raise SC64UpdateDataException('No MCU data inside update file') + if (not self.__fpga_data): + raise SC64UpdateDataException('No FPGA data inside update file') + if (not self.__bootloader_data): + raise SC64UpdateDataException('No bootloader data inside update file') + if (not self.__primer_data): + raise SC64UpdateDataException('No primer data inside update file') + + except IOError as e: + raise SC64UpdateDataException(f'IO error while loading update data: {e}') + + def get_update_info(self) -> Optional[str]: + return self.__update_info + + def get_mcu_data(self) -> Optional[bytes]: + return self.__mcu_data + + def get_fpga_data(self) -> Optional[bytes]: + return self.__fpga_data + + def get_bootloader_data(self) -> Optional[bytes]: + return self.__bootloader_data + + def get_primer_data(self) -> Optional[bytes]: + return self.__primer_data + + def create_bootloader_only_firmware(self): + if (self.__bootloader_data == None): + raise SC64UpdateDataException('No bootloader data available for firmware creation') + + chunk = b'' + chunk += self.__int_to_bytes(self.__CHUNK_ID_BOOTLOADER_DATA) + chunk += self.__int_to_bytes(8 + self.__align(len(self.__bootloader_data))) + chunk += self.__int_to_bytes(crc32(self.__bootloader_data)) + chunk += self.__int_to_bytes(len(self.__bootloader_data)) + chunk += self.__bootloader_data + chunk += bytes([0] * (self.__align(len(chunk)) - len(chunk))) + + data = b'' + data += self.__UPDATE_TOKEN + data += chunk + + return data + + +class STM32BootloaderException(Exception): + pass + +class STM32Bootloader: + __INIT = b'\x7F' + __ACK = b'\x79' + __NACK = b'\x1F' + + __MEMORY_RW_MAX_SIZE = 256 + __FLASH_LOAD_ADDRESS = 0x08000000 + __FLASH_MAX_LOAD_SIZE = 0x8000 + __RAM_LOAD_ADDRESS = 0x20001000 + __RAM_MAX_LOAD_SIZE = 0x1000 + + DEV_ID_STM32G030XX = b'\x04\x66' + + __connected = False + + def __init__(self, write: Callable[[bytes], None], read: Callable[[int], bytes], progress: Callable[[int, int, str], None]): + self.__write = write + self.__read = read + self.__progress = progress + + def __append_xor(self, data: bytes) -> bytes: + xor = (0xFF if (len(data) == 1) else 0x00) + for b in data: + xor ^= b + return bytes([*data, xor]) + + def __check_ack(self) -> None: + response = self.__read(1) + if (response == None): + raise STM32BootloaderException('No ACK/NACK byte received') + if (response == self.__NACK): + raise STM32BootloaderException('NACK byte received') + if (response != self.__ACK): + raise STM32BootloaderException('Unknown ACK/NACK byte received') + + def __cmd_send(self, cmd: bytes) -> None: + if (len(cmd) != 1): + raise ValueError('Command must contain only one byte') + self.__write(self.__append_xor(cmd)) + self.__check_ack() + + def __data_write(self, data: bytes) -> None: + self.__write(self.__append_xor(data)) + self.__check_ack() + + def __data_read(self) -> bytes: + length = self.__read(1) + if (len(length) != 1): + raise STM32BootloaderException('Did not receive length byte') + length = length[0] + data = self.__read(length + 1) + self.__check_ack() + return data + + def __get_id(self) -> bytes: + self.__cmd_send(b'\x02') + return self.__data_read() + + def __read_memory(self, address: int, length: int) -> bytes: + if (length == 0 or length > self.__MEMORY_RW_MAX_SIZE): + raise ValueError('Wrong data size for read memory command') + self.__cmd_send(b'\x11') + self.__data_write(address.to_bytes(4, byteorder='big')) + self.__data_write(bytes([length - 1])) + return self.__read(length) + + def __go(self, address: int) -> None: + self.__cmd_send(b'\x21') + self.__data_write(address.to_bytes(4, byteorder='big')) + self.__connected = False + + def __write_memory(self, address: int, data: bytes) -> None: + length = len(data) + if (length == 0 or length > self.__MEMORY_RW_MAX_SIZE): + raise ValueError('Wrong data size for write memory command') + if (((address % 4) != 0) or ((length % 4) != 0)): + raise ValueError('Write memory command requires 4 byte alignment') + self.__cmd_send(b'\x31') + self.__data_write(address.to_bytes(4, byteorder='big')) + self.__data_write(bytes([length - 1, *data])) + + def __mass_erase(self) -> None: + self.__cmd_send(b'\x44') + self.__data_write(b'\xFF\xFF') + + def __load_memory(self, address: int, data: bytes, description: str='') -> None: + length = len(data) + self.__progress(length, 0, description) + for offset in range(0, length, self.__MEMORY_RW_MAX_SIZE): + chunk = data[offset:offset + self.__MEMORY_RW_MAX_SIZE] + self.__write_memory(address + offset, chunk) + verify = self.__read_memory(address + offset, len(chunk)) + if (chunk != verify): + raise STM32BootloaderException('Memory verify failed') + self.__progress(length, offset, description) + self.__progress(length, length, description) + + def connect(self, id: int) -> None: + if (not self.__connected): + self.__write(self.__INIT) + self.__check_ack() + self.__connected = True + dev_id = self.__get_id() + if (dev_id != id): + raise STM32BootloaderException('Unknown chip detected') + + def load_ram_and_run(self, data: bytes, description: str='') -> None: + if (len(data) > self.__RAM_MAX_LOAD_SIZE): + raise STM32BootloaderException('RAM image too big') + self.__load_memory(self.__RAM_LOAD_ADDRESS, data, description) + self.__go(self.__RAM_LOAD_ADDRESS) + + def load_flash_and_run(self, data: bytes, description: str='') -> None: + if (len(data) > self.__FLASH_MAX_LOAD_SIZE): + raise STM32BootloaderException('Flash image too big') + self.__mass_erase() + try: + self.__load_memory(self.__FLASH_LOAD_ADDRESS, data, description) + self.__go(self.__FLASH_LOAD_ADDRESS) + except STM32BootloaderException as e: + self.__mass_erase() + raise STM32BootloaderException(e) + + +class LCMXO2PrimerException(Exception): + pass + +class LCMXO2Primer: + __PRIMER_ID_LCMXO2 = b'MXO2' + + __CMD_GET_PRIMER_ID = b'?' + __CMD_PROBE_FPGA = b'#' + __CMD_RESTART = b'$' + __CMD_GET_DEVICE_ID = b'I' + __CMD_ENABLE_FLASH = b'E' + __CMD_ERASE_FLASH = b'X' + __CMD_RESET_ADDRESS = b'A' + __CMD_WRITE_PAGE = b'W' + __CMD_READ_PAGE = b'R' + __CMD_PROGRAM_DONE = b'F' + __CMD_INIT_FEATBITS = b'Q' + __CMD_REFRESH = b'B' + + __FLASH_PAGE_SIZE = 16 + __FLASH_NUM_PAGES = 11260 + + __FPGA_PROBE_VALUE = b'\x64' + + DEV_ID_LCMXO2_7000HC = b'\x01\x2B\xD0\x43' + + def __init__(self, write: Callable[[bytes], None], read: Callable[[int], bytes], progress: Callable[[int, int, str], None]): + self.__write = write + self.__read = read + self.__progress = progress + + def __cmd_execute(self, cmd: bytes, data: bytes=b'') -> bytes: + if (len(cmd) != 1): + raise ValueError('Command must contain only one byte') + if (len(data) >= 256): + raise ValueError('Data size too big') + + packet = b'CMD' + cmd + packet += len(data).to_bytes(1, byteorder='little') + packet += data + packet += crc32(packet).to_bytes(4, byteorder='little') + self.__write(packet) + + response = self.__read(5) + if (len(response) != 5): + raise LCMXO2PrimerException(f'No response received [{cmd}]') + length = int.from_bytes(response[4:5], byteorder='little') + response += self.__read(length) + calculated_checksum = crc32(response) + received_checksum = int.from_bytes(self.__read(4), byteorder='little') + + if (response[0:3] != b'RSP'): + raise LCMXO2PrimerException(f'Invalid response token [{response[0:3]} / {cmd}]') + if (response[3:4] != cmd): + raise LCMXO2PrimerException(f'Invalid response command [{cmd} / {response[3]}]') + if (calculated_checksum != received_checksum): + raise LCMXO2PrimerException(f'Invalid response checksum [{cmd}]') + + return response[5:] + + def connect(self, id: bytes) -> None: + primer_id = self.__cmd_execute(self.__CMD_GET_PRIMER_ID) + if (primer_id != self.__PRIMER_ID_LCMXO2): + raise LCMXO2PrimerException('Invalid primer ID received') + + dev_id = self.__cmd_execute(self.__CMD_GET_DEVICE_ID) + if (dev_id != id): + raise LCMXO2PrimerException('Invalid FPGA device id received') + + def load_flash_and_run(self, data: bytes, description: str) -> None: + erase_description = f'{description} / Erase' + program_description = f'{description} / Program' + verify_description = f'{description} / Verify' + + length = len(data) + if (length > (self.__FLASH_PAGE_SIZE * self.__FLASH_NUM_PAGES)): + raise LCMXO2PrimerException('FPGA data size too big') + if ((length % self.__FLASH_PAGE_SIZE) != 0): + raise LCMXO2PrimerException('FPGA data size not aligned to page size') + + self.__cmd_execute(self.__CMD_ENABLE_FLASH) + + self.__progress(length, 0, erase_description) + self.__cmd_execute(self.__CMD_ERASE_FLASH) + self.__progress(length, length, erase_description) + + try: + self.__cmd_execute(self.__CMD_RESET_ADDRESS) + self.__progress(length, 0, program_description) + for offset in range(0, length, self.__FLASH_PAGE_SIZE): + page_data = data[offset:(offset + self.__FLASH_PAGE_SIZE)] + self.__cmd_execute(self.__CMD_WRITE_PAGE, page_data) + self.__progress(length, offset, program_description) + self.__progress(length, length, program_description) + + self.__cmd_execute(self.__CMD_RESET_ADDRESS) + self.__progress(length, 0, verify_description) + for offset in range(0, length, self.__FLASH_PAGE_SIZE): + page_data = data[offset:(offset + self.__FLASH_PAGE_SIZE)] + verify_data = self.__cmd_execute(self.__CMD_READ_PAGE) + self.__progress(length, offset, verify_description) + if (page_data != verify_data): + raise LCMXO2PrimerException('FPGA verification error') + self.__progress(length, length, verify_description) + + self.__cmd_execute(self.__CMD_INIT_FEATBITS) + + self.__cmd_execute(self.__CMD_PROGRAM_DONE) + + self.__cmd_execute(self.__CMD_REFRESH) + + if (self.__cmd_execute(self.__CMD_PROBE_FPGA) != self.__FPGA_PROBE_VALUE): + raise LCMXO2PrimerException('Invalid FPGA ID value received') + + except LCMXO2PrimerException as e: + self.__cmd_execute(self.__CMD_ENABLE_FLASH) + self.__cmd_execute(self.__CMD_ERASE_FLASH) + self.__cmd_execute(self.__CMD_REFRESH) + self.__cmd_execute(self.__CMD_RESTART) + raise LCMXO2PrimerException(e) + + self.__cmd_execute(self.__CMD_RESTART) + + +class SC64Exception(Exception): + pass + +class SC64: + __serial: Optional[serial.Serial] = None + __packets = queue.Queue() + + class __UpdateStatus(IntEnum): + MCU = 1 + FPGA = 2 + BOOTLOADER = 3 + DONE = 0x80 + ERROR = 0xFF + + def __init__(self) -> None: + SC64_VID = 0x0403 + SC64_PID = 0x6014 + SC64_SID = "SC64" + for p in list_ports.comports(): + if (p.vid == SC64_VID and p.pid == SC64_PID and p.serial_number.startswith(SC64_SID)): + try: + self.__serial = serial.Serial(p.device, timeout=10.0, write_timeout=10.0) + except serial.SerialException: + if (self.__serial): + self.__serial.close() + continue + return + raise SC64Exception('No SC64 USB device found') + + def __reset(self) -> None: + WAIT_DURATION = 0.01 + RETRY_COUNT = 100 + + self.__serial.dtr = 1 + for n in range(0, RETRY_COUNT + 1): + self.__serial.reset_input_buffer() + self.__serial.reset_output_buffer() + time.sleep(WAIT_DURATION) + if (self.__serial.dsr == 1): + break + if n == RETRY_COUNT: + raise SC64Exception('Couldn\'t reset SC64 device (on)') + + self.__serial.dtr = 0 + for n in range(0, RETRY_COUNT + 1): + time.sleep(WAIT_DURATION) + if (self.__serial.dsr == 0): + break + if n == RETRY_COUNT: + raise SC64Exception('Couldn\'t reset SC64 device (on)') + + def __process_incoming_data(self, wait_for_response: bool) -> Optional[tuple[bytes, bytes]]: + while (wait_for_response or self.__serial.in_waiting >= 4): + buffer = self.__serial.read(4) + token = buffer[0:3] + id = buffer[3:4] + if (token == b'CMP'): + length = int.from_bytes(self.__serial.read(4), byteorder='big') + data = self.__serial.read(length) + return (id, data) + elif (token == b'PKT'): + length = int.from_bytes(self.__serial.read(4), byteorder='big') + data = self.__serial.read(length) + self.__packets.put((id, data)) + if (not wait_for_response): + break + elif (token == b'ERR'): + raise SC64Exception('Command response error') + else: + raise SC64Exception('Invalid token received') + return None + + def __execute_command(self, cmd: bytes, args: list[int]=[0, 0], data: bytes=b'') -> bytes: + if (len(cmd) != 1): + raise SC64Exception('Length of command is different than 1 byte') + if (len(args) != 2): + raise SC64Exception('Number of arguments is different than 2') + try: + self.__serial.write(b'CMD' + cmd) + self.__serial.write(args[0].to_bytes(4, byteorder='big')) + self.__serial.write(args[1].to_bytes(4, byteorder='big')) + if (len(data) > 0): + self.__serial.write(data) + self.__serial.flush() + (id, response) = self.__process_incoming_data(True) + if (cmd != id): + raise SC64Exception('Command response ID didn\'t match') + return response + except serial.SerialException as e: + raise SC64Exception(f'Serial exception: {e}') + + def __receive_data_packet(self) -> Optional[tuple[bytes, bytes]]: + if (self.__packets.empty()): + try: + if (self.__process_incoming_data(False) != None): + raise SC64Exception('Unexpected command response') + except serial.SerialException as e: + raise SC64Exception(f'Serial exception: {e}') + if (not self.__packets.empty()): + packet = self.__packets.get() + self.__packets.task_done() + return packet + return None + + def update_firmware(self, data: bytes) -> None: + FIRMWARE_ADDRESS = 0x00100000 + FIRMWARE_UPDATE_TIMEOUT = 90.0 + + self.__reset() + self.__execute_command(b'R') + self.__execute_command(b'M', [FIRMWARE_ADDRESS, len(data)], data) + self.__execute_command(b'F', [FIRMWARE_ADDRESS, len(data)]) + + timeout = time.time() + FIRMWARE_UPDATE_TIMEOUT + while True: + if (time.time() > timeout): + raise SC64Exception('Firmware update timeout') + packet = self.__receive_data_packet() + if (packet == None): + time.sleep(0.001) + continue + (id, packet_data) = packet + if (id != b'F'): + raise SC64Exception('Unexpected packet id received') + status = self.__UpdateStatus(int.from_bytes(packet_data[0:4], byteorder='big')) + if (status == self.__UpdateStatus.ERROR): + raise SC64Exception('Firmware update error') + if (status == self.__UpdateStatus.DONE): + time.sleep(2) + break + + +class SC64BringUp: + __SERIAL_BAUD: int = 115200 + __SERIAL_TIMEOUT: float = 6.0 + __INTERVAL_TIME: float = 0.5 + + def __init__(self, progress: Callable[[int, int, str], None]) -> None: + self.__progress = progress + + def load_update_data(self, path: str) -> None: + self.__sc64_update_data = SC64UpdateData() + self.__sc64_update_data.load(path, require_all=True) + self.__bootloader_only_firmware = self.__sc64_update_data.create_bootloader_only_firmware() + + def get_update_info(self) -> str: + return self.__sc64_update_data.get_update_info() + + def start_bring_up(self, port: str, bootloader_only: bool=False) -> None: + link = None + sc64 = SC64() + + try: + if (not bootloader_only): + link = serial.Serial( + port, + baudrate=self.__SERIAL_BAUD, + parity=serial.PARITY_EVEN, + timeout=self.__SERIAL_TIMEOUT, + write_timeout=self.__SERIAL_TIMEOUT + ) + + stm32_bootloader = STM32Bootloader(link.write, link.read, self.__progress) + lcmxo2_primer = LCMXO2Primer(link.write, link.read, self.__progress) + + stm32_bootloader.connect(stm32_bootloader.DEV_ID_STM32G030XX) + stm32_bootloader.load_ram_and_run(self.__sc64_update_data.get_primer_data(), 'FPGA primer -> STM32 RAM') + time.sleep(self.__INTERVAL_TIME) + link.read_all() + + lcmxo2_primer.connect(lcmxo2_primer.DEV_ID_LCMXO2_7000HC) + lcmxo2_primer.load_flash_and_run(self.__sc64_update_data.get_fpga_data(), 'FPGA configuration -> LCMXO2 FLASH') + time.sleep(self.__INTERVAL_TIME) + link.read_all() + + stm32_bootloader.connect(stm32_bootloader.DEV_ID_STM32G030XX) + stm32_bootloader.load_flash_and_run(self.__sc64_update_data.get_mcu_data(), 'MCU software -> STM32 FLASH') + time.sleep(self.__INTERVAL_TIME) + link.read_all() + + bootloader_description = 'Bootloader -> SC64 FLASH (no progress reporting)' + bootloader_length = len(self.__bootloader_only_firmware) + self.__progress(bootloader_length, 0, bootloader_description) + sc64.update_firmware(self.__bootloader_only_firmware) + self.__progress(bootloader_length, bootloader_length, bootloader_description) + finally: + if (link and link.is_open): + link.close() + + +if __name__ == '__main__': + nargs = len(sys.argv) + if (nargs < 3 or nargs > 4): + Utils.die(f'Usage: {sys.argv[0]} serial_port update_file [--bootloader-only]') + + port = sys.argv[1] + update_data_path = sys.argv[2] + bootloader_only = False + if (nargs == 4): + if (sys.argv[3] == '--bootloader-only'): + bootloader_only = True + else: + Utils.die(f'Unknown argument: {sys.argv[3]}') + + utils = Utils() + sc64_bring_up = SC64BringUp(progress=utils.progress) + + Utils.log() + Utils.info('[ Welcome to SC64 flashcart board bring-up! ]') + Utils.log() + + Utils.log(f'Serial port: {port}') + Utils.log(f'Update data path: {os.path.abspath(update_data_path)}') + try: + sc64_bring_up.load_update_data(update_data_path) + except SC64UpdateDataException as e: + Utils.die(f'Provided \'{update_data_path}\' file is invalid: {e}') + Utils.log('Update info: ') + Utils.log(sc64_bring_up.get_update_info()) + Utils.log() + + if bootloader_only: + Utils.log('Running in "bootloader only" mode') + Utils.log() + + Utils.warning('[ CAUTION ]') + Utils.warning('Configure FTDI chip with provided ft232h_config.xml before continuing') + Utils.warning('Connect SC64 USB port to the same computer you\'re running this script') + Utils.warning('Make sure SC64 USB port is recognized in system before continuing') + Utils.log() + + Utils.warning('[ IMPORTANT ]') + Utils.warning('Unplug SC64 board from power and reconnect it before proceeding') + Utils.log() + + try: + if (input('Type YES to continue: ') != 'YES'): + Utils.die('No confirmation received. Exiting') + Utils.log() + except KeyboardInterrupt: + Utils.log() + Utils.die('Aborted') + + original_sigint_handler = signal.getsignal(signal.SIGINT) + try: + signal.signal(signal.SIGINT, lambda *kwargs: utils.exit_warning()) + sc64_bring_up.start_bring_up(port, bootloader_only) + except (serial.SerialException, STM32BootloaderException, LCMXO2PrimerException, SC64Exception) as e: + if (utils.get_progress_active): + Utils.log() + Utils.die(f'Error while running bring-up: {e}') + finally: + signal.signal(signal.SIGINT, original_sigint_handler) + + Utils.log() + Utils.info('[ SC64 flashcart board bring-up finished successfully! ]') + Utils.log() diff --git a/sw/pc/requirements.txt b/sw/tools/requirements.txt similarity index 50% rename from sw/pc/requirements.txt rename to sw/tools/requirements.txt index c3f0da9..d0dfd58 100644 --- a/sw/pc/requirements.txt +++ b/sw/tools/requirements.txt @@ -1,2 +1 @@ -Pillow==9.2.0 pyserial==3.5 diff --git a/sw/update/update.py b/sw/tools/update.py old mode 100755 new mode 100644 similarity index 95% rename from sw/update/update.py rename to sw/tools/update.py index 2889056..3b0c338 --- a/sw/update/update.py +++ b/sw/tools/update.py @@ -145,13 +145,13 @@ class JedecFile: class SC64UpdateData: - __UPDATE_TOKEN = b'SC64 Update v2.0' + __UPDATE_TOKEN = b'SC64 Update v2.0' - __CHUNK_ID_UPDATE_INFO = 1 - __CHUNK_ID_MCU_DATA = 2 - __CHUNK_ID_FPGA_DATA = 3 - __CHUNK_ID_BOOTLOADER_DATA = 4 - __CHUNK_ID_PRIMER_DATA = 5 + __CHUNK_ID_UPDATE_INFO = 1 + __CHUNK_ID_MCU_DATA = 2 + __CHUNK_ID_FPGA_DATA = 3 + __CHUNK_ID_BOOTLOADER_DATA = 4 + __CHUNK_ID_PRIMER_DATA = 5 __data = b'' @@ -219,13 +219,12 @@ if __name__ == "__main__": hostname = platform.node() creation_datetime = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S') - info = [ - f'build system: [{hostname}]', - f'creation datetime: [{creation_datetime}]', - ] + update_info = '\n'.join([ + f'builder: {hostname}', + f'created: {creation_datetime}', + ]) if (args.git): - info.append(args.git) - update_info = ' '.join(info) + update_info += args.git print(update_info) update.add_update_info(update_info.encode()) diff --git a/sw/update/.gitignore b/sw/update/.gitignore deleted file mode 100644 index 4cfd978..0000000 --- a/sw/update/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.bin