Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/fceux.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/automerge.yml43
-rw-r--r--.github/workflows/cmake_linux.yml65
-rw-r--r--.github/workflows/cmake_macos.yml64
-rw-r--r--.github/workflows/msbuild_win_x64.yml62
-rw-r--r--.github/workflows/msbuild_win_x86.yml62
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/boards/coolgirl.cpp2252
-rw-r--r--src/boards/warface.cpp99
-rw-r--r--src/ines.cpp5
-rw-r--r--src/state.cpp2
-rw-r--r--src/unif.cpp3
-rw-r--r--src/unif.h2
-rw-r--r--src/version.h2
-rw-r--r--vc/vc14_fceux.vcxproj2
-rw-r--r--vc/vc14_fceux.vcxproj.filters6
15 files changed, 2667 insertions, 4 deletions
diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml
new file mode 100644
index 00000000..03158a22
--- /dev/null
+++ b/.github/workflows/automerge.yml
@@ -0,0 +1,43 @@
+name: Auto-merge
+
+on:
+ workflow_dispatch:
+ schedule:
+ - cron: '0 0 * * *'
+
+env:
+ MY_REPO: https://ClusterM:${{secrets.GITHUB_TOKEN}}@github.com/ClusterM/fceux.git
+ MY_BRANCH: coolgirl
+ MASTER_REPO: https://github.com/TASVideos/fceux.git
+ MASTER_BRANCH: master
+
+jobs:
+ merge:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Merge with the master
+ run: |
+ git clone ${{env.MY_REPO}} -b ${{env.MY_BRANCH}} tmp
+ cd tmp
+ OLD_COMMIT=$(git rev-parse HEAD)
+ git config user.name "Automerge Bot"
+ git config user.email "bot@example.com"
+ git config pull.rebase false
+ git pull ${{env.MASTER_REPO}} ${{env.MASTER_BRANCH}}
+ NEW_COMMIT=$(git rev-parse HEAD)
+ git push
+ if [ "$OLD_COMMIT" != "$NEW_COMMIT" ]
+ then
+ echo "::warning::Successfully merged with master branch"
+ echo "::warning::New commit: $NEW_COMMIT"
+ echo "Lets send rebuild request!"
+ OUTPUT=$(curl -s -X POST https://api.github.com/repos/ClusterM/fceux/dispatches -H 'Accept: application/vnd.github.everest-preview+json' -u ${{secrets.DISPATCH_KEY}} --data '{"event_type": "Automerge-rebuild"}')
+ if [ ! -z "$OUTPUT" ]
+ then
+ echo "::error curl output: $OUTPUT"
+ exit 1
+ fi
+ else
+ echo "::warning::Everything is already up to date"
+ fi
diff --git a/.github/workflows/cmake_linux.yml b/.github/workflows/cmake_linux.yml
new file mode 100644
index 00000000..aa4e76e6
--- /dev/null
+++ b/.github/workflows/cmake_linux.yml
@@ -0,0 +1,65 @@
+name: Ubuntu Linux
+
+on:
+ push:
+ branches: [ coolgirl ]
+ pull_request:
+ branches: [ coolgirl ]
+ workflow_dispatch:
+ repository_dispatch:
+ types: [Automerge-rebuild]
+
+env:
+ BUILD_TYPE: Release
+ INSTALL_PREFIX: /tmp/fceux
+
+jobs:
+ build_and_deploy:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+
+ - name: Installing Package Dependencies
+ run: |
+ sudo apt-get --assume-yes update
+ sudo apt-get --assume-yes install lua5.1-dev
+ pkg-config --cflags --libs lua5.1
+ sudo apt-get --assume-yes install libsdl2-dev
+ sdl2-config --cflags --libs
+ sudo apt-get --assume-yes install libminizip-dev
+ pkg-config --cflags --libs minizip
+ sudo apt-get --assume-yes install qt5-default
+ sudo apt-get --assume-yes install qttools5-dev
+ sudo apt-get --assume-yes install libx264-dev
+ sudo apt-get --assume-yes install cppcheck
+
+ - name: Build
+ run: |
+ ./scripts/unix_make_docs.sh
+ mkdir -p $INSTALL_PREFIX/usr
+ mkdir buildQT
+ cd buildQT
+ cmake -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON ..
+ make -j $(nproc)
+ make install DESTDIR=${{env.INSTALL_PREFIX}}
+
+ - name: Create Debian Package
+ run: |
+ sed -i 's/Package: fceux/Package: fceux-coolgirl/g' ./pipelines/debpkg.pl
+ ./pipelines/debpkg.pl
+
+ - name: Test
+ run: sudo dpkg -i /tmp/fceux-*.deb
+
+ - name: Upload artifact
+ uses: actions/upload-artifact@v2
+ with:
+ name: fceux-ubuntu
+ path: /tmp/fceux-*.deb
+
+ - name: Upload to the site
+ if: github.event_name != 'pull_request'
+ run: |
+ curl -F "file=@$(find /tmp -maxdepth 1 -name fceux-*.deb)" -F 'key=${{secrets.UPLOADER_KEY}}' -F 'name=fceux.deb' '${{secrets.UPLOADER_URL}}'
diff --git a/.github/workflows/cmake_macos.yml b/.github/workflows/cmake_macos.yml
new file mode 100644
index 00000000..81a87fb7
--- /dev/null
+++ b/.github/workflows/cmake_macos.yml
@@ -0,0 +1,64 @@
+name: macOS
+
+on:
+ push:
+ branches: [ coolgirl ]
+ pull_request:
+ branches: [ coolgirl ]
+ workflow_dispatch:
+ repository_dispatch:
+ types: [Automerge-rebuild]
+
+env:
+ BUILD_TYPE: Release
+ INSTALL_PREFIX: /tmp/fceux
+ QT_PKGNAME: qt5
+ FCEUX_VERSION_MAJOR: 2
+ FCEUX_VERSION_MINOR: 4
+ FCEUX_VERSION_PATCH: 0
+
+jobs:
+ build_and_deploy:
+ runs-on: macos-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+
+ - name: Installing Package Dependencies
+ run: |
+ brew install sdl2
+ brew install ${{env.QT_PKGNAME}}
+ brew install minizip
+ brew install x264
+
+ - name: Build
+ run: |
+ ./scripts/unix_make_docs.sh
+ PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig:
+ export Qt5_DIR=$(brew --prefix qt5)
+ echo "Qt5_DIR=$Qt5_DIR"
+ Qt_DIR=$Qt5_DIR
+ mkdir build
+ cd build
+ cmake -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INSTALL_PREFIX=${{env.INSTALL_PREFIX}} -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DCMAKE_PREFIX_PATH=$Qt_DIR -DCMAKE_PROJECT_VERSION_MAJOR=${{env.FCEUX_VERSION_MAJOR}} -DCMAKE_PROJECT_VERSION_MINOR=${{env.FCEUX_VERSION_MINOR}} -DCMAKE_PROJECT_VERSION_PATCH=${{env.FCEUX_VERSION_PATCH}} -DCPACK_PACKAGE_VERSION_MAJOR=${{env.FCEUX_VERSION_MAJOR}} -DCPACK_PACKAGE_VERSION_MINOR=${{env.FCEUX_VERSION_MINOR}} -DCPACK_PACKAGE_VERSION_PATCH=${{env.FCEUX_VERSION_PATCH}} -DQT6=0 ..
+ make -j $(getconf _NPROCESSORS_ONLN)
+
+ - name: Install
+ working-directory: build
+ run: sudo make install
+
+ - name: Make package
+ working-directory: build
+ run: sudo cpack -G DragNDrop
+
+ - name: Upload artifact
+ uses: actions/upload-artifact@v2
+ with:
+ name: fceux-macos
+ path: build/fceux-*.dmg
+
+ - name: Upload to the site
+ if: github.event_name != 'pull_request'
+ working-directory: build
+ run: curl -F "file=@$(find . -maxdepth 1 -name fceux-*.dmg)" -F 'key=${{secrets.UPLOADER_KEY}}' -F 'name=fceux.dmg' '${{secrets.UPLOADER_URL}}'
diff --git a/.github/workflows/msbuild_win_x64.yml b/.github/workflows/msbuild_win_x64.yml
new file mode 100644
index 00000000..4b68948d
--- /dev/null
+++ b/.github/workflows/msbuild_win_x64.yml
@@ -0,0 +1,62 @@
+name: Windows (x64)
+
+on:
+ push:
+ branches: [ coolgirl ]
+ pull_request:
+ branches: [ coolgirl ]
+ workflow_dispatch:
+ repository_dispatch:
+ types: [Automerge-rebuild]
+
+env:
+ SOLUTION_FILE_PATH: vc/vc14_fceux.vcxproj
+ BUILD_CONFIGURATION: Release
+ PLATFORM: x64
+ OUTPUT_FILE: fceux64.zip
+ OUTPUT_SUBDIRECTORY: fceux64
+
+jobs:
+ build_and_deploy:
+ runs-on: windows-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+
+ - name: Add MSBuild to PATH
+ uses: microsoft/setup-msbuild@v1.0.2
+
+ - name: Build
+ run: msbuild ${{env.SOLUTION_FILE_PATH}} /p:Configuration=${{env.BUILD_CONFIGURATION}} /p:Platform=${{env.PLATFORM}}
+
+ - name: Prepare directory
+ working-directory: output
+ run: |
+ mkdir ${{env.OUTPUT_SUBDIRECTORY}}
+ move palettes ${{env.OUTPUT_SUBDIRECTORY}}
+ move luaScripts ${{env.OUTPUT_SUBDIRECTORY}}
+ move tools ${{env.OUTPUT_SUBDIRECTORY}}
+ move ..\vc\x64\Release\fceux64.exe ${{env.OUTPUT_SUBDIRECTORY}}
+ move ..\src\drivers\win\lua\x64\lua5.1.dll ${{env.OUTPUT_SUBDIRECTORY}}
+ move ..\src\drivers\win\lua\x64\lua51.dll ${{env.OUTPUT_SUBDIRECTORY}}
+ move ..\src\auxlib.lua ${{env.OUTPUT_SUBDIRECTORY}}
+ move ..\src\drivers\win\7z_64.dll ${{env.OUTPUT_SUBDIRECTORY}}
+ move fceux.chm ${{env.OUTPUT_SUBDIRECTORY}}
+ move taseditor.chm ${{env.OUTPUT_SUBDIRECTORY}}
+
+ - name: Upload artifact
+ uses: actions/upload-artifact@v2
+ with:
+ name: fceux-win64
+ path: output/${{env.OUTPUT_SUBDIRECTORY}}
+
+ - name: Archive
+ working-directory: output
+ run: |
+ ..\vc\zip -X -9 -r ${{env.OUTPUT_FILE}} ${{env.OUTPUT_SUBDIRECTORY}}
+
+ - name: Upload to the site
+ if: github.event_name != 'pull_request'
+ working-directory: output
+ run: curl -F 'file=@${{env.OUTPUT_FILE}}' -F 'key=${{secrets.UPLOADER_KEY}}' '${{secrets.UPLOADER_URL}}'
diff --git a/.github/workflows/msbuild_win_x86.yml b/.github/workflows/msbuild_win_x86.yml
new file mode 100644
index 00000000..a5152905
--- /dev/null
+++ b/.github/workflows/msbuild_win_x86.yml
@@ -0,0 +1,62 @@
+name: Windows (x86)
+
+on:
+ push:
+ branches: [ coolgirl ]
+ pull_request:
+ branches: [ coolgirl ]
+ workflow_dispatch:
+ repository_dispatch:
+ types: [Automerge-rebuild]
+
+env:
+ SOLUTION_FILE_PATH: vc/vc14_fceux.vcxproj
+ BUILD_CONFIGURATION: Release
+ PLATFORM: Win32
+ OUTPUT_FILE: fceux.zip
+ OUTPUT_SUBDIRECTORY: fceux
+
+jobs:
+ build_and_deploy:
+ runs-on: windows-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+
+ - name: Add MSBuild to PATH
+ uses: microsoft/setup-msbuild@v1.0.2
+
+ - name: Build
+ run: msbuild ${{env.SOLUTION_FILE_PATH}} /p:Configuration=${{env.BUILD_CONFIGURATION}} /p:Platform=${{env.PLATFORM}}
+
+ - name: Prepare directory
+ working-directory: output
+ run: |
+ mkdir ${{env.OUTPUT_SUBDIRECTORY}}
+ move palettes ${{env.OUTPUT_SUBDIRECTORY}}
+ move luaScripts ${{env.OUTPUT_SUBDIRECTORY}}
+ move tools ${{env.OUTPUT_SUBDIRECTORY}}
+ move fceux.exe ${{env.OUTPUT_SUBDIRECTORY}}
+ move lua5.1.dll ${{env.OUTPUT_SUBDIRECTORY}}
+ move lua51.dll ${{env.OUTPUT_SUBDIRECTORY}}
+ move auxlib.lua ${{env.OUTPUT_SUBDIRECTORY}}
+ move 7z.dll ${{env.OUTPUT_SUBDIRECTORY}}
+ move fceux.chm ${{env.OUTPUT_SUBDIRECTORY}}
+ move taseditor.chm ${{env.OUTPUT_SUBDIRECTORY}}
+
+ - name: Upload artifact
+ uses: actions/upload-artifact@v2
+ with:
+ name: fceux-win32
+ path: output/${{env.OUTPUT_SUBDIRECTORY}}
+
+ - name: Archive
+ working-directory: output
+ run: |
+ ..\vc\zip -X -9 -r ${{env.OUTPUT_FILE}} ${{env.OUTPUT_SUBDIRECTORY}}
+
+ - name: Upload to the site
+ if: github.event_name != 'pull_request'
+ working-directory: output
+ run: curl -F 'file=@${{env.OUTPUT_FILE}}' -F 'key=${{secrets.UPLOADER_KEY}}' '${{secrets.UPLOADER_URL}}'
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c4dc2b02..b2097593 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -467,6 +467,8 @@ set(SRC_CORE
${CMAKE_CURRENT_SOURCE_DIR}/boards/vrc7.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/vrc7p.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/yoko.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/boards/coolgirl.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/boards/warface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/input/arkanoid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/input/bworld.cpp
${CMAKE_CURRENT_SOURCE_DIR}/input/cursor.cpp
diff --git a/src/boards/coolgirl.cpp b/src/boards/coolgirl.cpp
new file mode 100644
index 00000000..cf4abb66
--- /dev/null
+++ b/src/boards/coolgirl.cpp
@@ -0,0 +1,2252 @@
+/* FCE Ultra - NES/Famicom Emulator
+*
+* Copyright notice for this file:
+* Copyright (C) 2020 Cluster
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "mapinc.h"
+
+const uint32 SAVE_FLASH_SIZE = 1024 * 1024 * 8;
+const int ROM_CHIP = 0x00;
+const int SRAM_CHIP = 0x10;
+const int FLASH_CHIP = 0x11;
+const int CHR_RAM_CHIP = 0x12;
+const int CFI_CHIP = 0x13;
+
+static uint32 SRAM_SIZE = 0;
+static uint8 *SRAM = NULL;
+static uint32 CHR_RAM_SIZE = 0;
+static uint8 *CHR_RAM;
+static uint8 *SAVE_FLASH = NULL;
+static uint8 *CFI = NULL;
+
+static uint8 sram_enabled = 0;
+static uint8 sram_page = 0; // [1:0]
+static uint8 can_write_chr = 0;
+static uint8 map_rom_on_6000 = 0;
+static uint8 flags = 0; // [2:0]
+static uint8 mapper = 0; // [5:0]
+static uint8 can_write_flash = 0;
+static uint8 mirroring = 0; // [1:0]
+static uint8 four_screen = 0;
+static uint8 lockout = 0;
+
+static uint32 prg_base = 0; // [26:14]
+static uint32 prg_mask = 0b11111000 << 14; // 11111000, 128KB // [20:14]
+static uint8 prg_mode = 0; // [2:0]
+static uint8 prg_bank_6000 = 0; // [7:0]
+static uint8 prg_bank_a = 0; // [7:0]
+static uint8 prg_bank_b = 1; // [7:0]
+static uint8 prg_bank_c = ~1; // [7:0]
+static uint8 prg_bank_d = ~0; // [7:0]
+
+static uint32 chr_mask = 0; // [18:13]
+static uint8 chr_mode = 0; // [2:0]
+static uint16 chr_bank_a = 0; // [8:0]
+static uint16 chr_bank_b = 1; // [8:0]
+static uint16 chr_bank_c = 2; // [8:0]
+static uint16 chr_bank_d = 3; // [8:0]
+static uint16 chr_bank_e = 4; // [8:0]
+static uint16 chr_bank_f = 5; // [8:0]
+static uint16 chr_bank_g = 6; // [8:0]
+static uint16 chr_bank_h = 7; // [8:0]
+
+static uint8 TKSMIR[8];
+
+static uint32 prg_bank_6000_mapped = 0;
+static uint32 prg_bank_a_mapped = 0;
+static uint32 prg_bank_b_mapped = 0;
+static uint32 prg_bank_c_mapped = 0;
+static uint32 prg_bank_d_mapped = 0;
+
+// for MMC2/MMC4
+static uint8 ppu_latch0 = 0;
+static uint8 ppu_latch1 = 0;
+// for MMC1
+static uint64 lreset = 0;
+static uint8 mmc1_load_register = 0; // [5:0]
+// for MMC3
+static uint8 mmc3_internal = 0; // [2:0]
+// for mapper #69
+static uint8 mapper69_internal = 0; // [3:0]
+// for mapper #112
+static uint8 mapper112_internal = 0; // [2:0]
+// for mapper #163
+static uint8 mapper_163_latch = 0;
+static uint8 mapper163_r0 = 0; // [7:0]
+static uint8 mapper163_r1 = 0; // [7:0]
+static uint8 mapper163_r2 = 0; // [7:0]
+static uint8 mapper163_r3 = 0; // [7:0]
+static uint8 mapper163_r4 = 0; // [7:0]
+static uint8 mapper163_r5 = 0; // [7:0]
+
+// For mapper #90
+static uint8 mul1 = 0;
+static uint8 mul2 = 0;
+
+// for MMC3 scanline-based interrupts, counts A12 rises after long A12 falls
+static uint8 mmc3_irq_enabled = 0; // register to enable/disable counter
+static uint8 mmc3_irq_latch = 0; // [7:0], stores counter reload latch value
+static uint8 mmc3_irq_counter = 0; // [7:0], counter itself (downcounting)
+static uint8 mmc3_irq_reload = 0; // flag to reload counter from latch
+// for MMC5 scanline-based interrupts, counts dummy PPU reads
+static uint8 mmc5_irq_enabled = 0; // register to enable/disable counter
+static uint8 mmc5_irq_line = 0; // [7:0], scanline on which IRQ will be triggered
+static uint8 mmc5_irq_out = 0; // stores 1 when IRQ is triggered
+// for mapper #18
+static uint16 mapper18_irq_value = 0; // [15:0], counter itself (downcounting)
+static uint8 mapper18_irq_control = 0; // [3:0], IRQ settings
+static uint16 mapper18_irq_latch = 0; // [15:0], stores counter reload latch value
+// for mapper #65
+static uint8 mapper65_irq_enabled = 0; // register to enable/disable IRQ
+static uint16 mapper65_irq_value = 0; // [15:0], counter itself (downcounting)
+static uint16 mapper65_irq_latch = 0; // [15:0], stores counter reload latch value
+// reg mapper65_irq_out = 0;
+// for Sunsoft FME-7
+static uint8 mapper69_irq_enabled = 0; // register to enable/disable IRQ
+static uint8 mapper69_counter_enabled = 0; // register to enable/disable counter
+static uint16 mapper69_irq_value = 0; // counter itself (downcounting)
+// for VRC4 CPU-based interrupts
+static uint8 vrc4_irq_value = 0; // [7:0], counter itself (upcounting)
+static uint8 vrc4_irq_control = 0; // [2:0]á IRQ settings
+static uint8 vrc4_irq_latch = 0; // [7:0], stores counter reload latch value
+static uint8 vrc4_irq_prescaler = 0; // [6:0], prescaler counter for VRC4
+static uint8 vrc4_irq_prescaler_counter = 0; // prescaler cicles counter for VRC4
+// for VRC3 CPU-based interrupts
+static uint16 vrc3_irq_value = 0; // [15:0], counter itself (upcounting)
+static uint8 vrc3_irq_control = 0; // [3:0], IRQ settings
+static uint16 vrc3_irq_latch = 0; // [15:0], stores counter reload latch value
+// for mapper #42 (only Baby Mario)
+static uint8 mapper42_irq_enabled = 0; // register to enable/disable counter
+static uint16 mapper42_irq_value = 0; // [14:0], counter itself (upcounting)
+// for mapper #83
+static uint8 mapper83_irq_enabled_latch = 0;
+static uint8 mapper83_irq_enabled = 0;
+static uint16 mapper83_irq_counter = 0;
+// for mapper #90
+static uint8 mapper90_xor = 0;
+// for mapper #67
+static uint8 mapper67_irq_enabled = 0;
+static uint8 mapper67_irq_latch = 0;
+static uint16 mapper67_irq_counter = 0;
+
+static uint8 flash_state = 0;
+static uint16 flash_buffer_a[10];
+static uint8 flash_buffer_v[10];
+static uint8 cfi_mode = 0;
+const uint8 cfi_data[] =
+{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x51, 0x51, 0x52, 0x52, 0x59, 0x59, 0x02, 0x02, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x27, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06,
+ 0x06, 0x06, 0x09, 0x09, 0x13, 0x13, 0x03, 0x03, 0x05, 0x05, 0x03, 0x03, 0x02, 0x02, 0x1E, 0x1E,
+ 0x02, 0x02, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x01, 0x01, 0xFF, 0xFF, 0x03, 0x03, 0x00, 0x00,
+ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x50, 0x50, 0x52, 0x52, 0x49, 0x49, 0x31, 0x31, 0x33, 0x33, 0x14, 0x14, 0x02, 0x02, 0x01, 0x01,
+ 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0xB5, 0xB5, 0xC5, 0xC5, 0x05, 0x05,
+ 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
+#define SET_BITS(target, target_bits, source, source_bits) target = set_bits(target, target_bits, get_bits(source, source_bits))
+
+static inline uint8 string_to_bits(char* bitsstr, int* bits)
+{
+ uint8 bit1, bit2, count = 0;
+ for (int i = 0; i < 32; i++)
+ bits[i] = -1;
+ while (*bitsstr)
+ {
+ bit1 = 0;
+ bit2 = 0;
+ if (isdigit(*bitsstr))
+ {
+ while (isdigit(*bitsstr))
+ {
+ bit1 *= 10;
+ bit1 += *bitsstr - '0';
+ bitsstr++;
+ }
+ if (*bitsstr == ':')
+ {
+ bitsstr++;
+ while (isdigit(*bitsstr))
+ {
+ bit2 *= 10;
+ bit2 += *bitsstr - '0';
+ bitsstr++;
+ }
+ if (bit2 < bit1)
+ for (int i = bit1; i >= bit2; i--)
+ {
+ bits[count] = i;
+ count++;
+ }
+ else
+ for (int i = bit1; i <= bit2; i++)
+ {
+ bits[count] = i;
+ count++;
+ }
+ }
+ else {
+ bits[count] = bit1;
+ count++;
+ }
+ }
+ else {
+ bitsstr++;
+ }
+ }
+ return count;
+}
+
+static inline uint32 get_bits(uint32 V, char* bitsstr)
+{
+ uint32 result = 0;
+ int bits[32];
+ string_to_bits(bitsstr, bits);
+ for (int i = 0; bits[i] >= 0; i++)
+ {
+ result <<= 1;
+ result |= (V >> bits[i]) & 1;
+ }
+ return result;
+}
+
+static inline uint32 set_bits(uint32 V, char* bitsstr, uint32 new_bits)
+{
+ int bits[32];
+ uint8 count = string_to_bits(bitsstr, bits);
+ for (int i = 0; i < count; i++)
+ {
+ if ((new_bits >> (count - i - 1)) & 1)
+ V |= 1 << bits[i];
+ else
+ V &= ~(1 << bits[i]);
+ }
+ return V;
+}
+
+static void COOLGIRL_Sync_PRG(void) {
+ prg_bank_6000_mapped = (prg_base >> 13) | (prg_bank_6000 & ((~(prg_mask >> 13) & 0xFE) | 1));
+ prg_bank_a_mapped = (prg_base >> 13) | (prg_bank_a & ((~(prg_mask >> 13) & 0xFE) | 1));
+ prg_bank_b_mapped = (prg_base >> 13) | (prg_bank_b & ((~(prg_mask >> 13) & 0xFE) | 1));
+ prg_bank_c_mapped = (prg_base >> 13) | (prg_bank_c & ((~(prg_mask >> 13) & 0xFE) | 1));
+ prg_bank_d_mapped = (prg_base >> 13) | (prg_bank_d & ((~(prg_mask >> 13) & 0xFE) | 1));
+ uint8 REG_A_CHIP = (prg_bank_a_mapped >= 0x20000 - SAVE_FLASH_SIZE / 1024 / 8) ? FLASH_CHIP : ROM_CHIP;
+ uint8 REG_B_CHIP = (prg_bank_b_mapped >= 0x20000 - SAVE_FLASH_SIZE / 1024 / 8) ? FLASH_CHIP : ROM_CHIP;
+ uint8 REG_C_CHIP = (prg_bank_c_mapped >= 0x20000 - SAVE_FLASH_SIZE / 1024 / 8) ? FLASH_CHIP : ROM_CHIP;
+ uint8 REG_D_CHIP = (prg_bank_d_mapped >= 0x20000 - SAVE_FLASH_SIZE / 1024 / 8) ? FLASH_CHIP : ROM_CHIP;
+
+ if (!cfi_mode)
+ {
+ switch (prg_mode & 7)
+ {
+ default:
+ case 0:
+ setprg16r(REG_A_CHIP, 0x8000, prg_bank_a_mapped >> 1);
+ setprg16r(REG_C_CHIP, 0xC000, prg_bank_c_mapped >> 1);
+ break;
+ case 1:
+ setprg16r(REG_C_CHIP, 0x8000, prg_bank_c_mapped >> 1);
+ setprg16r(REG_A_CHIP, 0xC000, prg_bank_a_mapped >> 1);
+ break;
+ case 4:
+ setprg8r(REG_A_CHIP, 0x8000, prg_bank_a_mapped);
+ setprg8r(REG_B_CHIP, 0xA000, prg_bank_b_mapped);
+ setprg8r(REG_C_CHIP, 0xC000, prg_bank_c_mapped);
+ setprg8r(REG_D_CHIP, 0xE000, prg_bank_d_mapped);
+ break;
+ case 5:
+ setprg8r(REG_C_CHIP, 0x8000, prg_bank_c_mapped);
+ setprg8r(REG_B_CHIP, 0xA000, prg_bank_b_mapped);
+ setprg8r(REG_A_CHIP, 0xC000, prg_bank_a_mapped);
+ setprg8r(REG_D_CHIP, 0xE000, prg_bank_d_mapped);
+ break;
+ case 6:
+ setprg32r(REG_A_CHIP, 0x8000, prg_bank_b_mapped >> 2);
+ break;
+ case 7:
+ setprg32r(REG_A_CHIP, 0x8000, prg_bank_a_mapped >> 2);
+ break;
+ }
+ }
+ else {
+ setprg32r(CFI_CHIP, 0x8000, 0);
+ }
+
+ if (!map_rom_on_6000)
+ setprg8r(SRAM_CHIP, 0x6000, sram_page); // Select SRAM page
+ else
+ setprg8(0x6000, prg_bank_6000_mapped); // Map ROM on $6000-$7FFF
+}
+
+static void COOLGIRL_Sync_CHR(void) {
+ // calculate CHR shift
+ // wire shift_chr = ENABLE_MAPPER_021_022_023_025 && ENABLE_MAPPER_022 && (mapper == 6'b011000) && flags[1];
+ int chr_shift = ((mapper == 0b011000) && (flags & 0b010)) ? 1 : 0;
+
+ // enable or disable writes to CHR RAM, setup CHR mask
+ SetupCartCHRMapping(CHR_RAM_CHIP, CHR_RAM, ((((~(chr_mask >> 13) & 0x3F) + 1) * 0x2000 - 1) & (CHR_RAM_SIZE - 1)) + 1, can_write_chr);
+
+ switch (chr_mode & 7)
+ {
+ default:
+ case 0:
+ setchr8r(0x12, chr_bank_a >> 3 >> chr_shift);
+ break;
+ case 1:
+ setchr4r(0x12, 0x0000, mapper_163_latch >> chr_shift);
+ setchr4r(0x12, 0x1000, mapper_163_latch >> chr_shift);
+ break;
+ case 2:
+ setchr2r(0x12, 0x0000, chr_bank_a >> 1 >> chr_shift);
+ TKSMIR[0] = TKSMIR[1] = chr_bank_a;
+ setchr2r(0x12, 0x0800, chr_bank_c >> 1 >> chr_shift);
+ TKSMIR[2] = TKSMIR[3] = chr_bank_c;
+ setchr1r(0x12, 0x1000, chr_bank_e >> chr_shift);
+ TKSMIR[4] = chr_bank_e;
+ setchr1r(0x12, 0x1400, chr_bank_f >> chr_shift);
+ TKSMIR[5] = chr_bank_f;
+ setchr1r(0x12, 0x1800, chr_bank_g >> chr_shift);
+ TKSMIR[6] = chr_bank_g;
+ setchr1r(0x12, 0x1C00, chr_bank_h >> chr_shift);
+ TKSMIR[7] = chr_bank_h;
+ break;
+ case 3:
+ setchr1r(0x12, 0x0000, chr_bank_e >> chr_shift);
+ TKSMIR[0] = chr_bank_e;
+ setchr1r(0x12, 0x0400, chr_bank_f >> chr_shift);
+ TKSMIR[1] = chr_bank_f;
+ setchr1r(0x12, 0x0800, chr_bank_g >> chr_shift);
+ TKSMIR[2] = chr_bank_g;
+ setchr1r(0x12, 0x0C00, chr_bank_h >> chr_shift);
+ TKSMIR[3] = chr_bank_h;
+ setchr2r(0x12, 0x1000, chr_bank_a >> 1 >> chr_shift);
+ TKSMIR[4] = TKSMIR[5] = chr_bank_a;
+ setchr2r(0x12, 0x1800, chr_bank_c >> 1 >> chr_shift);
+ TKSMIR[6] = TKSMIR[7] = chr_bank_c;
+ break;
+ case 4:
+ setchr4r(0x12, 0x0000, chr_bank_a >> 2 >> chr_shift);
+ setchr4r(0x12, 0x1000, chr_bank_e >> 2 >> chr_shift);
+ break;
+ case 5:
+ if (!ppu_latch0)
+ setchr4r(0x12, 0x0000, chr_bank_a >> 2 >> chr_shift);
+ else
+ setchr4r(0x12, 0x0000, chr_bank_b >> 2 >> chr_shift);
+ if (!ppu_latch1)
+ setchr4r(0x12, 0x1000, chr_bank_e >> 2 >> chr_shift);
+ else
+ setchr4r(0x12, 0x1000, chr_bank_f >> 2 >> chr_shift);
+ break;
+ case 6:
+ setchr2r(0x12, 0x0000, chr_bank_a >> 1 >> chr_shift);
+ setchr2r(0x12, 0x0800, chr_bank_c >> 1 >> chr_shift);
+ setchr2r(0x12, 0x1000, chr_bank_e >> 1 >> chr_shift);
+ setchr2r(0x12, 0x1800, chr_bank_g >> 1 >> chr_shift);
+ break;
+ case 7:
+ setchr1r(0x12, 0x0000, chr_bank_a >> chr_shift);
+ setchr1r(0x12, 0x0400, chr_bank_b >> chr_shift);
+ setchr1r(0x12, 0x0800, chr_bank_c >> chr_shift);
+ setchr1r(0x12, 0x0C00, chr_bank_d >> chr_shift);
+ setchr1r(0x12, 0x1000, chr_bank_e >> chr_shift);
+ setchr1r(0x12, 0x1400, chr_bank_f >> chr_shift);
+ setchr1r(0x12, 0x1800, chr_bank_g >> chr_shift);
+ setchr1r(0x12, 0x1C00, chr_bank_h >> chr_shift);
+ break;
+ }
+}
+
+static void COOLGIRL_Sync_Mirroring(void) {
+ if (!four_screen)
+ {
+ if (!((mapper == 0b010100) && (flags & 1))) // Mapper #189?
+ setmirror((mirroring < 2) ? (mirroring ^ 1) : mirroring);
+ }
+ else { // four screen mode
+ vnapage[0] = CHR_RAM + 0x3F000;
+ vnapage[1] = CHR_RAM + 0x3F400;
+ vnapage[2] = CHR_RAM + 0x3F800;
+ vnapage[3] = CHR_RAM + 0x3FC00;
+ }
+}
+
+static void COOLGIRL_Sync(void) {
+ COOLGIRL_Sync_PRG();
+ COOLGIRL_Sync_CHR();
+ COOLGIRL_Sync_Mirroring();
+}
+
+static DECLFW(COOLGIRL_Flash_Write) {
+ if (flash_state < 10)
+ {
+ flash_buffer_a[flash_state] = A & 0xFFF;
+ flash_buffer_v[flash_state] = V;
+ flash_state++;
+
+ // sector erase
+ if ((flash_state == 6) &&
+ (flash_buffer_a[0] == 0x0AAA) && (flash_buffer_v[0] == 0xAA) &&
+ (flash_buffer_a[1] == 0x0555) && (flash_buffer_v[1] == 0x55) &&
+ (flash_buffer_a[2] == 0x0AAA) && (flash_buffer_v[2] == 0x80) &&
+ (flash_buffer_a[3] == 0x0AAA) && (flash_buffer_v[3] == 0xAA) &&
+ (flash_buffer_a[4] == 0x0555) && (flash_buffer_v[4] == 0x55) &&
+ (flash_buffer_v[5] == 0x30))
+ {
+ uint32 sector_address = prg_bank_a_mapped * 0x2000;
+ for (uint32 i = sector_address; i < sector_address + 128 * 1024; i++)
+ SAVE_FLASH[i % SAVE_FLASH_SIZE] = 0xFF;
+ FCEU_printf("Flash sector erased: %08x - %08x\n", sector_address, sector_address + 128 * 1024 - 1);
+ flash_state = 0;
+ }
+
+ // writing byte
+ if ((flash_state == 4) &&
+ (flash_buffer_a[0] == 0x0AAA) && (flash_buffer_v[0] == 0xAA) &&
+ (flash_buffer_a[1] == 0x0555) && (flash_buffer_v[1] == 0x55) &&
+ (flash_buffer_a[2] == 0x0AAA) && (flash_buffer_v[2] == 0xA0))
+ {
+ uint32 sector_address = prg_bank_a_mapped * 0x2000;
+ uint32 flash_addr = sector_address + (A % 0x8000);
+ if (SAVE_FLASH[flash_addr % SAVE_FLASH_SIZE] != 0xFF) FCEU_PrintError("Error flash sector is not erased: %08x\n", flash_addr);
+ SAVE_FLASH[flash_addr % SAVE_FLASH_SIZE] = V;
+ if (A % 0x2000 == 0)
+ FCEU_printf("Flash sector writed: %08x\n", flash_addr);
+ flash_state = 0;
+ }
+
+ // enter CFI mode
+ if ((flash_state == 1) &&
+ (flash_buffer_a[0] == 0x0AAA) && (flash_buffer_v[0] == 0x98))
+ {
+ cfi_mode = 1;
+ COOLGIRL_Sync_PRG();
+ flash_state = 0;
+ return;
+ }
+ }
+ if (V == 0xF0)
+ {
+ flash_state = 0;
+ cfi_mode = 0;
+ COOLGIRL_Sync_PRG();
+ }
+}
+
+static DECLFW(COOLGIRL_WRITE) {
+ if (sram_enabled && A >= 0x6000 && A < 0x8000 && !map_rom_on_6000)
+ CartBW(A, V); // SRAM is enabled and writable
+ if (can_write_flash && A >= 0x8000) // writing flash
+ COOLGIRL_Flash_Write(A, V);
+
+ // block two writes in a row
+ if ((timestampbase + timestamp) < (lreset + 2)) return;
+ lreset = timestampbase + timestamp;
+
+ if (A >= 0x5000 && A < 0x6000 && !lockout)
+ {
+ //FCEU_printf("Write: %02x => %04x\n", V, A);
+ switch (A & 7)
+ {
+ case 0:
+ // {prg_base[26:22]} = cpu_data_in[4:0];
+ // use bits 29-27 to simulate flash memory
+ SET_BITS(prg_base, "29:22", V, "7:0");
+ break;
+ case 1:
+ // prg_base[21:14] = cpu_data_in[7:0];
+ SET_BITS(prg_base, "21:14", V, "7:0");
+ break;
+ case 2:
+ // {chr_mask[18], prg_mask[20:14]} = cpu_data_in[7:0];
+ SET_BITS(chr_mask, "18", V, "7");
+ SET_BITS(prg_mask, "20:14", V, "6:0");
+ //FCEU_printf("REG_prg_mask: %02x\n", REG_prg_mask);
+ break;
+ case 3:
+ // {prg_mode[2:0], chr_bank_a[7:3]} = cpu_data_in[7:0];
+ SET_BITS(prg_mode, "2:0", V, "7:5");
+ SET_BITS(chr_bank_a, "7:3", V, "4:0");
+ break;
+ case 4:
+ // {chr_mode[2:0], chr_mask[17:13]} = cpu_data_in[7:0];
+ SET_BITS(chr_mode, "2:0", V, "7:5");
+ SET_BITS(chr_mask, "17:13", V, "4:0");
+ break;
+ case 5:
+ // {chr_bank_a[8], prg_bank_a[5:1], sram_page[1:0]} = cpu_data_in[7:0];
+ SET_BITS(chr_bank_a, "8", V, "7");
+ SET_BITS(prg_bank_a, "5:1", V, "6:2");
+ SET_BITS(sram_page, "1:0", V, "1:0");
+ break;
+ case 6:
+ // {flags[2:0], mapper[4:0]} = cpu_data_in[7:0];
+ SET_BITS(flags, "2:0", V, "7:5");
+ SET_BITS(mapper, "4:0", V, "4:0");
+ break;
+ case 7:
+ // {lockout, mapper[5], four_screen, mirroring[1:0], prg_write_enabled, chr_write_enabled, sram_enabled} = cpu_data_in[7:0];
+ SET_BITS(lockout, "0", V, "7");
+ SET_BITS(mapper, "5", V, "6");
+ SET_BITS(four_screen, "0", V, "5");
+ SET_BITS(mirroring, "1:0", V, "4:3");
+ SET_BITS(can_write_flash, "0", V, "2");
+ SET_BITS(can_write_chr, "0", V, "1");
+ SET_BITS(sram_enabled, "0", V, "0");
+ if (mapper == 0b010001) prg_bank_b = ~2; // if (USE_MAPPER_009_010 && mapper == 6'b010001) prg_bank_b = 8'b11111101;
+ if (mapper == 0b010111) map_rom_on_6000 = 1; // if (ENABLE_MAPPER_042 && (mapper == 6'b010111)) map_rom_on_6000 <= 1;
+ if (mapper == 0b001110) prg_bank_b = 1; // if (USE_MAPPER_065 && mapper == 6'b001110) prg_bank_b = 1;
+ break;
+ }
+ }
+
+ if (A < 0x8000) // $0000-$7FFF
+ {
+ // Mapper #163
+ if (mapper == 0b000110)
+ {
+ if (A == 0x5101) // if (cpu_addr_in[14:0] == 15'h5101)
+ {
+ if (mapper163_r4 && !V) // if ((mapper163_r4 != 0) && (cpu_data_in == 0))
+ mapper163_r5 ^= 1; // mapper163_r5[0] = ~mapper163_r5[0];
+ mapper163_r4 = V;
+ }
+ else if (A == 0x5100 && V == 6) // if ((cpu_addr_in[14:0] == 15'h5100) && (cpu_data_in == 6))
+ {
+ SET_BITS(prg_mode, "0", 0, "0"); // prg_mode[0] = 0;
+ prg_bank_b = 0b1100; // prb_bank_b = 4'b1100;
+ }
+ else {
+ if (get_bits(A, "14:12") == 0b101) // if (cpu_addr_in[14:12] == 3'b101) begin
+ {
+ switch (get_bits(A, "9:8")) // case (cpu_addr_in[9:8])
+ {
+ case 2:
+ SET_BITS(prg_mode, "0", 1, "0"); // prg_mode[0] = 1;
+ SET_BITS(prg_bank_a, "7:6", V, "1:0"); // prg_bank_a[7:6] = cpu_data_in[1:0];
+ mapper163_r0 = V;
+ break;
+ case 0:
+ SET_BITS(prg_mode, "0", 1, "0"); // prg_mode[0] = 1;
+ SET_BITS(prg_bank_a, "5:2", V, "3:0"); // prg_bank_a[5:2] = cpu_data_in[3:0];
+ SET_BITS(chr_mode, "0", V, "7"); // chr_mode[0] = cpu_data_in[7];
+ mapper163_r1 = V;
+ break;
+ case 3:
+ mapper163_r2 = V; // mapper163_r2 = cpu_data_in;
+ break;
+ case 1:
+ mapper163_r3 = V; // mapper163_r3 = cpu_data_in;
+ break;
+ }
+ }
+ }
+ }
+
+ // Mapper #87
+ if (mapper == 0b001100)
+ {
+ if (get_bits(A, "14:13") == 0b11) // if (cpu_addr_in[14:13] == 2'b11) // $6000-$7FFF
+ {
+ // chr_bank_a[4:3] = {cpu_data_in[0], cpu_data_in[1]};
+ SET_BITS(chr_bank_a, "4:3", V, "0,1");
+ }
+ }
+
+ // Mapper #90 - JY
+ /*
+ if (mapper == 0b001101)
+ {
+ switch (A)
+ {
+ case 0x5800: mul1 = V; break;
+ case 0x5801: mul2 = V; break;
+ }
+ }
+ */
+
+ // MMC5 (not really)
+ if (mapper == 0b001111)
+ {
+ // case (cpu_addr_in[14:0])
+ switch (get_bits(A, "14:0"))
+ {
+ case 0x5105:
+ if (V == 0xFF)
+ {
+ four_screen = 1;
+ }
+ else {
+ four_screen = 0;
+ // case ({cpu_data_in[4], cpu_data_in[2]})
+ switch (get_bits(V, "4,2"))
+ {
+ case 0b00: // 2'b00: mirroring = 2'b10;
+ mirroring = 0b10; break;
+ case 0b01: // 2'b01: mirroring = 2'b00;
+ mirroring = 0b00; break;
+ case 0b10: // 2'b10: mirroring = 2'b01;
+ mirroring = 0b01; break;
+ case 0b11: // 2'b11: mirroring = 2'b11;
+ mirroring = 0b11; break;
+ }
+ }
+ break;
+ case 0x5115:
+ // prg_bank_a[4:0] = { cpu_data_in[4:1], 1'b0};
+ SET_BITS(prg_bank_a, "4:1", V, "4:1");
+ SET_BITS(prg_bank_a, "0", 0, "0");
+ // prg_bank_b[4:0] = { cpu_data_in[4:1], 1'b1};
+ SET_BITS(prg_bank_b, "4:1", V, "4:1");
+ SET_BITS(prg_bank_b, "0", 1, "0");
+ break;
+ case 0x5116:
+ // prg_bank_c[4:0] = cpu_data_in[4:0];
+ SET_BITS(prg_bank_c, "4:0", V, "4:0");
+ break;
+ case 0x5117:
+ // prg_bank_d[4:0] = cpu_data_in[4:0];
+ SET_BITS(prg_bank_d, "4:0", V, "4:0");
+ break;
+ case 0x5120:
+ // chr_bank_a[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_a, "7:0", V, "7:0");
+ break;
+ case 0x5121:
+ // chr_bank_b[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_b, "7:0", V, "7:0");
+ break;
+ case 0x5122:
+ // chr_bank_c[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_c, "7:0", V, "7:0");
+ break;
+ case 0x5123:
+ // chr_bank_d[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_d, "7:0", V, "7:0");
+ break;
+ case 0x5128:
+ // chr_bank_e[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_e, "7:0", V, "7:0");
+ break;
+ case 0x5129:
+ // chr_bank_f[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_f, "7:0", V, "7:0");
+ break;
+ case 0x512A:
+ // chr_bank_g[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_g, "7:0", V, "7:0");
+ break;
+ case 0x512B:
+ // chr_bank_h[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_h, "7:0", V, "7:0");
+ break;
+ case 0x5203:
+ // mmc5_irq_ack = 1;
+ X6502_IRQEnd(FCEU_IQEXT);
+ mmc5_irq_out = 0;
+ // mmc5_irq_line[7:0] = cpu_data_in[7:0];
+ SET_BITS(mmc5_irq_line, "7:0", V, "7:0");
+ break;
+ case 0x5204:
+ // mmc5_irq_ack = 1;
+ X6502_IRQEnd(FCEU_IQEXT);
+ mmc5_irq_out = 0;
+ // mmc5_irq_enabled = cpu_data_in[7];
+ mmc5_irq_enabled = get_bits(V, "7");
+ break;
+ }
+ }
+
+ // Mapper #189
+ if ((mapper == 0b010100) && (flags & 2))
+ {
+ if (A >= 0x4120) // if (cpu_addr_in[14:0] >= 15'h4120) // $4120-$7FFF
+ {
+ // prg_bank_a[5:2] = cpu_data_in[3:0] | cpu_data_in[7:4];
+ prg_bank_a = set_bits(prg_bank_a, "5:2",
+ get_bits(V, "7:4") | get_bits(V, "3:0"));
+ }
+ }
+
+ // Mappers #79 and #146 - NINA-03/06 and Sachen 3015: (flag0 = 1)
+ if (mapper == 0b011011)
+ {
+ // if ({cpu_addr_in[14:13], cpu_addr_in[8]} == 3'b101)
+ if (get_bits(A, "14:13,8") == 0b101)
+ {
+ //chr_bank_a[5:3] = cpu_data_in[2:0];
+ SET_BITS(chr_bank_a, "5:3", V, "2:0");
+ //prg_bank_a[2] = cpu_data_in[3];
+ SET_BITS(prg_bank_a, "2", V, "3");
+ }
+ }
+
+ // Mapper #133
+ if (mapper == 0b011100)
+ {
+ // if ({cpu_addr_in[14:13], cpu_addr_in[8]} == 3'b101)
+ if (get_bits(A, "14:13,8") == 0b101)
+ {
+ //chr_bank_a[4:3] = cpu_data_in[1:0];
+ SET_BITS(chr_bank_a, "4:3", V, "1:0");
+ //prg_bank_a[2] = cpu_data_in[2];
+ SET_BITS(prg_bank_a, "2", V, "2");
+ }
+ }
+
+ // Mapper #184
+ if (mapper == 0b011111)
+ {
+ if (get_bits(A, "14:13") == 0b11) // if (cpu_addr_in[14:13] == 2'b11)
+ {
+ // chr_bank_a[4:2] = cpu_data_in[2:0];
+ SET_BITS(chr_bank_a, "4:2", V, "2:0");
+ // chr_bank_e[4:2] = {1'b1, cpu_data_in[5:4]};
+ SET_BITS(chr_bank_e, "3:2", V, "5:4");
+ SET_BITS(chr_bank_e, "4", 1, "0");
+ }
+ }
+
+ // Mapper #38
+ if (mapper == 0b100000)
+ {
+ // if (cpu_addr_in[14:12] == 3'b111)
+ if (get_bits(A, "14:12") == 0b111)
+ {
+ // prg_bank_a[3:2] = cpu_data_in[1:0];
+ SET_BITS(prg_bank_a, "3:2", V, "1:0");
+ // chr_bank_a[4:3] = cpu_data_in[3:2];
+ SET_BITS(chr_bank_a, "4:3", V, "3:2");
+ }
+ }
+ }
+ else // $8000-$FFFF
+ {
+ // Mapper #2 - UxROM
+ // flag0 - mapper #71 - for Fire Hawk only.
+ // other mapper-#71 games are UxROM
+ if (mapper == 0b000001)
+ {
+ // if (!ENABLE_MAPPER_071 | ~flags[0] | (cpu_addr_in[14:12] != 3'b001))
+ if (!(flags & 1) || (get_bits(A, "14:12") != 0b001))
+ {
+ // prg_bank_a[UxROM_BITSIZE+1:1] = cpu_data_in[UxROM_BITSIZE:0];
+ // UxROM_BITSIZE = 4
+ SET_BITS(prg_bank_a, "5:1", V, "4:0");
+ // if (ENABLE_MAPPER_030 && flags[1])
+ if (flags & 2)
+ {
+ // One screen mirroring select, CHR RAM bank, PRG ROM bank
+ // mirroring[1:0] = { 1'b1, cpu_data_in[7]};
+ SET_BITS(mirroring, "1", 1, "0");
+ SET_BITS(mirroring, "0", V, "7");
+ // chr_bank_a[1:0] = cpu_data_in[6:5];
+ SET_BITS(chr_bank_a, "1:0", V, "6:5");
+ }
+ }
+ else {
+ // CodeMasters, blah. Mirroring control used only by Fire Hawk
+ // mirroring[1:0] = {1'b1, cpu_data_in[4]};
+ SET_BITS(mirroring, "1", 1, "0");
+ SET_BITS(mirroring, "0", V, "4");
+ }
+ }
+
+ // Mapper #3 - CNROM
+ if (mapper == 0b000010)
+ {
+ // chr_bank_a[7:3] = cpu_data_in[4:0];
+ SET_BITS(chr_bank_a, "7:3", V, "4:0");
+ }
+
+ // Mapper #78 - Holy Diver
+ if (mapper == 0b000011)
+ {
+ // prg_bank_a[3:1] = cpu_data_in[2:0];
+ SET_BITS(prg_bank_a, "3:1", V, "2:0");
+ // chr_bank_a[6:3] = cpu_data_in[7:4];
+ SET_BITS(chr_bank_a, "6:3", V, "7:4");
+ // mirroring = { 1'b0, ~cpu_data_in[3]};
+ mirroring = get_bits(V, "3") ^ 1;
+ }
+
+ // Mapper #97 - Irem's TAM-S1
+ if (mapper == 0b000100)
+ {
+ // prg_bank_a[5:1] = cpu_data_in[4:0];
+ SET_BITS(chr_bank_a, "5:1", V, "4:0");
+ // mirroring = { 1'b0, ~cpu_data_in[7]};
+ mirroring = get_bits(V, "7") ^ 1;
+ }
+
+ // Mapper #93 - Sunsoft-2
+ if (mapper == 0b000101)
+ {
+ // prg_bank_a[3:1] = { cpu_data_in[6:4] };
+ SET_BITS(prg_bank_a, "3:1", V, "6:4");
+ // chr_write_enabled = cpu_data_in[0];
+ can_write_chr = V & 1;
+ }
+
+ // Mapper #18
+ if (mapper == 0b000111)
+ {
+ // case ({cpu_addr_in[14:12], cpu_addr_in[1:0]})
+ switch (get_bits(A, "14:12,1:0"))
+ {
+ case 0b00000: // 5'b00000: prg_bank_a[3:0] = cpu_data_in[3:0]; // $8000
+ SET_BITS(prg_bank_a, "3:0", V, "3:0"); break;
+ case 0b00001: // 5'b00001: prg_bank_a[7:4] = cpu_data_in[3:0]; // $8001
+ SET_BITS(prg_bank_a, "7:4", V, "3:0"); break;
+ case 0b00010: // 5'b00010: prg_bank_b[3:0] = cpu_data_in[3:0]; // $8002
+ SET_BITS(prg_bank_b, "3:0", V, "3:0"); break;
+ case 0b00011: // 5'b00011: prg_bank_b[7:4] = cpu_data_in[3:0]; // $8003
+ SET_BITS(prg_bank_b, "7:4", V, "3:0"); break;
+ case 0b00100: // 5'b00100: prg_bank_c[3:0] = cpu_data_in[3:0]; // $9000
+ SET_BITS(prg_bank_c, "3:0", V, "3:0"); break;
+ case 0b00101: // 5'b00101: prg_bank_c[7:4] = cpu_data_in[3:0]; // $9001
+ SET_BITS(prg_bank_c, "7:4", V, "3:0"); break;
+ case 0b00110:
+ break;
+ case 0b00111:
+ break;
+ case 0b01000: // 5'b01000: chr_bank_a[3:0] = cpu_data_in[3:0]; // $A000
+ SET_BITS(chr_bank_a, "3:0", V, "3:0"); break;
+ case 0b01001: // 5'b01001: chr_bank_a[7:4] = cpu_data_in[3:0]; // $A001
+ SET_BITS(chr_bank_a, "7:4", V, "3:0"); break;
+ case 0b01010: // 5'b01010: chr_bank_b[3:0] = cpu_data_in[3:0]; // $A002
+ SET_BITS(chr_bank_b, "3:0", V, "3:0"); break;
+ case 0b01011: // 5'b01011: chr_bank_b[7:4] = cpu_data_in[3:0]; // $A003
+ SET_BITS(chr_bank_b, "7:4", V, "3:0"); break;
+ case 0b01100: // 5'b01100: chr_bank_c[3:0] = cpu_data_in[3:0]; // $B000
+ SET_BITS(chr_bank_c, "3:0", V, "3:0"); break;
+ case 0b01101: // 5'b01101: chr_bank_c[7:4] = cpu_data_in[3:0]; // $B001
+ SET_BITS(chr_bank_c, "7:4", V, "3:0"); break;
+ case 0b01110: // 5'b01110: chr_bank_d[3:0] = cpu_data_in[3:0]; // $B002
+ SET_BITS(chr_bank_d, "3:0", V, "3:0"); break;
+ case 0b01111: // 5'b01111: chr_bank_d[7:4] = cpu_data_in[3:0]; // $B003
+ SET_BITS(chr_bank_d, "7:4", V, "3:0"); break;
+ case 0b10000: // 5'b10000: chr_bank_e[3:0] = cpu_data_in[3:0]; // $C000
+ SET_BITS(chr_bank_e, "3:0", V, "3:0"); break;
+ case 0b10001: // 5'b10001: chr_bank_e[7:4] = cpu_data_in[3:0]; // $C001
+ SET_BITS(chr_bank_e, "7:4", V, "3:0"); break;
+ case 0b10010: // 5'b10010: chr_bank_f[3:0] = cpu_data_in[3:0]; // $C002
+ SET_BITS(chr_bank_f, "3:0", V, "3:0"); break;
+ case 0b10011: // 5'b10011: chr_bank_f[7:4] = cpu_data_in[3:0]; // $C003
+ SET_BITS(chr_bank_f, "7:4", V, "3:0"); break;
+ case 0b10100: // 5'b10100: chr_bank_g[3:0] = cpu_data_in[3:0]; // $D000
+ SET_BITS(chr_bank_g, "3:0", V, "3:0"); break;
+ case 0b10101: // 5'b10101: chr_bank_g[7:4] = cpu_data_in[3:0]; // $D001
+ SET_BITS(chr_bank_g, "7:4", V, "3:0"); break;
+ case 0b10110: // 5'b10110: chr_bank_h[3:0] = cpu_data_in[3:0]; // $D002
+ SET_BITS(chr_bank_h, "3:0", V, "3:0"); break;
+ case 0b10111: // 5'b10111: chr_bank_h[7:4] = cpu_data_in[3:0]; // $D003
+ SET_BITS(chr_bank_h, "7:4", V, "3:0"); break;
+ case 0b11000: // 5'b11000: mapper18_irq_latch[3:0] = cpu_data_in[3:0]; // $E000
+ SET_BITS(mapper18_irq_latch, "3:0", V, "3:0"); break;
+ case 0b11001: // 5'b11001: mapper18_irq_latch[7:4] = cpu_data_in[3:0]; // $E001
+ SET_BITS(mapper18_irq_latch, "7:4", V, "3:0"); break;
+ case 0b11010: // 5'b11010: mapper18_irq_latch[11:8] = cpu_data_in[3:0]; // $E002
+ SET_BITS(mapper18_irq_latch, "11:8", V, "3:0"); break;
+ case 0b11011: // 5'b11011: mapper18_irq_latch[15:12] = cpu_data_in[3:0]; // $E003
+ SET_BITS(mapper18_irq_latch, "15:12", V, "3:0"); break;
+ case 0b11100: // 5'b11100: begin // $F000
+ // mapper18_irq_out = 0; // ack
+ X6502_IRQEnd(FCEU_IQEXT);
+ // mapper18_irq_value[15:0] = mapper18_irq_latch[15:0];
+ mapper18_irq_value = mapper18_irq_latch; break; // irq_cpu_out = 0;
+ case 0b11101: // 5'b11101: begin // $F001
+ X6502_IRQEnd(FCEU_IQEXT); // irq_cpu_control[3:0] = cpu_data_in[3:0];
+ SET_BITS(mapper18_irq_control, "3:0", V, "3:0"); break;
+ case 0b11110: // 5'b11110
+ switch (get_bits(V, "1:0")) // case (cpu_data_in[1:0])
+ {
+ case 0b00: mirroring = 0b01; break; //2'b00: mirroring = 2'b01; // Horz
+ case 0b01: mirroring = 0b00; break; //2'b01: mirroring = 2'b00; // Vert
+ case 0b10: mirroring = 0b10; break; //2'b10: mirroring = 2'b10; // 1SsA
+ case 0b11: mirroring = 0b11; break; //2'b11: mirroring = 2'b11; // 1SsB
+ }
+ case 0b11111:
+ break; // sound
+ }
+ }
+
+ // Mapper #7 - AxROM, mapper #241 - BNROM
+ if (mapper == 0b001000)
+ {
+ // AxROM_BxROM_BITSIZE = 3
+ //prg_bank_a[AxROM_BxROM_BITSIZE + 2:2] = cpu_data_in[AxROM_BxROM_BITSIZE:0];
+ SET_BITS(prg_bank_a, "5:2", V, "3:0");
+ //if (!ENABLE_MAPPER_034_241_BxROM || !flags[0]) // BxROM?
+ // mirroring = { 1'b1, cpu_data_in[4]};
+ if (!(flags & 1))
+ mirroring = (1 << 1) | get_bits(V, "4");
+ }
+
+ // Mapper #228 - Cheetahmen II
+ if (mapper == 0b001001)
+ {
+ // prg_bank_a[5:2] = cpu_addr_in[10:7];
+ SET_BITS(prg_bank_a, "5:2", A, "10:7");
+ // chr_bank_a[7:3] = { cpu_addr_in[2:0], cpu_data_in[1:0] }; // only 256k, sorry
+ SET_BITS(chr_bank_a, "7:5", A, "2:0");
+ SET_BITS(chr_bank_a, "4:3", V, "1:0");
+ // mirroring = { 1'b0, cpu_addr_in[13]};
+ mirroring = get_bits(A, "13");
+ }
+
+ // Mapper #11 - ColorDreams
+ if (mapper == 0b001010)
+ {
+ // prg_bank_a[3:2] = cpu_data_in[1:0];
+ SET_BITS(prg_bank_a, "3:2", V, "1:0");
+ // chr_bank_a[6:3] = cpu_data_in[7:4];
+ SET_BITS(chr_bank_a, "6:3", V, "7:4");
+ }
+
+ // Mapper #66 - GxROM
+ if (mapper == 0b001011)
+ {
+ // prg_bank_a[3:2] = cpu_data_in[5:4];
+ SET_BITS(prg_bank_a, "3:2", V, "5:4");
+ // chr_bank_a[4:3] = cpu_data_in[1:0];
+ SET_BITS(chr_bank_a, "4:3", V, "1:0");
+ }
+
+ // Mapper #90 - JY
+ if (mapper == 0b001101)
+ {
+ // if (cpu_addr_in[14:12] == 3'b000) // $800x
+ if (get_bits(A, "14:12") == 0b000)
+ {
+ // case (cpu_addr_in[1:0])
+ switch (get_bits(A, "1:0"))
+ {
+ // 2'b00: prg_bank_a[5:0] = cpu_data_in[5:0];
+ case 0b00: SET_BITS(prg_bank_a, "5:0", V, "5:0"); break;
+ // 2'b01: prg_bank_b[5:0] = cpu_data_in[5:0];
+ case 0b01: SET_BITS(prg_bank_b, "5:0", V, "5:0"); break;
+ // 2'b10: prg_bank_c[5:0] = cpu_data_in[5:0];
+ case 0b10: SET_BITS(prg_bank_c, "5:0", V, "5:0"); break;
+ // 2'b11: prg_bank_d[5:0] = cpu_data_in[5:0];
+ case 0b11: SET_BITS(prg_bank_d, "5:0", V, "5:0"); break;
+ }
+ }
+
+ // if (cpu_addr_in[14:12] == 3'b001) // $900x
+ if (get_bits(A, "14:12") == 0b001)
+ {
+ // case (cpu_addr_in[2:0])
+ switch (get_bits(A, "2:0"))
+ {
+ case 0b000: // 3'b000: chr_bank_a[7:0] = cpu_data_in[7:0]; // $9000
+ SET_BITS(chr_bank_a, "7:0", V, "7:0"); break;
+ case 0b001: // 3'b001: chr_bank_b[7:0] = cpu_data_in[7:0]; // $9001
+ SET_BITS(chr_bank_b, "7:0", V, "7:0"); break;
+ case 0b010: // 3'b010: chr_bank_c[7:0] = cpu_data_in[7:0]; // $9002
+ SET_BITS(chr_bank_c, "7:0", V, "7:0"); break;
+ case 0b011: // 3'b011: chr_bank_d[7:0] = cpu_data_in[7:0]; // $9003
+ SET_BITS(chr_bank_d, "7:0", V, "7:0"); break;
+ case 0b100: // 3'b100: chr_bank_e[7:0] = cpu_data_in[7:0]; // $9004
+ SET_BITS(chr_bank_e, "7:0", V, "7:0"); break;
+ case 0b101: // 3'b101: chr_bank_f[7:0] = cpu_data_in[7:0]; // $9005
+ SET_BITS(chr_bank_f, "7:0", V, "7:0"); break;
+ case 0b110: // 3'b110: chr_bank_g[7:0] = cpu_data_in[7:0]; // $9006
+ SET_BITS(chr_bank_g, "7:0", V, "7:0"); break;
+ case 0b111: // 3'b111: chr_bank_h[7:0] = cpu_data_in[7:0]; // $9007
+ SET_BITS(chr_bank_h, "7:0", V, "7:0"); break;
+ }
+ }
+
+ // if ({cpu_addr_in[14:12], cpu_addr_in[1:0]} == 5'b10101) // $D001
+ if (get_bits(A, "14:12,1:0") == 0b10101)
+ {
+ // mirroring = cpu_data_in[1:0];
+ SET_BITS(mirroring, "1:0", V, "1:0");
+ }
+
+ // use MMC3's IRQs
+ // if (cpu_addr_in[14:12] == 3'b100) // $C00x
+ if (get_bits(A, "14:12") == 0b100)
+ {
+ // case (cpu_addr_in[2:0])
+ switch (get_bits(A, "2:0"))
+ {
+ case 0b000:
+ // 3'b000: mmc3_irq_enabled = cpu_data_in[0];
+ if (V & 1)
+ {
+ mmc3_irq_enabled = 1;
+ }
+ else {
+ X6502_IRQEnd(FCEU_IQEXT);
+ mmc3_irq_enabled = 0;
+ }
+ break;
+ case 0b001:
+ break; // who cares about this shit?
+ case 0b010:
+ // 3'b010: mmc3_irq_enabled = 0;
+ mmc3_irq_enabled = 0;
+ X6502_IRQEnd(FCEU_IQEXT);
+ break;
+ case 0b011:
+ // 3'b011: mmc3_irq_enabled = 1;
+ mmc3_irq_enabled = 1;
+ break;
+ case 0b100:
+ break; // prescaler? who cares?
+ case 0b101:
+ // mmc3_irq_latch = cpu_data_in ^ mapper90_xor;
+ mmc3_irq_latch = V ^ mapper90_xor;
+ mmc3_irq_reload = 1;
+ break;
+ case 0b110:
+ // mapper90_xor = cpu_data_in;
+ mapper90_xor = V;
+ break;
+ case 0b111:
+ break; // meh
+ }
+ }
+ }
+
+ // Mapper #65 - Irem's H3001
+ if (mapper == 0b001110)
+ {
+ // case ({cpu_addr_in[14:12], cpu_addr_in[2:0]})
+ switch (get_bits(A, "14:12,2:0"))
+ {
+ case 0b000000:
+ // 6'b000000: prg_bank_a[5:0] = cpu_data_in[5:0]; // $8000
+ SET_BITS(prg_bank_a, "5:0", V, "5:0");
+ break;
+ case 0b001001:
+ // 6'b001001: mirroring = {1'b0, cpu_data_in[7]}; // $9001, mirroring
+ mirroring = get_bits(V, "7");
+ break;
+ case 0b001011:
+ // mapper65_irq_out = 0; // ack
+ X6502_IRQEnd(FCEU_IQEXT); // irq_cpu_out = 0;
+ // mapper65_irq_enabled = cpu_data_in[7]; // $9003, enable IRQ
+ mapper65_irq_enabled = get_bits(V, "7");
+ break;
+ case 0b001100:
+ X6502_IRQEnd(FCEU_IQEXT); // mapper65_irq_out = 0; // ack
+ mapper65_irq_value = mapper65_irq_latch; // $9004, IRQ reload
+ break;
+ case 0b001101: // mapper65_irq_latch[15:8] = cpu_data_in; // $9005, IRQ high value
+ SET_BITS(mapper65_irq_latch, "15:8", V, "7:0"); break;
+ case 0b001110: // mapper65_irq_latch[7:0] = cpu_data_in; // $9006, IRQ low value
+ SET_BITS(mapper65_irq_latch, "7:0", V, "7:0"); break;
+ case 0b010000: // prg_bank_b[5:0] = cpu_data_in[5:0]; // $A000
+ prg_bank_b = (prg_bank_b & 0b11000000) | (V & 0b00111111); break;
+ case 0b011000: // chr_bank_a[7:0] = cpu_data_in; // $B000
+ SET_BITS(chr_bank_a, "7:0", V, "7:0"); break;
+ case 0b011001: // chr_bank_b[7:0] = cpu_data_in[7:0]; // $B001
+ SET_BITS(chr_bank_b, "7:0", V, "7:0"); break;
+ case 0b011010: // chr_bank_c[7:0] = cpu_data_in[7:0]; // $B002
+ SET_BITS(chr_bank_c, "7:0", V, "7:0"); break;
+ case 0b011011: // chr_bank_d[7:0] = cpu_data_in[7:0]; // $B003
+ SET_BITS(chr_bank_d, "7:0", V, "7:0"); break;
+ case 0b011100: // chr_bank_e[7:0] = cpu_data_in[7:0]; // $B004
+ SET_BITS(chr_bank_e, "7:0", V, "7:0"); break;
+ case 0b011101: // chr_bank_f[7:0] = cpu_data_in[7:0]; // $B005
+ SET_BITS(chr_bank_f, "7:0", V, "7:0"); break;
+ case 0b011110: // chr_bank_g[7:0] = cpu_data_in[7:0]; // $B006
+ SET_BITS(chr_bank_g, "7:0", V, "7:0"); break;
+ case 0b011111: // chr_bank_h[7:0] = cpu_data_in[7:0]; // $B007
+ SET_BITS(chr_bank_h, "7:0", V, "7:0"); break;
+ case 0b100000: // 6'b100000: prg_bank_c[5:0] = cpu_data_in[5:0]; // $C000
+ SET_BITS(prg_bank_c, "5:0", V, "5:0"); break;
+ }
+ }
+
+ // Mapper #1 - MMC1
+ /*
+ r0 - load register
+ flag0 - 16KB of SRAM (SOROM)
+ */
+ if (mapper == 0b010000)
+ {
+ if (V & 0x80) // reset
+ {
+ mmc1_load_register = set_bits(mmc1_load_register, "5:0", 0b100000); // mmc1_load_register[5:0] = 6'b100000;
+ prg_mode = 0; // 0x4000 (A) + fixed last (C)
+ prg_bank_c = set_bits(prg_bank_c, "4:0", 0b11110); // prg_bank_c[4:0] = 5'b11110;
+ }
+ else {
+ // mmc1_load_register[5:0] = { cpu_data_in[0], mmc1_load_register[5:1] };
+ SET_BITS(mmc1_load_register, "4:0", mmc1_load_register, "5:1");
+ SET_BITS(mmc1_load_register, "5", V, "0");
+ // if (mmc1_load_register[0] == 1)
+ if (mmc1_load_register & 1)
+ {
+ switch ((A >> 13) & 3)
+ {
+ case 0b00: // 2'b00: begin // $8000-$9FFF
+ if (get_bits(mmc1_load_register, "4:3") == 0b11) // if (mmc1_load_register[4:3] == 2'b11)
+ {
+ prg_mode = 0; // prg_mode = 3'b000; // 0x4000 (A) + fixed last (C)
+ prg_bank_c = set_bits(prg_bank_c, "4:1", 0b1111); // prg_bank_c[4:1] = 4'b1111;
+ }
+ //else if (mmc1_load_register[4:3] == 2'b10)
+ else if (get_bits(mmc1_load_register, "4:3") == 0b10)
+ {
+ prg_mode = 0b001; // prg_mode = 3'b001; // fixed first (C) + 0x4000 (A)
+ prg_bank_c = set_bits(prg_bank_c, "4:1", 0b0000); // prg_bank_c[4:0] = 4'b0000;
+ }
+ else
+ prg_mode = 0b111; // prg_mode = 3'b111; // 0x8000 (A)
+ if (get_bits(mmc1_load_register, "5"))
+ chr_mode = 0b100;
+ else
+ chr_mode = 0b000;
+ mirroring = set_bits(mirroring, "1:0", get_bits(mmc1_load_register, "2:1") ^ 0b10);
+ break;
+ case 0b01: // 2'b01
+ SET_BITS(chr_bank_a, "6:2", mmc1_load_register, "5:1"); // chr_bank_a[6:2] = mmc1_load_register[5:1];
+ if (flags & 1) // (flags[0]) - 16KB of SRAM
+ {
+ // PRG RAM page #2 is battery backed
+ sram_page = 2 | get_bits(mmc1_load_register, "4") ^ 1; // sram_page <= {1'b1, ~mmc1_load_register[4]};
+ }
+ SET_BITS(prg_bank_a, "5", mmc1_load_register, "5"); // prg_bank_a[5] = mmc1_load_register[5]; // for SUROM, 512k PRG support
+ SET_BITS(prg_bank_c, "5", mmc1_load_register, "5"); // prg_bank_c[5] = mmc1_load_register[5]; // for SUROM, 512k PRG support
+ break;
+ case 0b10: // 2'b10: chr_bank_e[6:2] = mmc1_load_register[5:1]; // $C000-$DFFF
+ SET_BITS(chr_bank_e, "6:2", mmc1_load_register, "5:1");
+ break;
+ case 0b11: // 2'b11
+ // prg_bank_a[4:1] = r0[4:1];
+ SET_BITS(prg_bank_a, "4:1", mmc1_load_register, "4:1");
+ // sram_enabled = ~mmc1_load_register[5];
+ sram_enabled = get_bits(mmc1_load_register, "5") ^ 1;
+ break;
+ }
+ mmc1_load_register = 0b100000; // mmc1_load_register[5:0] = 6'b100000;
+ }
+ }
+ }
+
+ // Mapper #9 and #10 - MMC2 and MMC4
+ // flag0 - 0=MMC2, 1=MMC4
+ if (mapper == 0b010001)
+ {
+ switch ((A >> 12) & 7)
+ {
+ case 2: // $A000-$AFFF
+ if (!(flags & 1)) // MMC2
+ prg_bank_a = (prg_bank_a & 0xF0) | (V & 0x0F); // prg_bank_a[3:0] = cpu_data_in[3:0];
+ else // MMC4
+ prg_bank_a = (prg_bank_a & 0xE1) | ((V & 0x0F) << 1); // prg_bank_a[4:0] = { cpu_data_in[3:0], 1'b0};
+ break;
+ case 3: // $B000-$BFFF
+ chr_bank_a = (chr_bank_a & 0x83) | ((V & 0x1F) << 2); // chr_bank_a[6:2] = cpu_data_in[4:0];
+ break;
+ case 4: // $C000-$CFFF
+ chr_bank_b = (chr_bank_b & 0x83) | ((V & 0x1F) << 2); // chr_bank_b[6:2] = cpu_data_in[4:0];
+ break;
+ case 5: // $D000-$DFFF
+ chr_bank_e = (chr_bank_e & 0x83) | ((V & 0x1F) << 2); // chr_bank_b[6:2] = cpu_data_in[4:0];
+ break;
+ case 6: // $E000-$EFFF
+ chr_bank_f = (chr_bank_f & 0x83) | ((V & 0x1F) << 2); // chr_bank_b[6:2] = cpu_data_in[4:0];
+ break;
+ case 7: // $F000-$FFFF
+ mirroring = V & 1;
+ break;
+ }
+ }
+
+ // Mapper #152
+ if (mapper == 0b010010)
+ {
+ chr_bank_a = (chr_bank_a & 0x87) | ((V & 0x0F) << 3); // chr_bank_a[6:3] = cpu_data_in[3:0];
+ prg_bank_a = (prg_bank_a & 0xF1) | ((V & 0x70) >> 3); // prg_bank_a[3:1] = cpu_data_in[6:4];
+ mirroring = 2 | (V >> 7); // mirroring = {1'b1, cpu_data_in[7]};
+ }
+
+ // Mapper #73 - VRC3
+ if (mapper == 0b010011)
+ {
+ switch (get_bits(A, "14:12")) // case (cpu_addr_in[14:12])
+ {
+ case 0b000: // 3'b000: vrc3_irq_latch[3:0] = cpu_data_in[3:0]; // $8000-$8FFF
+ SET_BITS(vrc3_irq_latch, "3:0", V, "3:0");
+ break;
+ case 0b001: // 3'b001: vrc3_irq_latch[7:4] = cpu_data_in[3:0]; // $9000-$9FFF
+ SET_BITS(vrc3_irq_latch, "7:4", V, "3:0");
+ break;
+ case 0b010: // 3'b010: vrc3_irq_latch[11:8] = cpu_data_in[3:0]; // $A000-$AFFF
+ SET_BITS(vrc3_irq_latch, "11:8", V, "3:0");
+ break;
+ case 0b011: // 3'b011: vrc3_irq_latch[15:12] = cpu_data_in[3:0]; // $B000-$BFFF
+ SET_BITS(vrc3_irq_latch, "15:12", V, "3:0");
+ break;
+ case 0b100: // // $C000-$CFFF
+ X6502_IRQEnd(FCEU_IQEXT); // vrc3_irq_out = 0; // ack
+ SET_BITS(vrc3_irq_control, "2:0", V, "2:0"); // vrc3_irq_control[2:0] = cpu_data_in[2:0]; // mode, enabled, enabled after ack
+ if (vrc3_irq_control & 2) // if (vrc3_irq_control[1]) // if E is set
+ vrc3_irq_value = vrc3_irq_latch; // vrc3_irq_value[15:0] = vrc3_irq_latch[15:0]; // reload with latch
+ break;
+ case 0b101: // // $D000-$DFFF
+ X6502_IRQEnd(FCEU_IQEXT); // vrc3_irq_out = 0; // ack
+ SET_BITS(vrc3_irq_control, "1", vrc3_irq_control, "0"); // vrc3_irq_control[1] = vrc3_irq_control[0];
+ break;
+ case 0b110: // $E000-$EFFF
+ break;
+ case 0b111: // 3'b111: prg_bank_a[3:1] = cpu_data_in[2:0]; // $F000-$FFFF
+ SET_BITS(prg_bank_a, "3:1", V, "2:0");
+ break;
+ }
+ }
+
+ // Mapper #4 - MMC3/MMC6
+ /*
+ flag0 - TxSROM
+ flag1 - mapper #189
+ */
+ if (mapper == 0b010100)
+ {
+ // case ({cpu_addr_in[14:13], cpu_addr_in[0]})
+ switch (get_bits(A, "14:13,0"))
+ {
+ case 0b000: // $8000-$9FFE, even
+ SET_BITS(mmc3_internal, "2:0", V, "2:0"); // mmc3_internal[2:0] = cpu_data_in[2:0];
+ if (!(flags & 2) && !(flags & 4)) // if ((!USE_MAPPER_189 | ~flags[1]) & (!USE_MAPPER_206 | ~flags[2]))
+ {
+ if (get_bits(V, "6")) // if (cpu_data_in[6])
+ prg_mode = 0b101;
+ else
+ prg_mode = 0b100;
+ }
+ if (!(flags & 4)) // if (!USE_MAPPER_206 | ~flags[2]) // disabled for mapper #206
+ {
+ if (V & 0x80) // if (cpu_data_in[7])
+ chr_mode = 0b011;
+ else
+ chr_mode = 0b010;
+ }
+ break;
+ case 0b001: // $8001-$9FFF, odd
+ switch (get_bits(mmc3_internal, "2:0"))
+ {
+ case 0b000: // 3'b000: chr_bank_a[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_a, "7:0", V, "7:0"); break;
+ case 0b001: // 3'b001: chr_bank_c[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_c, "7:0", V, "7:0"); break;
+ case 0b010: // 3'b010: chr_bank_e[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_e, "7:0", V, "7:0"); break;
+ case 0b011: // 3'b011: chr_bank_f[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_f, "7:0", V, "7:0"); break;
+ case 0b100: // 3'b100: chr_bank_g[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_g, "7:0", V, "7:0"); break;
+ case 0b101: // 3'b101: chr_bank_h[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_h, "7:0", V, "7:0"); break;
+ case 0b110: // 3'b110: if (!ENABLE_MAPPER_189 | ~flags[1]) prg_bank_a[(MMC3_BITSIZE-1):0] = cpu_data_in[(MMC3_BITSIZE-1):0];
+ if (!(flags & 2))
+ SET_BITS(prg_bank_a, "7:0", V, "7:0");
+ break;
+ case 0b111: // 3'b111: if (!ENABLE_MAPPER_189 | ~flags[1]) prg_bank_b[(MMC3_BITSIZE-1):0] = cpu_data_in[(MMC3_BITSIZE-1):0];
+ if (!(flags & 2))
+ SET_BITS(prg_bank_b, "7:0", V, "7:0");
+ break;
+ }
+ break;
+ case 0b010: // $A000-$BFFE, even (mirroring)
+ // if (!ENABLE_MAPPER_206 | ~flags[2]) // disabled for mapper #206
+ if (!(flags & 4))
+ mirroring = V & 1; // mirroring = {1'b0, cpu_data_in[0]};
+ break;
+ case 0b011: // RAM protect... no
+ break;
+ case 0b100: // 3'b100: mmc3_irq_latch = cpu_data_in; // $C000-$DFFE, even (IRQ latch)
+ mmc3_irq_latch = V; break;
+ case 0b101: // 3'b101: mmc3_irq_reload = 1; // $C001-$DFFF, odd
+ mmc3_irq_reload = 1; break;
+ case 0b110: // 3'b110: mmc3_irq_enabled = 0; // $E000-$FFFE, even
+ X6502_IRQEnd(FCEU_IQEXT);
+ mmc3_irq_enabled = 0;
+ break;
+ case 0b111: // $E001-$FFFF, odd
+ if (!(flags & 4)) // if (!USE_MAPPER_206 | ~flags[2]) // disabled for mapper #206
+ mmc3_irq_enabled = 1; // mmc3_irq_enabled = 1;
+ break;
+ }
+ }
+
+ // Mapper #112
+ /*
+ r0[2:0] - internal register
+ */
+ if (mapper == 0b010101)
+ {
+ switch (get_bits(A, "14:13"))
+ {
+ case 0b00: // $8000-$9FFF
+ SET_BITS(mapper112_internal, "2:0", V, "2:0"); // mapper112_internal[2:0] = cpu_data_in[2:0];
+ break;
+ case 0b01: // $A000-BFFF
+ switch (get_bits(mapper112_internal, "2:0"))
+ {
+ case 0b000: // 3'b000: prg_bank_a[5:0] = cpu_data_in[5:0];
+ SET_BITS(prg_bank_a, "5:0", V, "5:0"); break;
+ case 0b001: // 3'b001: prg_bank_b[5:0] = cpu_data_in[5:0];
+ SET_BITS(prg_bank_b, "5:0", V, "5:0"); break;
+ case 0b010: // 3'b010: chr_bank_a[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_a, "7:0", V, "7:0"); break;
+ case 0b011: // 3'b011: chr_bank_c[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_c, "7:0", V, "7:0"); break;
+ case 0b100: // 3'b100: chr_bank_e[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_e, "7:0", V, "7:0"); break;
+ case 0b101: // 3'b101: chr_bank_f[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_f, "7:0", V, "7:0"); break;
+ case 0b110: // 3'b110: chr_bank_g[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_g, "7:0", V, "7:0"); break;
+ case 0b111: // 3'b111: chr_bank_h[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_h, "7:0", V, "7:0"); break;
+ }
+ break;
+ case 0b10: // $C000-$DFFF
+ break;
+ case 0b11: // 2'b11: mirroring = {1'b0, cpu_data_in[0]}; // $E000-$FFFF
+ mirroring = V & 1; break;
+ }
+ }
+
+ // Mappers #33 + #48 - Taito
+ // flag0=0 - #33, flag0=1 - #48
+ if (mapper == 0b010110)
+ {
+ // case ({cpu_addr_in[14:13], cpu_addr_in[1:0]})
+ switch (get_bits(A, "14:13,1:0"))
+ {
+ case 0b0000:
+ SET_BITS(prg_bank_a, "5:0", V, "5:0"); // prg_bank_a[5:0] = cpu_data_in[5:0]; // $8000, PRG Reg 0 (8k @ $8000)
+ if (!(flags & 1)) // if (~flags[0]) // 33
+ mirroring = get_bits(V, "6"); // mirroring = {1'b0, cpu_data_in[6]};
+ break;
+ case 0b0001: // 4'b0001: prg_bank_b[5:0] = cpu_data_in[5:0]; // $8001, PRG Reg 1 (8k @ $A000)
+ SET_BITS(prg_bank_b, "5:0", V, "5:0"); break;
+ case 0b0010: // 4'b0010: chr_bank_a[7:1] = cpu_data_in[6:0]; // $8002, CHR Reg 0 (2k @ $0000)
+ SET_BITS(chr_bank_a, "7:1", V, "6:0"); break;
+ case 0b0011: // 4'b0011: chr_bank_c[7:1] = cpu_data_in[6:0]; // $8003, CHR Reg 1 (2k @ $0800)
+ SET_BITS(chr_bank_c, "7:1", V, "6:0"); break;
+ case 0b0100: // 4'b0100: chr_bank_e[7:0] = cpu_data_in[7:0]; // $A000, CHR Reg 2 (1k @ $1000)
+ SET_BITS(chr_bank_e, "7:0", V, "7:0"); break;
+ case 0b0101: // 4'b0101: chr_bank_f[7:0] = cpu_data_in[7:0]; // $A001, CHR Reg 2 (1k @ $1400)
+ SET_BITS(chr_bank_f, "7:0", V, "7:0"); break;
+ case 0b0110: // 4'b0110: chr_bank_g[7:0] = cpu_data_in[7:0]; // $A002, CHR Reg 2 (1k @ $1800)
+ SET_BITS(chr_bank_g, "7:0", V, "7:0"); break;
+ case 0b0111: // 4'b0111: chr_bank_h[7:0] = cpu_data_in[7:0]; // $A003, CHR Reg 2 (1k @ $1C00)
+ SET_BITS(chr_bank_h, "7:0", V, "7:0"); break;
+ case 0b1100: // 4'b1100: if (flags[0]) mirroring = {1'b0, cpu_data_in[6]}; // $E000, mirroring, for mapper #48
+ if (flags & 1) // 48
+ mirroring = get_bits(V, "6"); // mirroring = cpu_data_in[6];
+ case 0b1000: // 4'b1000: irq_scanline_latch = ~cpu_data_in; // $C000, IRQ latch
+ mmc3_irq_latch = set_bits(mmc3_irq_latch, "7:0", get_bits(V, "7:0") ^ 0b11111111);
+ break;
+ case 0b1001: // 4'b1001: mmc3_irq_reload = 1; // $C001, IRQ reload
+ mmc3_irq_reload = 1; break;
+ case 0b1010: // 4'b1010: mmc3_irq_enabled = 1; // $C002, IRQ enable
+ mmc3_irq_enabled = 1; break;
+ case 0b1011: // 4'b1011: mmc3_irq_enabled = 0; // $C003, IRQ disable & ack
+ mmc3_irq_enabled = 0;
+ X6502_IRQEnd(FCEU_IQEXT); // irq_cpu_out = 0; // ack
+ break;
+ }
+ }
+
+ // Mapper #42
+ if (mapper == 0b010111)
+ {
+ // case ({cpu_addr_in[14], cpu_addr_in[1:0]})
+ switch (get_bits(A, "14,1:0"))
+ {
+ case 0: // 3'b000: chr_bank_a[7:3] = cpu_data_in[4:0]; // $8000, CHR Reg (8k @ $8000)
+ SET_BITS(chr_bank_a, "7:3", V, "4:0");
+ break;
+ case 4: // 3'b100: prg_bank_6000[3:0] = cpu_data_in[3:0]; // $E000, PRG Reg (8k @ $6000)
+ SET_BITS(prg_bank_6000, "3:0", V, "3:0");
+ break;
+ case 5: // 3'b101: mirroring = {1'b0, cpu_data_in[3]}; // Mirroring
+ mirroring = get_bits(V, "3");
+ break;
+ case 6: // 3'b110: ... // IRQ
+ mapper42_irq_enabled = get_bits(V, "1"); // mapper42_irq_enabled = cpu_data_in[1];
+ if (!mapper42_irq_enabled) // if (!mapper42_irq_enabled)
+ {
+ X6502_IRQEnd(FCEU_IQEXT); // irq_cpu_out = 0;
+ mapper42_irq_value = 0; // mapper42_irq_value = 0;
+ }
+ break;
+ }
+ }
+
+ // Mapper #23 - VRC2/4
+ /*
+ flag0 - switches A0 and A1 lines. 0=A0,A1 like VRC2b (mapper #23), 1=A1,A0 like VRC2a(#22), VRC2c(#25)
+ flag1 - divides CHR bank select by two (mapper #22, VRC2a)
+ */
+ if (mapper == 0b011000)
+ {
+ uint8 vrc_2b_hi =
+ (flags & 5) == 0 ? // (!flags[0] && !flags[2]) ?
+ (get_bits(A, "7") | get_bits(A, "2")) // | cpu_addr_in[7] | cpu_addr_in[2]) // mapper #21
+ : (flags & 5) == 1 ? //: (flags[0] && !flags[2]) ?
+ get_bits(A, "0") // (cpu_addr_in[0]) // mapper #22
+ : (flags & 5) == 4 ? // : (!flags[0] && flags[2]) ?
+ (get_bits(A, "5") | get_bits(A, "3") | get_bits(A, "1")) // (cpu_addr_in[5] | cpu_addr_in[3] | cpu_addr_in[1]) // mapper #23
+ : (get_bits(A, "2") | get_bits(A, "0")); // : (cpu_addr_in[2] | cpu_addr_in[0]); // mapper #25
+ uint8 vrc_2b_low =
+ (flags & 5) == 0 ? // (!flags[0] && !flags[2]) ?
+ (get_bits(A, "6") | get_bits(A, "1")) // (cpu_addr_in[6] | cpu_addr_in[1]) // mapper #21
+ : (flags & 5) == 1 ? // : (flags[0] && !flags[2]) ?
+ get_bits(A, "1") // (cpu_addr_in[1]) // mapper #22
+ : (flags & 5) == 4 ?// : (!flags[0] && flags[2]) ?
+ (get_bits(A, "4") | get_bits(A, "2") | get_bits(A, "0")) // (cpu_addr_in[4] | cpu_addr_in[2] | cpu_addr_in[0]) // mapper #23
+ : (get_bits(A, "3") | get_bits(A, "1")); // : (cpu_addr_in[3] | cpu_addr_in[1]); // mapper #25
+
+ // case ({ cpu_addr_in[14:12], vrc_2b_hi, vrc_2b_low })
+ switch ((get_bits(A, "14:12") << 2) | (vrc_2b_hi << 1) | vrc_2b_low)
+ {
+ case 0b00000: // $8000-$8003, PRG0
+ case 0b00001:
+ case 0b00010:
+ case 0b00011:
+ SET_BITS(prg_bank_a, "4:0", V, "4:0"); // prg_bank_a[4:0] = cpu_data_in[4:0];
+ break;
+ case 0b00100: // $9000-$9001, mirroring
+ case 0b00101:
+ // VRC2 - using games are usually well - behaved and only write 0 or 1 to this register,
+ // but Wai Wai World in one instance writes $FF instead
+ if (V != 0b11111111) // if (cpu_data_in != 8'b11111111) mirroring = cpu_data_in[1:0]; // $9000-$9001, mirroring
+ SET_BITS(mirroring, "1:0", V, "1:0");
+ break;
+ case 0b00110: // $9002-$9004, PRG swap
+ case 0b00111:
+ SET_BITS(prg_mode, "0", V, "1"); // prg_mode[0] = cpu_data_in[1];
+ break;
+ case 0b01000: // $A000-$A003, PRG1
+ case 0b01001:
+ case 0b01010:
+ case 0b01011:
+ SET_BITS(prg_bank_b, "4:0", V, "4:0"); // prg_bank_b[4:0] = cpu_data_in[4:0];
+ break;
+ case 0b01100: // 5'b01100: chr_bank_a[3:0] = cpu_data_in[3:0]; // $B000, CHR0 low
+ SET_BITS(chr_bank_a, "3:0", V, "3:0"); break;
+ case 0b01101: // 5'b01101: chr_bank_a[7:4] = cpu_data_in[3:0]; // $B001, CHR0 hi
+ SET_BITS(chr_bank_a, "7:4", V, "3:0"); break;
+ case 0b01110: // 5'b01110: chr_bank_b[3:0] = cpu_data_in[3:0]; // $B002, CHR1 low
+ SET_BITS(chr_bank_b, "3:0", V, "3:0"); break;
+ case 0b01111: // 5'b01111: chr_bank_b[7:4] = cpu_data_in[3:0]; // $B003, CHR1 hi
+ SET_BITS(chr_bank_b, "7:4", V, "3:0"); break;
+ case 0b10000: // 5'b10000: chr_bank_c[3:0] = cpu_data_in[3:0]; // $C000, CHR2 low
+ SET_BITS(chr_bank_c, "3:0", V, "3:0"); break;
+ case 0b10001: // 5'b10001: chr_bank_c[7:4] = cpu_data_in[3:0]; // $C001, CHR2 hi
+ SET_BITS(chr_bank_c, "7:4", V, "3:0"); break;
+ case 0b10010: // 5'b10010: chr_bank_d[3:0] = cpu_data_in[3:0]; // $C002, CHR3 low
+ SET_BITS(chr_bank_d, "3:0", V, "3:0"); break;
+ case 0b10011: // 5'b10011: chr_bank_d[7:4] = cpu_data_in[3:0]; // $C003, CHR3 hi
+ SET_BITS(chr_bank_d, "7:4", V, "3:0"); break;
+ case 0b10100: // 5'b10100: chr_bank_e[3:0] = cpu_data_in[3:0]; // $D000, CHR4 low
+ SET_BITS(chr_bank_e, "3:0", V, "3:0"); break;
+ case 0b10101: // 5'b10101: chr_bank_e[7:4] = cpu_data_in[3:0]; // $D001, CHR4 hi
+ SET_BITS(chr_bank_e, "7:4", V, "3:0"); break;
+ case 0b10110: // 5'b10110: chr_bank_f[3:0] = cpu_data_in[3:0]; // $D002, CHR5 low
+ SET_BITS(chr_bank_f, "3:0", V, "3:0"); break;
+ case 0b10111: // 5'b10111: chr_bank_f[7:4] = cpu_data_in[3:0]; // $D003, CHR5 hi
+ SET_BITS(chr_bank_f, "7:4", V, "3:0"); break;
+ case 0b11000: // 5'b11000: chr_bank_g[3:0] = cpu_data_in[3:0]; // $E000, CHR6 low
+ SET_BITS(chr_bank_g, "3:0", V, "3:0"); break;
+ case 0b11001: // 5'b11001: chr_bank_g[7:4] = cpu_data_in[3:0]; // $E001, CHR6 hi
+ SET_BITS(chr_bank_g, "7:4", V, "3:0"); break;
+ case 0b11010: // 5'b11010: chr_bank_h[3:0] = cpu_data_in[3:0]; // $E002, CHR7 low
+ SET_BITS(chr_bank_h, "3:0", V, "3:0"); break;
+ case 0b11011: // 5'b11011: chr_bank_h[7:4] = cpu_data_in[3:0]; // $E003, CHR7 hi
+ SET_BITS(chr_bank_h, "7:4", V, "3:0"); break;
+ }
+
+ // if (cpu_addr_in[14:12] == 3'b111)
+ if (get_bits(A, "14:12") == 0b111)
+ {
+ // case (vrc_2b_hi, vrc_2b_low})
+ switch ((vrc_2b_hi << 1) | vrc_2b_low)
+ {
+ case 0b00: // 2'b00: vrc4_irq_latch[3:0] = cpu_data_in[3:0]; // IRQ latch low
+ SET_BITS(vrc4_irq_latch, "3:0", V, "3:0"); break;
+ case 0b01: // 2'b01: vrc4_irq_latch[7:4] = cpu_data_in[3:0]; // IRQ latch hi
+ SET_BITS(vrc4_irq_latch, "7:4", V, "3:0"); break;
+ case 0b10: // 2'b10 // IRQ control
+ X6502_IRQEnd(FCEU_IQEXT); // vrc4_irq_out = 0; // ack
+ SET_BITS(vrc4_irq_control, "2:0", V, "2:0"); // vrc4_irq_control[2:0] = cpu_data_in[2:0]; // mode, enabled, enabled after ack
+ if (vrc4_irq_control & 2) // if (vrc4_irq_control[1]) begin // if E is set
+ {
+ vrc4_irq_prescaler_counter = 0; // vrc4_irq_prescaler_counter[1:0] = 2'b00; // reset prescaler
+ vrc4_irq_prescaler = 0; // vrc4_irq_prescaler[6:0] = 7'b0000000;
+ SET_BITS(vrc4_irq_value, "7:0", vrc4_irq_latch, "7:0"); // vrc4_irq_value[7:0] = vrc4_irq_latch[7:0]; // reload with latch
+ }
+ break;
+ case 0b11: // 2'b11 // IRQ ack
+ X6502_IRQEnd(FCEU_IQEXT); // vrc4_irq_out = 0;
+ SET_BITS(vrc4_irq_control, "1", vrc4_irq_control, "0"); // vrc4_irq_control[1] = vrc4_irq_control[0];
+ break;
+ }
+ }
+ }
+
+ // Mapper #69 - Sunsoft FME-7
+ if (mapper == 0b011001)
+ {
+ // if (cpu_addr_in[14:13] == 2'b00) mapper69_internal[3:0] = cpu_data_in[3:0];
+ if (get_bits(A, "14:13") == 0b00) SET_BITS(mapper69_internal, "3:0", V, "3:0");
+ // if (cpu_addr_in[14:13] == 2'b01)
+ if (get_bits(A, "14:13") == 0b01)
+ {
+ switch (get_bits(mapper69_internal, "3:0")) // case (mapper69_internal[3:0])
+ {
+ case 0b0000: // 4'b0000: chr_bank_a[7:0] = cpu_data_in[7:0]; // CHR0
+ SET_BITS(chr_bank_a, "7:0", V, "7:0"); break;
+ case 0b0001: // 4'b0001: chr_bank_b[7:0] = cpu_data_in[7:0]; // CHR1
+ SET_BITS(chr_bank_b, "7:0", V, "7:0"); break;
+ case 0b0010: // 4'b0010: chr_bank_c[7:0] = cpu_data_in[7:0]; // CHR2
+ SET_BITS(chr_bank_c, "7:0", V, "7:0"); break;
+ case 0b0011: // 4'b0011: chr_bank_d[7:0] = cpu_data_in[7:0]; // CHR3
+ SET_BITS(chr_bank_d, "7:0", V, "7:0"); break;
+ case 0b0100: // 4'b0100: chr_bank_e[7:0] = cpu_data_in[7:0]; // CHR4
+ SET_BITS(chr_bank_e, "7:0", V, "7:0"); break;
+ case 0b0101: // 4'b0101: chr_bank_f[7:0] = cpu_data_in[7:0]; // CHR5
+ SET_BITS(chr_bank_f, "7:0", V, "7:0"); break;
+ case 0b0110: // 4'b0110: chr_bank_g[7:0] = cpu_data_in[7:0]; // CHR6
+ SET_BITS(chr_bank_g, "7:0", V, "7:0"); break;
+ case 0b0111: // 4'b0111: chr_bank_h[7:0] = cpu_data_in[7:0]; // CHR7
+ SET_BITS(chr_bank_h, "7:0", V, "7:0"); break;
+ case 0b1000: // 4'b1000: {sram_enabled, map_rom_on_6000, prg_bank_6000} = {cpu_data_in[7], ~cpu_data_in[6], cpu_data_in[5:0]}; // PRG0
+ sram_enabled = (V >> 7) & 1;
+ map_rom_on_6000 = ((V >> 6) & 1) ^ 1;
+ prg_bank_6000 = V & 0x3F;
+ break;
+ case 0b1001: // 4'b1001: prg_bank_a[5:0] = cpu_data_in[5:0]; // PRG1
+ SET_BITS(prg_bank_a, "5:0", V, "5:0"); break;
+ case 0b1010: // 4'b1010: prg_bank_b[5:0] = cpu_data_in[5:0]; // PRG2
+ SET_BITS(prg_bank_b, "5:0", V, "5:0"); break;
+ case 0b1011: // 4'b1011: prg_bank_c[5:0] = cpu_data_in[5:0]; // PRG3
+ SET_BITS(prg_bank_c, "5:0", V, "5:0"); break;
+ case 0b1100: // 4'b1100: mirroring[1:0] = cpu_data_in[1:0]; // mirroring
+ SET_BITS(mirroring, "1:0", V, "1:0"); break;
+ case 0b1101: // 4'b1101
+ X6502_IRQEnd(FCEU_IQEXT); // fme7_irq_out = 0; // ack
+ mapper69_counter_enabled = get_bits(V, "7"); // fme7_counter_enabled = cpu_data_in[7];
+ mapper69_irq_enabled = get_bits(V, "0"); // fme7_irq_enabled = cpu_data_in[0];
+ break;
+ case 0b1110: // 4'b1110: fme7_irq_value[7:0] = cpu_data_in[7:0]; // IRQ low
+ SET_BITS(mapper69_irq_value, "7:0", V, "7:0"); break;
+ case 0b1111: // fme7_irq_value[15:8] = cpu_data_in[7:0]; // IRQ high
+ SET_BITS(mapper69_irq_value, "15:8", V, "7:0"); break;
+ }
+ }
+ }
+
+ // Mapper #32 - Irem's G-101
+ if (mapper == 0b011010)
+ {
+ switch (get_bits(A, "14:12"))
+ {
+ case 0b000: // 2'b00: prg_bank_a[5:0] = cpu_data_in[5:0]; // $8000-$8FFF, PRG0
+ SET_BITS(prg_bank_a, "5:0", V, "5:0");
+ break;
+ case 0b001: // 2'b01: {prg_mode[0], mirroring} = {cpu_data_in[1], 1'b0, cpu_data_in[0]}; // $9000-$9FFF, PRG mode, mirroring
+ SET_BITS(prg_mode, "0", V, "1");
+ mirroring = V & 1;
+ break;
+ case 0b010: // 2'b10: prg_bank_b[5:0] = cpu_data_in[5:0]; // $A000-$AFFF, PRG1
+ SET_BITS(prg_bank_b, "5:0", V, "5:0");
+ break;
+ case 0b011: // $B000-$BFFF, CHR regs
+ switch (get_bits(A, "2:0"))
+ {
+ case 0b000: // 3'b000: chr_bank_a[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_a, "7:0", V, "7:0"); break;
+ case 0b001: // 3'b001: chr_bank_b[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_b, "7:0", V, "7:0"); break;
+ case 0b010: // 3'b010: chr_bank_c[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_c, "7:0", V, "7:0"); break;
+ case 0b011: // 3'b011: chr_bank_d[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_d, "7:0", V, "7:0"); break;
+ case 0b100: // 3'b100: chr_bank_e[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_e, "7:0", V, "7:0"); break;
+ case 0b101: // 3'b101: chr_bank_f[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_f, "7:0", V, "7:0"); break;
+ case 0b110: // 3'b110: chr_bank_g[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_g, "7:0", V, "7:0"); break;
+ case 0b111: // 3'b111: chr_bank_h[7:0] = cpu_data_in[7:0];
+ SET_BITS(chr_bank_h, "7:0", V, "7:0"); break;
+ }
+ break;
+ }
+ }
+
+ // Mapper #36 is assigned to TXC's PCB 01-22000-400
+ if (mapper == 0b011101)
+ {
+ if (get_bits(A, "14:1") != 0b11111111111111) // (cpu_addr_in[14:1] != 14'b11111111111111)
+ {
+ // prg_bank_a[5:2] = cpu_data_in[7:4];
+ SET_BITS(prg_bank_a, "5:2", V, "7:4");
+ // chr_bank_a[6:3] = cpu_data_in[3:0];
+ SET_BITS(chr_bank_a, "6:3", V, "3:0");
+ }
+ }
+
+ // Mapper #70
+ if (mapper == 0b011110)
+ {
+ // prg_bank_a[4:1] = cpu_data_in[7:4];
+ SET_BITS(prg_bank_a, "4:1", V, "7:4");
+ // chr_bank_a[6:3] = cpu_data_in[3:0];
+ SET_BITS(chr_bank_a, "6:3", V, "3:0");
+ }
+
+ // Mapper #75 - VRC1
+ if (mapper == 0b100010)
+ {
+ // case (cpu_addr_in[14:12])
+ switch (get_bits(A, "14:12"))
+ {
+ case 0b000: // 3'b000: prg_bank_a[3:0] = cpu_data_in[3:0]; // $8000-$8FFF
+ SET_BITS(prg_bank_a, "3:0", V, "3:0"); break;
+ case 0b001:
+ mirroring = V & 1; // mirroring = {1'b0, cpu_data_in[0]};
+ SET_BITS(chr_bank_a, "6", V, "1"); // chr_bank_a[6] = cpu_data_in[1];
+ SET_BITS(chr_bank_e, "6", V, "2"); // chr_bank_e[6] = cpu_data_in[2];
+ break;
+ case 0b010: // 3'b010: prg_bank_b[3:0] = cpu_data_in[3:0]; // $A000-$AFFF
+ SET_BITS(prg_bank_b, "3:0", V, "3:0"); break;
+ case 0b100: // 3'b100: prg_bank_c[3:0] = cpu_data_in[3:0]; // $C000-$CFFF
+ SET_BITS(prg_bank_c, "3:0", V, "3:0"); break;
+ case 0b110: // 3'b110: ñhr_bank_a[5:2] = cpu_data_in[3:0]; // $E000-$EFFF
+ SET_BITS(chr_bank_a, "5:2", V, "3:0"); break;
+ case 0b111: // 3'b111: chr_bank_e[5:2] = cpu_data_in[3:0]; // $F000-$FFFF
+ SET_BITS(chr_bank_e, "5:2", V, "3:0"); break;
+ }
+ }
+
+ // Mapper #83 - Cony/Yoko
+ if (mapper == 0b100011)
+ {
+ // case (cpu_addr_in[9:8])
+ switch (get_bits(A, "9:8"))
+ {
+ case 0b01: // $81xx
+ mirroring = get_bits(V, "1:0"); // mirroring <= cpu_data_in[1:0];
+ mapper83_irq_enabled_latch = get_bits(V, "7"); // mapper83_irq_enabled_latch <= cpu_data_in[7];
+ break;
+ case 0b10: // 82xx
+ if (!get_bits(A, "0")) // if (!cpu_addr_in[0])
+ {
+ X6502_IRQEnd(FCEU_IQEXT); // mapper83_irq_out <= 0;
+ SET_BITS(mapper83_irq_counter, "7:0", V, "7:0"); // mapper83_irq_counter[7:0] <= cpu_data_in[7:0];
+ }
+ else {
+ mapper83_irq_enabled = mapper83_irq_enabled_latch; //mapper83_irq_enabled <= mapper83_irq_enabled_latch;
+ SET_BITS(mapper83_irq_counter, "15:8", V, "7:0"); // mapper83_irq_counter[15:8] <= cpu_data_in[7:0];
+ }
+ break;
+ case 0b11:
+ if (!get_bits(A, "4")) // if (!cpu_addr_in[4])
+ {
+ switch (get_bits(A, "1:0")) // case (cpu_addr_in[1:0])
+ {
+ case 0b00: SET_BITS(prg_bank_a, "7:0", V, "7:0"); break; // 2'b00: prg_bank_a[7:0] <= cpu_data_in[7:0];
+ case 0b01: SET_BITS(prg_bank_b, "7:0", V, "7:0"); break; // 2'b01: prg_bank_b[7:0] <= cpu_data_in[7:0];
+ case 0b10: SET_BITS(prg_bank_b, "7:0", V, "7:0"); break; // 2'b10: prg_bank_c[7:0] <= cpu_data_in[7:0];
+ //case 0b11: SET_BITS(prg_bank_6000, "7:0", V, "7:0"); break; //2'b11: prg_bank_6000[7:0] <= cpu_data_in[7:0];
+ }
+ }
+ else {
+ switch (get_bits(A, "2:0")) // case (cpu_addr_in[2:0])
+ {
+ case 0b000: SET_BITS(chr_bank_a, "7:0", V, "7:0"); break; // 3'b000: chr_bank_a[7:0] <= cpu_data_in[7:0];
+ case 0b001: SET_BITS(chr_bank_b, "7:0", V, "7:0"); break; // 3'b001: chr_bank_b[7:0] <= cpu_data_in[7:0];
+ case 0b010: SET_BITS(chr_bank_c, "7:0", V, "7:0"); break; // 3'b010: chr_bank_c[7:0] <= cpu_data_in[7:0];
+ case 0b011: SET_BITS(chr_bank_d, "7:0", V, "7:0"); break; // 3'b011: chr_bank_d[7:0] <= cpu_data_in[7:0];
+ case 0b100: SET_BITS(chr_bank_e, "7:0", V, "7:0"); break; // 3'b100: chr_bank_e[7:0] <= cpu_data_in[7:0];
+ case 0b101: SET_BITS(chr_bank_f, "7:0", V, "7:0"); break; // 3'b101: chr_bank_f[7:0] <= cpu_data_in[7:0];
+ case 0b110: SET_BITS(chr_bank_g, "7:0", V, "7:0"); break; // 3'b110: chr_bank_g[7:0] <= cpu_data_in[7:0];
+ case 0b111: SET_BITS(chr_bank_h, "7:0", V, "7:0"); break; // 3'b111: chr_bank_h[7:0] <= cpu_data_in[7:0];
+ }
+ }
+ break;
+ }
+ }
+
+ // Mapper #67 - Sunsoft-3
+ if (mapper == 0b100100)
+ {
+ if (get_bits(A, "11")) // if (cpu_addr_in[11])
+ {
+ switch (get_bits(A, "14:12")) // case (cpu_addr_in[14:12])
+ {
+ case 0b000: // 3'b000: chr_bank_a[6:1] <= cpu_data_in[5:0]; // $8800
+ SET_BITS(chr_bank_a, "6:1", V, "5:0"); break;
+ case 0b001: // 3'b001: chr_bank_c[6:1] <= cpu_data_in[5:0]; // $9800
+ SET_BITS(chr_bank_c, "6:1", V, "5:0"); break;
+ case 0b010: // 3'b010: chr_bank_e[6:1] <= cpu_data_in[5:0]; // $A800
+ SET_BITS(chr_bank_e, "6:1", V, "5:0"); break;
+ case 0b011: // 3'b011: chr_bank_g[6:1] <= cpu_data_in[5:0]; // $B800
+ SET_BITS(chr_bank_g, "6:1", V, "5:0"); break;
+ case 0b100: // 3'b100: begin // $C800, IRQ load
+ mapper67_irq_latch = ~mapper67_irq_latch;
+ if (mapper67_irq_latch)
+ SET_BITS(mapper67_irq_counter, "15:8", V, "7:0"); // mapper67_irq_counter[15:8] <= cpu_data_in[7:0];
+ else
+ SET_BITS(mapper67_irq_counter, "7:0", V, "7:0"); // mapper67_irq_counter[7:0] <= cpu_data_in[7:0];
+ break;
+ case 0b101: // 3'b101: begin // $D800, IRQ enable
+ mapper67_irq_latch = 0; // mapper67_irq_latch <= 0;
+ SET_BITS(mapper67_irq_enabled, "0", V, "4"); // mapper67_irq_enabled <= cpu_data_in[4];
+ break;
+ case 0b110: // 3'b110: mirroring[1:0] <= cpu_data_in[1:0]; // $E800
+ SET_BITS(mirroring, "1:0", V, "1:0");
+ break;
+ case 0b111: // 3'b111: prg_bank_a[4:1] <= cpu_data_in[3:0]; // $F800
+ SET_BITS(prg_bank_a, "4:1", V, "3:0");
+ break;
+ }
+ }
+ else {
+ // Interrupt Acknowledge ($8000)
+ X6502_IRQEnd(FCEU_IQEXT); // mapper67_irq_out <= 0;
+ }
+ }
+
+ // Mapper #89 - Sunsoft-2 chip on the Sunsoft-3 board
+ if (mapper == 0b100101)
+ {
+ // prg_bank_a[3:1] <= cpu_data_in[6:4];
+ SET_BITS(prg_bank_a, "3:1", V, "6:4");
+ // chr_bank_a[6:3] <= {cpu_data_in[7], cpu_data_in[2:0]};
+ SET_BITS(chr_bank_a, "6:3", V, "7,2:0");
+ // mirroring[1:0] <= {1'b1, cpu_data_in[3]};
+ SET_BITS(mirroring, "1", 1, "0");
+ SET_BITS(mirroring, "0", V, "3");
+ }
+ }
+
+ COOLGIRL_Sync();
+}
+
+static DECLFR(MAFRAM) {
+ if ((mapper == 0b000000) && (A >= 0x5000) && (A < 0x6000))
+ return 0;
+
+ // Mapper #163
+ // (USE_MAPPER_163 && (mapper == 5'b00110) && m2 && romsel && cpu_rw_in && ((cpu_addr_in[14:8] & 7'h77) == 7'h51)) ?
+ if ((mapper == 0b000110) && ((A & 0x7700) == 0x5100))
+ return mapper163_r2 | mapper163_r0 | mapper163_r1 | ~mapper163_r3; // {1'b1, r2 | r0 | r1 | ~r3}
+ // (USE_MAPPER_163 && (mapper == 5'b00110) && m2 && romsel && cpu_rw_in && ((cpu_addr_in[14:8] & 7'h77) == 7'h55)) ?
+ if ((mapper == 0b000110) && ((A & 0x7700) == 0x5500))
+ return (mapper163_r5 & 1) ? mapper163_r2 : mapper163_r1; // {1'b1, r5[0] ? r2 : r1}
+
+ // MMC5
+ if ((mapper == 0b001111) && (A == 0x5204))
+ {
+ int ppuon = (PPU[1] & 0x18);
+ uint8 r = (!ppuon || scanline + 1 >= 241) ? 0 : 1;
+ uint8 p = mmc5_irq_out;
+ X6502_IRQEnd(FCEU_IQEXT);
+ mmc5_irq_out = 0;
+ return (p << 7) | (r << 6);
+ }
+
+ // Mapper #36 is assigned to TXC's PCB 01-22000-400
+ if ((mapper == 0b011101) && ((A & 0xE100) == 0x4100)) // (USE_MAPPER_036 && mapper == 5'b11101 && {cpu_addr_in[14:13], cpu_addr_in[8]} == 3'b101) ?
+ {
+ return (prg_bank_a & 0x0C) << 2; // {1'b1, 2'b00, prg_bank_a[3:2], 4'b00}
+ }
+
+ // Mapper #83 - Cony/Yoko
+ if ((mapper == 0b100011) && ((A & 0x7000) == 0x5000)) return flags & 3;
+
+ // Mapper #90 - JY
+ if ((mapper == 0b001101) && (A == 0x5800)) return (mul1 * mul2) & 0xFF;
+ if ((mapper == 0b001101) && (A == 0x5801)) return ((mul1 * mul2) >> 8) & 0xFF;
+
+ if (sram_enabled && !map_rom_on_6000 && (A >= 0x6000) && (A < 0x8000))
+ return CartBR(A); // SRAM
+ if (map_rom_on_6000 && (A >= 0x6000) && (A < 0x8000))
+ return CartBR(A); // PRG
+
+ return X.DB; // Open bus
+}
+
+static void COOLGIRL_ScanlineCounter(void) {
+ // for MMC3 and MMC3-based
+ if (mmc3_irq_reload || !mmc3_irq_counter)
+ {
+ mmc3_irq_counter = mmc3_irq_latch;
+ mmc3_irq_reload = 0;
+ }
+ else
+ mmc3_irq_counter--;
+ if (!mmc3_irq_counter && mmc3_irq_enabled)
+ X6502_IRQBegin(FCEU_IQEXT);
+
+ // for MMC5
+ if (mmc5_irq_line == scanline + 1)
+ {
+ if (mmc5_irq_enabled)
+ {
+ X6502_IRQBegin(FCEU_IQEXT);
+ mmc5_irq_out = 1;
+ }
+ }
+
+ // for mapper #163
+ if (scanline == 239)
+ {
+ mapper_163_latch = 0;
+ COOLGIRL_Sync_CHR();
+ }
+ else if (scanline == 127)
+ {
+ mapper_163_latch = 1;
+ COOLGIRL_Sync_CHR();
+ }
+}
+
+static void COOLGIRL_CpuCounter(int a) {
+ while (a--)
+ {
+ // Mapper #23 - VRC4
+ if (vrc4_irq_control & 2) // if (ENABLE_MAPPER_021_022_023_025 & ENABLE_VRC4_INTERRUPTS & (vrc4_irq_control[1]))
+ {
+ // Cycle mode without prescaler is not used by any games? It's missed in fceux source code.
+ if (vrc4_irq_control & 4) // if (vrc4_irq_control[2]) // cycle mode
+ {
+ FCEU_PrintError("Cycle IRQ mode is not supported, please report to Cluster");
+ vrc4_irq_value++; // {carry, vrc4_irq_value[7:0]} = vrc4_irq_value[7:0] + 1'b1; // just count IRQ value
+ if (vrc4_irq_value == 0) // if (carry)
+ {
+ X6502_IRQBegin(FCEU_IQEXT); // vrc4_irq_out = 1;
+ vrc4_irq_value = vrc4_irq_latch; // vrc4_irq_value[7:0] = vrc4_irq_latch[7:0];
+ }
+ }
+ else {
+ vrc4_irq_prescaler++; // vrc4_irq_prescaler = vrc4_irq_prescaler + 1'b1; // count prescaler
+ // if ((vrc4_irq_prescaler_counter[1] == 0 && vrc4_irq_prescaler == 114)
+ // || (vrc4_irq_prescaler_counter[1] == 1 && vrc4_irq_prescaler == 113)) // 114, 114, 113
+ if ((!(vrc4_irq_prescaler_counter & 2) && vrc4_irq_prescaler == 114) || ((vrc4_irq_prescaler_counter & 2) && vrc4_irq_prescaler == 113))
+ {
+ vrc4_irq_prescaler = 0; // vrc4_irq_prescaler = 0;
+ vrc4_irq_prescaler_counter++; // vrc4_irq_prescaler_counter = vrc4_irq_prescaler_counter + 1'b1;
+ if (vrc4_irq_prescaler_counter == 0b11) vrc4_irq_prescaler_counter = 0; // if (vrc4_irq_prescaler_counter == 2'b11) vrc4_irq_prescaler_counter = 2'b00;
+ vrc4_irq_value++; // {carry, vrc4_irq_value[7:0]} = vrc4_irq_value[7:0] + 1'b1;
+ if (vrc4_irq_value == 0) // f (carry)
+ {
+ X6502_IRQBegin(FCEU_IQEXT);
+ vrc4_irq_value = vrc4_irq_latch; // irq_cpu_value[7:0] = vrc4_irq_latch[7:0];
+ }
+ }
+ }
+ }
+
+ // Mapper #73 - VRC3
+ if (vrc3_irq_control & 2)
+ {
+ if (vrc3_irq_control & 4) // if (vrc3_irq_control[2])
+ { // 8-bit mode
+ //vrc3_irq_value = set_bits(vrc3_irq_value, "7:0", get_bits(vrc3_irq_value, "7:0") + 1); // vrc3_irq_value[7:0] = vrc3_irq_value[7:0] + 1'b1;
+ vrc3_irq_value = (vrc3_irq_value & 0xFF00) | ((vrc3_irq_value + 1) & 0xFF);
+ //if (get_bits(vrc3_irq_value, "7:0") == 0) // if (vrc3_irq_value[7:0] == 0)
+ if ((vrc3_irq_value & 0xFF) == 0)
+ {
+ X6502_IRQBegin(FCEU_IQEXT); // vrc3_irq_out = 1;
+ //SET_BITS(vrc3_irq_value, "7:0", vrc3_irq_latch, "7:0"); // vrc3_irq_value[7:0] = vrc3_irq_latch[7:0];
+ vrc3_irq_value = (vrc3_irq_value & 0xFF00) | (vrc3_irq_latch & 0xFF);
+ }
+ }
+ else { // 16-bit
+ //vrc3_irq_value = set_bits(vrc3_irq_value, "15:0", get_bits(vrc3_irq_value, "15:0") + 1); // vrc3_irq_value[15:0] = vrc3_irq_value[15:0] + 1'b1;
+ vrc3_irq_value += 1;
+ if (vrc3_irq_value == 0) // if (vrc3_irq_value[15:0] == 0)
+ {
+ X6502_IRQBegin(FCEU_IQEXT); // vrc3_irq_out = 1;
+ //SET_BITS(vrc3_irq_value, "15:0", vrc3_irq_latch, "15:0"); // vrc3_irq_value[15:0] = vrc3_irq_latch[15:0];
+ vrc3_irq_value = vrc3_irq_latch;
+ }
+ }
+ }
+
+ // Mapper #69 - Sunsoft FME-7
+ // if (ENABLE_MAPPER_069 & fme7_counter_enabled)
+ if (mapper69_counter_enabled)
+ {
+ // {carry, fme7_irq_value[15:0]} = {0'b0, fme7_irq_value[15:0]} - 1'b1;
+ mapper69_irq_value--;
+ // if (fme7_irq_enabled && carry) fme7_irq_out = 1;
+ if (mapper69_irq_value == 0xFFFF) X6502_IRQBegin(FCEU_IQEXT);
+ }
+
+ // Mapper #18
+ if (mapper18_irq_control & 1) // if (mapper18_irq_control[0])
+ {
+ uint8 carry;
+ //carry = get_bits(mapper18_irq_value, "3:0") - 1;
+ carry = (mapper18_irq_value & 0x0F) - 1;
+ //SET_BITS(mapper18_irq_value, "3:0", carry, "3:0");
+ mapper18_irq_value = (mapper18_irq_value & 0xFFF0) | (carry & 0x0F);
+ carry = (carry >> 4) & 1;
+ // if (mapper18_irq_control[3] == 1'b0)
+ if (!(mapper18_irq_control & 0b1000))
+ {
+ //carry = get_bits(mapper18_irq_value, "7:4") - carry;
+ carry = ((mapper18_irq_value >> 4) & 0x0F) - carry;
+ //SET_BITS(mapper18_irq_value, "7:4", carry, "3:0");
+ mapper18_irq_value = (mapper18_irq_value & 0xFF0F) | ((carry & 0x0F) << 4);
+ carry = (carry >> 4) & 1;
+ }
+ // if (mapper18_irq_control[3:2] == 2'b00)
+ if (!(mapper18_irq_control & 0b1100))
+ {
+ //carry = get_bits(mapper18_irq_value, "11:8") - carry;
+ carry = ((mapper18_irq_value >> 8) & 0x0F) - carry;
+ //SET_BITS(mapper18_irq_value, "11:8", carry, "3:0");
+ mapper18_irq_value = (mapper18_irq_value & 0xF0FF) | ((carry & 0x0F) << 8);
+ carry = (carry >> 4) & 1;
+ }
+ // if (mapper18_irq_control[3:1] == 3'b000)
+ if (!(mapper18_irq_control & 0b1110))
+ {
+ //carry = get_bits(mapper18_irq_value, "15:12") - carry;
+ carry = ((mapper18_irq_value >> 12) & 0x0F) - carry;
+ //SET_BITS(mapper18_irq_value, "15:12", carry, "3:0");
+ mapper18_irq_value = (mapper18_irq_value & 0x0FFF) | ((carry & 0x0F) << 12);
+ carry = (carry >> 4) & 1;
+ }
+ if (carry)
+ X6502_IRQBegin(FCEU_IQEXT);
+ }
+
+ // Mapper #65 - Irem's H3001
+ // if (mapper65_irq_enabled)
+ if (mapper65_irq_enabled)
+ {
+ if (mapper65_irq_value != 0) // if (mapper65_irq_value[15:0] != 0)
+ {
+ mapper65_irq_value--; // mapper65_irq_value[15:0] = mapper65_irq_value[15:0] - 1;
+ if (!mapper65_irq_value)
+ X6502_IRQBegin(FCEU_IQEXT); // if (mapper65_irq_value[15:0] == 0) irq_cpu_out = 1;
+ }
+ }
+
+ // Mapper #42
+ if (mapper42_irq_enabled)
+ {
+ //mapper42_irq_value = set_bits(mapper42_irq_value, "14:0", get_bits(mapper42_irq_value, "14:0") + 1);
+ //if (get_bits(mapper42_irq_value, "14:13") == 0b11)
+ mapper42_irq_value++;
+ if (mapper42_irq_value >> 15) mapper42_irq_value = 0;
+ if (((mapper42_irq_value >> 13) & 0b11) == 0b11)
+ X6502_IRQBegin(FCEU_IQEXT);
+ else
+ X6502_IRQEnd(FCEU_IQEXT);
+ }
+
+ // Mapper #83 - Cony/Yoko
+ if (mapper83_irq_enabled)
+ {
+ if (mapper83_irq_counter == 0) // if (mapper83_irq_counter == 0)
+ X6502_IRQBegin(FCEU_IQEXT); // mapper83_irq_out <= 1;
+ mapper83_irq_counter--; // mapper83_irq_counter = mapper83_irq_counter - 1'b1;
+ }
+
+ // Mapper #67 - Sunsoft-3
+ if (mapper67_irq_enabled)
+ {
+ mapper67_irq_counter--; // mapper67_irq_counter = mapper67_irq_counter - 1'b1;
+ if (mapper67_irq_counter == 0xFFFF) // if (mapper67_irq_counter == 16'hFFFF)
+ {
+ X6502_IRQBegin(FCEU_IQEXT); // mapper67_irq_out <= 1; // fire IRQ
+ mapper67_irq_enabled = 0; // mapper67_irq_enabled <= 0; // disable IRQ
+ }
+ }
+ }
+}
+
+static void COOLGIRL_PPUHook(uint32 A) {
+ // For TxROM
+ if ((mapper == 0b010100) && (flags & 1))
+ {
+ setmirror(MI_0 + (TKSMIR[(A & 0x1FFF) >> 10] >> 7));
+ }
+
+ // Mapper #9 and #10 - MMC2 and MMC4
+ if (mapper == 0b010001)
+ {
+ if ((A >> 4) == 0xFD) // if (ppu_addr_in[13:3] == 11'b00111111011) ppu_latch0 = 0;
+ {
+ ppu_latch0 = 0;
+ COOLGIRL_Sync_CHR();
+ }
+ if ((A >> 4) == 0xFE) // if (ppu_addr_in[13:3] == 11'b00111111101) ppu_latch0 = 1;
+ {
+ ppu_latch0 = 1;
+ COOLGIRL_Sync_CHR();
+ }
+ if ((A >> 4) == 0x1FD) // if (ppu_addr_in[13:3] == 11'b01111111011) ppu_latch1 = 0;
+ {
+ ppu_latch1 = 0;
+ COOLGIRL_Sync_CHR();
+ }
+ if ((A >> 4) == 0x1FE) // if (ppu_addr_in[13:3] == 11'b01111111101) ppu_latch1 = 1;
+ {
+ ppu_latch1 = 1;
+ COOLGIRL_Sync_CHR();
+ }
+ }
+}
+
+static void COOLGIRL_Reset(void) {
+ sram_enabled = 0;
+ sram_page = 0;
+ can_write_chr = 0;
+ map_rom_on_6000 = 0;
+ flags = 0;
+ mapper = 0;
+ can_write_flash = 0;
+ mirroring = 0;
+ four_screen = 0;
+ lockout = 0;
+ prg_base = 0;
+ prg_mask = 0b11111000 << 14;
+ prg_mode = 0;
+ prg_bank_6000 = 0;
+ prg_bank_a = 0;
+ prg_bank_b = 1;
+ prg_bank_c = ~1;
+ prg_bank_d = ~0;
+ chr_mask = 0;
+ chr_mode = 0;
+ chr_bank_a = 0;
+ chr_bank_b = 1;
+ chr_bank_c = 2;
+ chr_bank_d = 3;
+ chr_bank_e = 4;
+ chr_bank_f = 5;
+ chr_bank_g = 6;
+ chr_bank_h = 7;
+ ppu_latch0 = 0;
+ ppu_latch1 = 0;
+ lreset = 0;
+ mmc1_load_register = 0;
+ mmc3_internal = 0;
+ mapper69_internal = 0;
+ mapper112_internal = 0;
+ mapper_163_latch = 0;
+ mapper163_r0 = 0;
+ mapper163_r1 = 0;
+ mapper163_r2 = 0;
+ mapper163_r3 = 0;
+ mapper163_r4 = 0;
+ mapper163_r5 = 0;
+ mul1 = 0;
+ mul2 = 0;
+ mmc3_irq_enabled = 0;
+ mmc3_irq_latch = 0;
+ mmc3_irq_counter = 0;
+ mmc3_irq_reload = 0;
+ mmc5_irq_enabled = 0;
+ mmc5_irq_line = 0;
+ mmc5_irq_out = 0;
+ mapper18_irq_value = 0;
+ mapper18_irq_control = 0;
+ mapper18_irq_latch = 0;
+ mapper65_irq_enabled = 0;
+ mapper65_irq_value = 0;
+ mapper65_irq_latch = 0;
+ mapper69_irq_enabled = 0;
+ mapper69_counter_enabled = 0;
+ mapper69_irq_value = 0;
+ vrc4_irq_value = 0;
+ vrc4_irq_control = 0;
+ vrc4_irq_latch = 0;
+ vrc4_irq_prescaler = 0;
+ vrc4_irq_prescaler_counter = 0;
+ vrc3_irq_value = 0;
+ vrc3_irq_control = 0;
+ vrc3_irq_latch = 0;
+ mapper42_irq_enabled = 0;
+ mapper42_irq_value = 0;
+ mapper90_xor = 0;
+ flash_state = 0;
+ cfi_mode = 0;
+ COOLGIRL_Sync();
+}
+
+static void COOLGIRL_Power(void) {
+ FCEU_CheatAddRAM(32, 0x6000, SRAM);
+ SetReadHandler(0x4020, 0x7FFF, MAFRAM);
+ SetReadHandler(0x8000, 0xFFFF, CartBR);
+ SetWriteHandler(0x4020, 0xFFFF, COOLGIRL_WRITE);
+ GameHBIRQHook = COOLGIRL_ScanlineCounter;
+ MapIRQHook = COOLGIRL_CpuCounter;
+ PPU_hook = COOLGIRL_PPUHook;
+ COOLGIRL_Reset();
+}
+
+static void COOLGIRL_Close(void) {
+ if (CHR_RAM)
+ FCEU_gfree(CHR_RAM);
+ if (SRAM)
+ FCEU_gfree(SRAM);
+ if (SAVE_FLASH)
+ FCEU_gfree(SAVE_FLASH);
+ if (CFI)
+ FCEU_gfree(CFI);
+ CHR_RAM = SRAM = SAVE_FLASH = CFI = NULL;
+}
+
+static void COOLGIRL_Restore(int version) {
+ COOLGIRL_Sync();
+ lreset = 0;
+}
+
+#define ExState(var, varname) AddExState(&var, sizeof(var), 0, varname)
+
+void COOLGIRL_Init(CartInfo *info) {
+ CHR_RAM_SIZE = info->ines2 ? (info->vram_size + info->battery_vram_size) : (512 * 1024);
+ CHR_RAM = (uint8*)FCEU_gmalloc(CHR_RAM_SIZE);
+ memset(CHR_RAM, 0, CHR_RAM_SIZE);
+ SetupCartCHRMapping(CHR_RAM_CHIP, CHR_RAM, CHR_RAM_SIZE, 0);
+ AddExState(CHR_RAM, sizeof(CHR_RAM_SIZE), 0, "CHR_");
+
+ SRAM_SIZE = info->ines2 ? (info->wram_size + info->battery_wram_size) : (32 * 1024);
+ SRAM = (uint8*)FCEU_gmalloc(SRAM_SIZE);
+ memset(SRAM, 0, SRAM_SIZE);
+ SetupCartPRGMapping(SRAM_CHIP, SRAM, SRAM_SIZE, 1);
+ AddExState(SRAM, 32 * 1024, 0, "SRAM");
+ info->SaveGame[0] = SRAM;
+ info->SaveGameLen[0] = 32 * 1024;
+
+ SAVE_FLASH = (uint8*)FCEU_gmalloc(SAVE_FLASH_SIZE);
+ SetupCartPRGMapping(FLASH_CHIP, SAVE_FLASH, SAVE_FLASH_SIZE, 1);
+ AddExState(SAVE_FLASH, SAVE_FLASH_SIZE, 0, "SAVF");
+ info->SaveGame[1] = SAVE_FLASH;
+ info->SaveGameLen[1] = SAVE_FLASH_SIZE;
+
+ CFI = (uint8*)FCEU_gmalloc(0x8000);
+ for (int i = 0; i < 0x8000; i += sizeof(cfi_data))
+ memcpy(&CFI[i], cfi_data, sizeof(cfi_data));
+ SetupCartPRGMapping(CFI_CHIP, CFI, 0x8000, 0);
+
+ ExState(sram_enabled, "SREN");
+ ExState(sram_page, "SRPG");
+ ExState(can_write_chr, "SRWR");
+ ExState(map_rom_on_6000, "MR6K");
+ ExState(flags, "FLGS");
+ ExState(mapper, "MPPR");
+ ExState(can_write_flash, "FLWR");
+ ExState(mirroring, "MIRR");
+ ExState(four_screen, "4SCR");
+ ExState(lockout, "LOCK");
+ ExState(prg_base, "PBAS");
+ ExState(prg_mask, "PMSK");
+ ExState(prg_mode, "PMOD");
+ ExState(prg_bank_6000, "P6BN");
+ ExState(prg_bank_a, "PABN");
+ ExState(prg_bank_b, "PBBN");
+ ExState(prg_bank_c, "PCBN");
+ ExState(prg_bank_d, "PDBN");
+ ExState(chr_mask, "CMSK");
+ ExState(chr_mode, "CMOD");
+ ExState(chr_bank_a, "CABN");
+ ExState(chr_bank_b, "CBBN");
+ ExState(chr_bank_c, "CCBN");
+ ExState(chr_bank_d, "CDBN");
+ ExState(chr_bank_e, "CEBN");
+ ExState(chr_bank_f, "CFBN");
+ ExState(chr_bank_g, "CGBN");
+ ExState(chr_bank_h, "CHBN");
+ ExState(ppu_latch0, "PPU0");
+ ExState(ppu_latch1, "PPU1");
+ ExState(lreset, "LRST");
+ ExState(mmc1_load_register, "M01R");
+ ExState(mmc3_internal, "M01I");
+ ExState(mapper69_internal, "M69I");
+ ExState(mapper112_internal, "112I");
+ ExState(mapper_163_latch, "163L");
+ ExState(mapper163_r0, "1630");
+ ExState(mapper163_r1, "1631");
+ ExState(mapper163_r2, "1632");
+ ExState(mapper163_r3, "1633");
+ ExState(mapper163_r4, "1634");
+ ExState(mapper163_r5, "1635");
+ ExState(mul1, "MUL1");
+ ExState(mul2, "MUL2");
+ ExState(mmc3_irq_enabled, "M4IE");
+ ExState(mmc3_irq_latch, "M4IL");
+ ExState(mmc3_irq_counter, "M4IC");
+ ExState(mmc3_irq_reload, "M4IR");
+ ExState(mmc5_irq_enabled, "M5IE");
+ ExState(mmc5_irq_line, "M5IL");
+ ExState(mmc5_irq_out, "M5IO");
+ ExState(mapper18_irq_value, "18IV");
+ ExState(mapper18_irq_control, "18IC");
+ ExState(mapper18_irq_latch, "18IL");
+ ExState(mapper65_irq_enabled, "65IE");
+ ExState(mapper65_irq_value, "65IV");
+ ExState(mapper65_irq_latch, "65IL");
+ ExState(mapper69_irq_enabled, "69IE");
+ ExState(mapper69_counter_enabled, "69CE");
+ ExState(mapper69_irq_value, "69IV");
+ ExState(vrc4_irq_value, "V4IV");
+ ExState(vrc4_irq_control, "V4IC");
+ ExState(vrc4_irq_latch, "V4IL");
+ ExState(vrc4_irq_prescaler, "V4PP");
+ ExState(vrc4_irq_prescaler_counter, "V4PC");
+ ExState(vrc3_irq_value, "V3IV");
+ ExState(vrc3_irq_control, "V3IC");
+ ExState(vrc3_irq_latch, "V3IL");
+ ExState(mapper42_irq_enabled, "42IE");
+ ExState(mapper42_irq_value, "42IV");
+ ExState(mapper83_irq_enabled_latch, "M83L");
+ ExState(mapper83_irq_enabled, "M83I");
+ ExState(mapper83_irq_counter, "M83C");
+ ExState(mapper90_xor, "90XR");
+ ExState(mapper67_irq_enabled, "67IE");
+ ExState(mapper67_irq_latch, "67IL");
+ ExState(mapper67_irq_counter, "67IC");
+ ExState(flash_state, "FLST");
+ ExState(flash_buffer_a, "FLBA");
+ ExState(flash_buffer_v, "FLBV");
+ ExState(cfi_mode, "CFIM");
+
+ info->Power = COOLGIRL_Power;
+ info->Reset = COOLGIRL_Reset;
+ info->Close = COOLGIRL_Close;
+ GameStateRestore = COOLGIRL_Restore;
+}
diff --git a/src/boards/warface.cpp b/src/boards/warface.cpp
new file mode 100644
index 00000000..8db2edbc
--- /dev/null
+++ b/src/boards/warface.cpp
@@ -0,0 +1,99 @@
+/* FCE Ultra - NES/Famicom Emulator
+*
+* Copyright notice for this file:
+* Copyright (C) 2020 Cluster
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "mapinc.h"
+
+static uint8 prg_bank = 0;
+static uint8 chr_bank = 0;
+static uint16 timer = 0;
+
+static void WARFACE_Sync(void) {
+ setprg16(0x8000, prg_bank);
+ setprg16(0xC000, ~0);
+
+ if (chr_bank & 0x80)
+ {
+ if (scanline < 63 || scanline > 240)
+ setchr4(0x0000, (chr_bank & 0x1C) | 0);
+ else if (scanline < 127)
+ setchr4(0x0000, (chr_bank & 0x1C) | 1);
+ else if (scanline < 191)
+ setchr4(0x0000, (chr_bank & 0x1C) | 2);
+ else
+ setchr4(0x0000, (chr_bank & 0x1C) | 3);
+ }
+ else {
+ setchr4(0x0000, chr_bank & 0x1F);
+ }
+ setchr4(0x1000, ~0);
+}
+
+static DECLFW(WARFACE_WRITE) {
+ if ((A & 1) == 0)
+ {
+ prg_bank = V;
+ if (V & 0x80) timer = 4095;
+ X6502_IRQEnd(FCEU_IQEXT);
+ }
+ else {
+ chr_bank = V;
+ }
+
+ WARFACE_Sync();
+}
+
+static void WARFACE_ScanlineCounter(void) {
+ WARFACE_Sync();
+}
+
+static void WARFACE_CpuCounter(int a) {
+ while (a--)
+ {
+ if (timer > 0)
+ {
+ timer--;
+ if (!timer) X6502_IRQBegin(FCEU_IQEXT);
+ }
+ }
+}
+
+static void WARFACE_Reset(void) {
+ WARFACE_Sync();
+}
+
+static void WARFACE_Power(void) {
+ SetReadHandler(0x8000, 0xFFFF, CartBR);
+ SetWriteHandler(0x6000, 0x7FFF, WARFACE_WRITE);
+ GameHBIRQHook = WARFACE_ScanlineCounter;
+ MapIRQHook = WARFACE_CpuCounter;
+ WARFACE_Reset();
+}
+
+static void WARFACE_Restore(int version) {
+ WARFACE_Sync();
+}
+
+void WARFACE_Init(CartInfo *info) {
+ AddExState(&prg_bank, sizeof(prg_bank), 0, "PRGL");
+ AddExState(&chr_bank, sizeof(chr_bank), 0, "CHRL");
+ info->Power = WARFACE_Power;
+ info->Reset = WARFACE_Reset;
+ GameStateRestore = WARFACE_Restore;
+}
diff --git a/src/ines.cpp b/src/ines.cpp
index 92fa0bdf..6ddc8c43 100644
--- a/src/ines.cpp
+++ b/src/ines.cpp
@@ -453,7 +453,7 @@ typedef struct {
// to something more unified for ines 2.0 specific
static int not_power2[] =
{
- 53, 198, 228, 547
+ 53, 198, 228, 342, 547
};
BMAPPINGLocal bmap[] = {
@@ -730,11 +730,14 @@ BMAPPINGLocal bmap[] = {
{"HP10xx/H20xx Boards", 260, BMCHPxx_Init},
{"810544-CA-1", 261, BMC810544CA1_Init},
{"SMD132/SMD133", 268, SMD132_SMD133_Init},
+ {"COOLGIRL", 342, COOLGIRL_Init},
{"Impact Soft MMC3 Flash Board", 406, Mapper406_Init },
{"KONAMI QTAi Board", 547, QTAi_Init },
+ {"WARFACE", 3914, WARFACE_Init },
+
{"", 0, NULL}
};
diff --git a/src/state.cpp b/src/state.cpp
index 78279c4b..3a8fac80 100644
--- a/src/state.cpp
+++ b/src/state.cpp
@@ -88,7 +88,7 @@ EMUFILE_MEMORY memory_savestate;
// temporary buffer for compressed data of a savestate
std::vector<uint8> compressed_buf;
-#define SFMDATA_SIZE (64)
+#define SFMDATA_SIZE (128)
static SFORMAT SFMDATA[SFMDATA_SIZE];
static int SFEXINDEX;
diff --git a/src/unif.cpp b/src/unif.cpp
index 617b41cb..b10a147a 100644
--- a/src/unif.cpp
+++ b/src/unif.cpp
@@ -473,9 +473,10 @@ static BMAPPING bmap[] = {
{ "HPxx", BMCHPxx_Init, 0 },
{ "MINDKIDS", MINDKIDS_Init, BMCFLAG_256KCHRR },
{ "FNS", FNS_Init, BMCFLAG_16KCHRR },
+ { "COOLGIRL", COOLGIRL_Init, 0 },
+ { "WARFACE", WARFACE_Init, 0 },
{ "BS-400R", BS400R_Init, 0 },
{ "BS-4040R", BS4040R_Init, 0 },
-
{ 0, 0, 0 }
};
diff --git a/src/unif.h b/src/unif.h
index b6759bdf..4c125595 100644
--- a/src/unif.h
+++ b/src/unif.h
@@ -160,6 +160,8 @@ void BMC80013B_Init(CartInfo *info);
void BMCHPxx_Init(CartInfo *info);
void MINDKIDS_Init(CartInfo *info);
void FNS_Init(CartInfo *info);
+void COOLGIRL_Init(CartInfo * info);
+void WARFACE_Init(CartInfo *info);
void BS400R_Init(CartInfo *info);
void BS4040R_Init(CartInfo *info);
void SMD132_SMD133_Init(CartInfo *info);
diff --git a/src/version.h b/src/version.h
index 01c9daae..2ce4b187 100644
--- a/src/version.h
+++ b/src/version.h
@@ -44,7 +44,7 @@
#elif defined(PUBLIC_RELEASE)
#define FCEU_SUBVERSION_STRING ""
#else
-#define FCEU_SUBVERSION_STRING "-interim git" SCM_REV_STR
+#define FCEU_SUBVERSION_STRING "-coolgirl git" SCM_REV_STR
#endif
#if defined(_MSC_VER)
diff --git a/vc/vc14_fceux.vcxproj b/vc/vc14_fceux.vcxproj
index 10bdf280..79aec3fe 100644
--- a/vc/vc14_fceux.vcxproj
+++ b/vc/vc14_fceux.vcxproj
@@ -473,6 +473,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)"</Command>
<ClCompile Include="..\src\boards\cheapocabra.cpp" />
<ClCompile Include="..\src\boards\cityfighter.cpp" />
<ClCompile Include="..\src\boards\coolboy.cpp" />
+ <ClCompile Include="..\src\boards\coolgirl.cpp" />
<ClCompile Include="..\src\boards\dance2000.cpp" />
<ClCompile Include="..\src\boards\eh8813a.cpp" />
<ClCompile Include="..\src\boards\et-100.cpp" />
@@ -510,6 +511,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)"</Command>
<ClCompile Include="..\src\boards\vrc6.cpp" />
<ClCompile Include="..\src\boards\vrc7.cpp" />
<ClCompile Include="..\src\boards\vrc7p.cpp" />
+ <ClCompile Include="..\src\boards\warface.cpp" />
<ClCompile Include="..\src\boards\yoko.cpp" />
<ClCompile Include="..\src\boards\__dummy_mapper.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
diff --git a/vc/vc14_fceux.vcxproj.filters b/vc/vc14_fceux.vcxproj.filters
index c270d091..0d5d7adf 100644
--- a/vc/vc14_fceux.vcxproj.filters
+++ b/vc/vc14_fceux.vcxproj.filters
@@ -1105,6 +1105,12 @@
<ClCompile Include="..\src\input\virtualboy.cpp">
<Filter>input</Filter>
</ClCompile>
+ <ClCompile Include="..\src\boards\coolgirl.cpp">
+ <Filter>boards</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\boards\warface.cpp">
+ <Filter>boards</Filter>
+ </ClCompile>
<ClCompile Include="..\src\input\lcdcompzapper.cpp">
<Filter>input</Filter>
</ClCompile>