33
.github/workflows/compilation.yml
vendored
Normal file
33
.github/workflows/compilation.yml
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
jobs:
|
||||
build-ps2:
|
||||
runs-on: ubuntu-latest
|
||||
container: ps2dev/ps2dev:latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
apk add build-base git bash
|
||||
|
||||
- name: Compile project
|
||||
run: |
|
||||
make -f Makefile.libretro platform=ps2 clean all
|
||||
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
|
||||
|
||||
- name: Upload artifacts
|
||||
if: ${{ success() }}
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: fceumm_libretro_ps2-${{ steps.slug.outputs.sha8 }}
|
||||
path: fceumm_libretro_ps2.a
|
||||
33
.github/workflows/crowdin_prep.yml
vendored
Normal file
33
.github/workflows/crowdin_prep.yml
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# Prepare source texts & upload them to Crowdin
|
||||
|
||||
name: Crowdin Source Texts Upload
|
||||
|
||||
# on change to the English texts
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'src/drivers/libretro/libretro_core_options.h'
|
||||
|
||||
jobs:
|
||||
upload_source_file:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Setup Java JDK
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Upload Source
|
||||
shell: bash
|
||||
env:
|
||||
CROWDIN_API_KEY: ${{ secrets.CROWDIN_API_KEY }}
|
||||
run: |
|
||||
python3 intl/upload_workflow.py $CROWDIN_API_KEY "libretro-fceumm" "src/drivers/libretro/libretro_core_options.h"
|
||||
46
.github/workflows/crowdin_translate.yml
vendored
Normal file
46
.github/workflows/crowdin_translate.yml
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
# Download translations form Crowdin & Recreate libretro_core_options_intl.h
|
||||
|
||||
name: Crowdin Translation Integration
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# please choose a random time & weekday to avoid all repos synching at the same time
|
||||
- cron: '20 1 * * 5' # Fridays at 1:20 AM, UTC
|
||||
|
||||
jobs:
|
||||
create_intl_file:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Setup Java JDK
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token.
|
||||
fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository.
|
||||
|
||||
- name: Create intl file
|
||||
shell: bash
|
||||
env:
|
||||
CROWDIN_API_KEY: ${{ secrets.CROWDIN_API_KEY }}
|
||||
run: |
|
||||
python3 intl/download_workflow.py $CROWDIN_API_KEY "libretro-fceumm" "src/drivers/libretro/libretro_core_options_intl.h"
|
||||
|
||||
- name: Commit files
|
||||
run: |
|
||||
git config --local user.email "github-actions@github.com"
|
||||
git config --local user.name "github-actions[bot]"
|
||||
git add intl/*_workflow.py "src/drivers/libretro/libretro_core_options_intl.h"
|
||||
git commit -m "Fetch translations & Recreate libretro_core_options_intl.h"
|
||||
|
||||
- name: GitHub Push
|
||||
uses: ad-m/github-push-action@v0.6.0
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
branch: ${{ github.ref }}
|
||||
302
.gitlab-ci.yml
Normal file
302
.gitlab-ci.yml
Normal file
@@ -0,0 +1,302 @@
|
||||
# DESCRIPTION: GitLab CI/CD for libRetro (NOT FOR GitLab-proper)
|
||||
|
||||
##############################################################################
|
||||
################################# BOILERPLATE ################################
|
||||
##############################################################################
|
||||
|
||||
# Core definitions
|
||||
.core-defs:
|
||||
variables:
|
||||
JNI_PATH: .
|
||||
CORENAME: fceumm
|
||||
MAKEFILE: Makefile.libretro
|
||||
|
||||
# Inclusion templates, required for the build to work
|
||||
include:
|
||||
################################## DESKTOPS ################################
|
||||
# Windows 64-bit
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/windows-x64-mingw.yml'
|
||||
|
||||
# Windows 32-bit
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/windows-i686-mingw.yml'
|
||||
|
||||
# Windows msvc10 64-bit
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/windows-x64-msvc10-msys2.yml'
|
||||
|
||||
# Windows msvc10 32-bit
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/windows-i686-msvc10-msys2.yml'
|
||||
|
||||
# Windows msvc05 32-bit
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/windows-i686-msvc05-msys2.yml'
|
||||
|
||||
# Linux 64-bit
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/linux-x64.yml'
|
||||
|
||||
# Linux 32-bit
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/linux-i686.yml'
|
||||
|
||||
# MacOS 64-bit
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/osx-x64.yml'
|
||||
|
||||
# MacOS ARM 64-bit
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/osx-arm64.yml'
|
||||
|
||||
################################## CELLULAR ################################
|
||||
# Android
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/android-jni.yml'
|
||||
|
||||
# iOS
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/ios-arm64.yml'
|
||||
|
||||
# iOS (armv7)
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/ios9.yml'
|
||||
|
||||
################################## CONSOLES ################################
|
||||
# PlayStation Portable
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/psp-static.yml'
|
||||
|
||||
# PlayStation Vita
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/vita-static.yml'
|
||||
|
||||
# PlayStation2
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/ps2-static.yml'
|
||||
|
||||
# Nintendo 3DS
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/ctr-static.yml'
|
||||
|
||||
# Nintendo GameCube
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/ngc-static.yml'
|
||||
|
||||
# Nintendo Wii
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/wii-static.yml'
|
||||
|
||||
# Nintendo WiiU
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/wiiu-static.yml'
|
||||
|
||||
# Nintendo Switch
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/libnx-static.yml'
|
||||
|
||||
# OpenDingux
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/dingux-mips32.yml'
|
||||
|
||||
# OpenDingux (ARM)
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/dingux-arm32.yml'
|
||||
|
||||
# tvOS (AppleTV)
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/tvos-arm64.yml'
|
||||
|
||||
#################################### MISC ##################################
|
||||
# Emscripten
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/emscripten-static.yml'
|
||||
|
||||
# Stages for building
|
||||
stages:
|
||||
- build-prepare
|
||||
- build-shared
|
||||
- build-static
|
||||
|
||||
##############################################################################
|
||||
#################################### STAGES ##################################
|
||||
##############################################################################
|
||||
#
|
||||
################################### DESKTOPS #################################
|
||||
# Windows 64-bit
|
||||
libretro-build-windows-x64:
|
||||
extends:
|
||||
- .libretro-windows-x64-mingw-make-default
|
||||
- .core-defs
|
||||
|
||||
# Windows 32-bit
|
||||
libretro-build-windows-i686:
|
||||
extends:
|
||||
- .libretro-windows-i686-mingw-make-default
|
||||
- .core-defs
|
||||
|
||||
# Windows msvc10 64-bit
|
||||
libretro-build-windows-msvc10-x64:
|
||||
extends:
|
||||
- .libretro-windows-x64-msvc10-msys2-make-default
|
||||
- .core-defs
|
||||
|
||||
# Windows msvc10 32-bit
|
||||
libretro-build-windows-msvc10-i686:
|
||||
extends:
|
||||
- .libretro-windows-i686-msvc10-msys2-make-default
|
||||
- .core-defs
|
||||
|
||||
# Windows msvc05 32-bit
|
||||
libretro-build-windows-msvc05-i686:
|
||||
extends:
|
||||
- .libretro-windows-i686-msvc05-msys2-make-default
|
||||
- .core-defs
|
||||
|
||||
# Linux 64-bit
|
||||
libretro-build-linux-x64:
|
||||
extends:
|
||||
- .libretro-linux-x64-make-default
|
||||
- .core-defs
|
||||
|
||||
# Linux 32-bit
|
||||
libretro-build-linux-i686:
|
||||
extends:
|
||||
- .libretro-linux-i686-make-default
|
||||
- .core-defs
|
||||
|
||||
# MacOS 64-bit
|
||||
libretro-build-osx-x64:
|
||||
extends:
|
||||
- .libretro-osx-x64-make-10-7
|
||||
- .core-defs
|
||||
|
||||
# MacOS ARM 64-bit
|
||||
libretro-build-osx-arm64:
|
||||
extends:
|
||||
- .libretro-osx-arm64-make-default
|
||||
- .core-defs
|
||||
|
||||
################################### CELLULAR #################################
|
||||
# Android ARMv7a
|
||||
android-armeabi-v7a:
|
||||
extends:
|
||||
- .libretro-android-jni-armeabi-v7a
|
||||
- .core-defs
|
||||
|
||||
# Android ARMv8a
|
||||
android-arm64-v8a:
|
||||
extends:
|
||||
- .libretro-android-jni-arm64-v8a
|
||||
- .core-defs
|
||||
|
||||
# Android 64-bit x86
|
||||
android-x86_64:
|
||||
extends:
|
||||
- .libretro-android-jni-x86_64
|
||||
- .core-defs
|
||||
|
||||
# Android 32-bit x86
|
||||
android-x86:
|
||||
extends:
|
||||
- .libretro-android-jni-x86
|
||||
- .core-defs
|
||||
|
||||
# iOS
|
||||
libretro-build-ios-arm64:
|
||||
extends:
|
||||
- .libretro-ios-arm64-make-default
|
||||
- .core-defs
|
||||
|
||||
# iOS (armv7) [iOS 9 and up]
|
||||
libretro-build-ios9:
|
||||
extends:
|
||||
- .libretro-ios9-make-default
|
||||
- .core-defs
|
||||
|
||||
# tvOS
|
||||
libretro-build-tvos-arm64:
|
||||
extends:
|
||||
- .libretro-tvos-arm64-make-default
|
||||
- .core-defs
|
||||
|
||||
################################### CONSOLES #################################
|
||||
# PlayStation Portable
|
||||
libretro-build-psp:
|
||||
extends:
|
||||
- .libretro-psp-static-retroarch-master
|
||||
- .core-defs
|
||||
|
||||
# PlayStation Vita
|
||||
libretro-build-vita:
|
||||
extends:
|
||||
- .libretro-vita-static-retroarch-master
|
||||
- .core-defs
|
||||
|
||||
# PlayStation2
|
||||
libretro-build-ps2:
|
||||
extends:
|
||||
- .libretro-ps2-static-retroarch-master
|
||||
- .core-defs
|
||||
|
||||
# Nintendo 3DS
|
||||
libretro-build-ctr:
|
||||
extends:
|
||||
- .libretro-ctr-static-retroarch-master
|
||||
- .core-defs
|
||||
|
||||
# Nintendo GameCube
|
||||
libretro-build-ngc:
|
||||
extends:
|
||||
- .libretro-ngc-static-retroarch-master
|
||||
- .core-defs
|
||||
|
||||
# Nintendo Wii
|
||||
libretro-build-wii:
|
||||
extends:
|
||||
- .libretro-wii-static-retroarch-master
|
||||
- .core-defs
|
||||
|
||||
# Nintendo WiiU
|
||||
libretro-build-wiiu:
|
||||
extends:
|
||||
- .libretro-wiiu-static-retroarch-master
|
||||
- .core-defs
|
||||
|
||||
# Nintendo Switch
|
||||
libretro-build-libnx-aarch64:
|
||||
extends:
|
||||
- .libretro-libnx-static-retroarch-master
|
||||
- .core-defs
|
||||
|
||||
# OpenDingux
|
||||
libretro-build-dingux-mips32:
|
||||
extends:
|
||||
- .libretro-dingux-mips32-make-default
|
||||
- .core-defs
|
||||
|
||||
# OpenDingux Beta
|
||||
libretro-build-dingux-odbeta-mips32:
|
||||
extends:
|
||||
- .libretro-dingux-odbeta-mips32-make-default
|
||||
- .core-defs
|
||||
|
||||
# RetroFW
|
||||
libretro-build-retrofw-mips32:
|
||||
extends:
|
||||
- .libretro-retrofw-mips32-make-default
|
||||
- .core-defs
|
||||
|
||||
# Miyoo
|
||||
libretro-build-miyoo-arm32:
|
||||
extends:
|
||||
- .libretro-miyoo-arm32-make-default
|
||||
- .core-defs
|
||||
|
||||
#################################### MISC ##################################
|
||||
# Emscripten
|
||||
libretro-build-emscripten:
|
||||
extends:
|
||||
- .libretro-emscripten-static-retroarch-master
|
||||
- .core-defs
|
||||
127
Makefile.common
127
Makefile.common
@@ -1,69 +1,76 @@
|
||||
ifeq ($(LIBRETRO_COMM_DIR),)
|
||||
LIBRETRO_COMM_DIR := $(CORE_DIR)/drivers/libretro/libretro-common
|
||||
endif
|
||||
INCFLAGS := -I$(CORE_DIR)/drivers/libretro -I$(LIBRETRO_COMM_DIR)/include -I$(CORE_DIR) -I$(CORE_DIR)/input -I$(CORE_DIR)/boards
|
||||
COREDEFINES = -D__LIBRETRO__ -DSOUND_QUALITY=0 -DPATH_MAX=1024 -DFCEU_VERSION_NUMERIC=9813 -DFRONTEND_SUPPORTS_RGB565
|
||||
|
||||
ifeq ($(PSS_STYLE),2)
|
||||
COREDEFINES += -DPSS_STYLE=2
|
||||
else
|
||||
COREDEFINES += -DPSS_STYLE=1
|
||||
INCFLAGS := \
|
||||
-I$(CORE_DIR)/drivers/libretro \
|
||||
-I$(LIBRETRO_COMM_DIR)/include \
|
||||
-I$(CORE_DIR) \
|
||||
-I$(CORE_DIR)/input \
|
||||
-I$(CORE_DIR)/boards
|
||||
|
||||
ifneq (,$(findstring msvc2003,$(platform)))
|
||||
INCFLAGS += -I$(LIBRETRO_COMM_DIR)/include/compat/msvc
|
||||
endif
|
||||
|
||||
ifeq ($(TUP_CWD),)
|
||||
FCEU_SRC_DIRS := $(CORE_DIR)/boards $(CORE_DIR)/input $(CORE_DIR)/mappers
|
||||
SOURCES_C := $(foreach dir,$(FCEU_SRC_DIRS),$(wildcard $(dir)/*.c))
|
||||
else
|
||||
SOURCES_C = $(CORE_DIR)/boards/*.c $(CORE_DIR)/input/*.c
|
||||
endif
|
||||
COREDEFINES = \
|
||||
-D__LIBRETRO__ \
|
||||
-DPATH_MAX=1024 \
|
||||
-DFCEU_VERSION_NUMERIC=9813 \
|
||||
-DFRONTEND_SUPPORTS_RGB565
|
||||
|
||||
FCEU_SRC_DIRS := \
|
||||
$(CORE_DIR)/boards \
|
||||
$(CORE_DIR)/input
|
||||
|
||||
SOURCES_C := $(foreach dir,$(FCEU_SRC_DIRS),$(wildcard $(dir)/*.c))
|
||||
|
||||
ifeq ($(HAVE_NTSC),1)
|
||||
COREDEFINES += -DHAVE_NTSC_FILTER -I$(CORE_DIR)/ntsc
|
||||
SOURCES_C += $(CORE_DIR)/ntsc/nes_ntsc.c
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_GRIFFIN),1)
|
||||
SOURCES_C += $(CORE_DIR)/drivers/libretro/griffin.c
|
||||
else
|
||||
SOURCES_C += \
|
||||
$(CORE_DIR)/drivers/libretro/libretro.c \
|
||||
$(CORE_DIR)/cart.c \
|
||||
$(CORE_DIR)/cheat.c \
|
||||
$(CORE_DIR)/crc32.c \
|
||||
$(CORE_DIR)/fceu-endian.c \
|
||||
$(CORE_DIR)/fceu-memory.c \
|
||||
$(CORE_DIR)/misc.c \
|
||||
$(CORE_DIR)/fceu.c \
|
||||
$(CORE_DIR)/fds.c \
|
||||
$(CORE_DIR)/fds_apu.c \
|
||||
$(CORE_DIR)/file.c \
|
||||
$(CORE_DIR)/filter.c \
|
||||
$(CORE_DIR)/general.c \
|
||||
$(CORE_DIR)/input.c \
|
||||
$(CORE_DIR)/md5.c \
|
||||
$(CORE_DIR)/nsf.c \
|
||||
$(CORE_DIR)/palette.c \
|
||||
$(CORE_DIR)/ppu.c \
|
||||
$(CORE_DIR)/sound.c \
|
||||
$(CORE_DIR)/state.c \
|
||||
$(CORE_DIR)/video.c \
|
||||
$(CORE_DIR)/vsuni.c
|
||||
|
||||
ifeq ($(STATIC_LINKING),1)
|
||||
else
|
||||
SOURCES_C += $(CORE_DIR)/drivers/libretro/libretro-common/streams/memory_stream.c \
|
||||
$(CORE_DIR)/drivers/libretro/libretro-common/compat/compat_snprintf.c \
|
||||
$(CORE_DIR)/drivers/libretro/libretro-common/string/stdstring.c \
|
||||
$(CORE_DIR)/drivers/libretro/libretro-common/encodings/encoding_utf.c \
|
||||
$(CORE_DIR)/drivers/libretro/libretro-common/compat/compat_strl.c
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
SOURCES_C += $(CORE_DIR)/debug.c
|
||||
endif
|
||||
COREDEFINES += \
|
||||
-DHAVE_NTSC_FILTER \
|
||||
-I$(CORE_DIR)/ntsc
|
||||
SOURCES_C += $(CORE_DIR)/ntsc/nes_ntsc.c
|
||||
endif
|
||||
|
||||
SOURCES_C += \
|
||||
$(CORE_DIR)/ines.c \
|
||||
$(CORE_DIR)/unif.c $(CORE_DIR)/x6502.c \
|
||||
$(CORE_DIR)/drivers/libretro/libretro_dipswitch.c
|
||||
$(CORE_DIR)/drivers/libretro/libretro.c \
|
||||
$(CORE_DIR)/drivers/libretro/libretro_dipswitch.c \
|
||||
$(CORE_DIR)/cart.c \
|
||||
$(CORE_DIR)/cheat.c \
|
||||
$(CORE_DIR)/crc32.c \
|
||||
$(CORE_DIR)/fceu-endian.c \
|
||||
$(CORE_DIR)/fceu-memory.c \
|
||||
$(CORE_DIR)/fceu.c \
|
||||
$(CORE_DIR)/fds.c \
|
||||
$(CORE_DIR)/fds_apu.c \
|
||||
$(CORE_DIR)/file.c \
|
||||
$(CORE_DIR)/filter.c \
|
||||
$(CORE_DIR)/general.c \
|
||||
$(CORE_DIR)/input.c \
|
||||
$(CORE_DIR)/md5.c \
|
||||
$(CORE_DIR)/nsf.c \
|
||||
$(CORE_DIR)/palette.c \
|
||||
$(CORE_DIR)/ppu.c \
|
||||
$(CORE_DIR)/sound.c \
|
||||
$(CORE_DIR)/state.c \
|
||||
$(CORE_DIR)/video.c \
|
||||
$(CORE_DIR)/vsuni.c \
|
||||
$(CORE_DIR)/ines.c \
|
||||
$(CORE_DIR)/unif.c \
|
||||
$(CORE_DIR)/x6502.c
|
||||
|
||||
ifneq ($(STATIC_LINKING), 1)
|
||||
SOURCES_C += \
|
||||
$(LIBRETRO_COMM_DIR)/compat/compat_posix_string.c \
|
||||
$(LIBRETRO_COMM_DIR)/compat/compat_snprintf.c \
|
||||
$(LIBRETRO_COMM_DIR)/compat/compat_strcasestr.c \
|
||||
$(LIBRETRO_COMM_DIR)/compat/compat_strl.c \
|
||||
$(LIBRETRO_COMM_DIR)/compat/fopen_utf8.c \
|
||||
$(LIBRETRO_COMM_DIR)/encodings/encoding_utf.c \
|
||||
$(LIBRETRO_COMM_DIR)/file/file_path.c \
|
||||
$(LIBRETRO_COMM_DIR)/file/file_path_io.c \
|
||||
$(LIBRETRO_COMM_DIR)/streams/file_stream.c \
|
||||
$(LIBRETRO_COMM_DIR)/streams/file_stream_transforms.c \
|
||||
$(LIBRETRO_COMM_DIR)/streams/memory_stream.c \
|
||||
$(LIBRETRO_COMM_DIR)/string/stdstring.c \
|
||||
$(LIBRETRO_COMM_DIR)/time/rtime.c \
|
||||
$(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c
|
||||
endif
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
DEBUG=0
|
||||
PSS_STYLE=1
|
||||
EXTERNAL_ZLIB=0
|
||||
HAVE_GRIFFIN=1
|
||||
STATIC_LINKING=0
|
||||
ENDIANNESS_DEFINES=
|
||||
SIGNED_CHAR=0
|
||||
@@ -25,10 +23,6 @@ ifeq ($(platform),)
|
||||
platform = win
|
||||
else ifneq ($(findstring Darwin,$(shell uname -s)),)
|
||||
platform = osx
|
||||
arch = intel
|
||||
ifeq ($(shell uname -p),powerpc)
|
||||
arch = ppc
|
||||
endif
|
||||
else ifneq ($(findstring win,$(shell uname -s)),)
|
||||
platform = win
|
||||
endif
|
||||
@@ -41,10 +35,15 @@ ifeq ($(shell uname -a),)
|
||||
system_platform = win
|
||||
else ifneq ($(findstring Darwin,$(shell uname -a)),)
|
||||
system_platform = osx
|
||||
arch = intel
|
||||
ifeq ($(shell uname -p),powerpc)
|
||||
arch = ppc
|
||||
ifeq ($(shell uname -p),powerpc)
|
||||
arch = ppc
|
||||
else
|
||||
ifeq ($(shell uname -p),arm)
|
||||
arch = arm64
|
||||
else
|
||||
arch = intel
|
||||
endif
|
||||
endif
|
||||
else ifneq ($(findstring MINGW,$(shell uname -a)),)
|
||||
system_platform = win
|
||||
endif
|
||||
@@ -84,11 +83,19 @@ else ifeq ($(platform), osx)
|
||||
fpic := -fPIC
|
||||
SHARED := -dynamiclib
|
||||
ifeq ($(arch),ppc)
|
||||
ENDIANNESS_DEFINES += -DMSB_FIRST
|
||||
ENDIANNESS_DEFINES += -DMSB_FIRST -DHAVE_NO_LANGEXTRA
|
||||
endif
|
||||
ifeq ($(CROSS_COMPILE),1)
|
||||
TARGET_RULE = -target $(LIBRETRO_APPLE_PLATFORM) -isysroot $(LIBRETRO_APPLE_ISYSROOT)
|
||||
CFLAGS += $(TARGET_RULE)
|
||||
LDFLAGS += $(TARGET_RULE)
|
||||
endif
|
||||
|
||||
OSXVER = `sw_vers -productVersion | cut -d. -f 2`
|
||||
OSX_LT_MAVERICKS = `(( $(OSXVER) <= 9)) && echo "YES"`
|
||||
fpic += -mmacosx-version-min=10.1
|
||||
ifeq ($(OSX_LT_MAVERICKS),YES)
|
||||
fpic += -mmacosx-version-min=10.1
|
||||
endif
|
||||
ifndef ($(NOUNIVERSAL))
|
||||
CFLAGS += $(ARCHFLAGS)
|
||||
LDFLAGS += $(ARCHFLAGS)
|
||||
@@ -147,42 +154,19 @@ else ifeq ($(platform), qnx)
|
||||
AR = qcc -Vgcc_ntoarmv7le
|
||||
PLATFORM_DEFINES := -D__BLACKBERRY_QNX__ -marm -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp
|
||||
|
||||
# PS3
|
||||
else ifeq ($(platform), ps3)
|
||||
TARGET := $(TARGET_NAME)_libretro_$(platform).a
|
||||
CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe
|
||||
AR = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ar.exe
|
||||
PLATFORM_DEFINES := -D__CELLOS_LV2
|
||||
ENDIANNESS_DEFINES += -DMSB_FIRST
|
||||
STATIC_LINKING=1
|
||||
EXTERNAL_ZLIB=1
|
||||
|
||||
# sncps3
|
||||
else ifeq ($(platform), sncps3)
|
||||
TARGET := $(TARGET_NAME)_libretro_ps3.a
|
||||
CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe
|
||||
AR = $(CELL_SDK)/host-win32/sn/bin/ps3snarl.exe
|
||||
PLATFORM_DEFINES := -D__CELLOS_LV2
|
||||
ENDIANNESS_DEFINES += -DMSB_FIRST
|
||||
STATIC_LINKING=1
|
||||
EXTERNAL_ZLIB=1
|
||||
|
||||
# PS2
|
||||
else ifeq ($(platform), ps2)
|
||||
TARGET := $(TARGET_NAME)_libretro_$(platform).a
|
||||
CC = ee-gcc$(EXE_EXT)
|
||||
AR = ee-ar$(EXE_EXT)
|
||||
FCEU_DEFINES := -DPATH_MAX=1024 -DINLINE=inline -DPSS_STYLE=1 -DFCEU_VERSION_NUMERIC=9813 -DHAVE_ASPRINTF
|
||||
CC = mips64r5900el-ps2-elf-gcc$(EXE_EXT)
|
||||
AR = mips64r5900el-ps2-elf-ar$(EXE_EXT)
|
||||
FCEU_DEFINES := -DPATH_MAX=1024 -DINLINE=inline -DFCEU_VERSION_NUMERIC=9813 -DHAVE_ASPRINTF
|
||||
ENDIANNESS_DEFINES := -DLSB_FIRST -DLOCAL_LE=1
|
||||
PLATFORM_DEFINES := -DPS2 -G0 -DFRONTEND_SUPPORTS_ABGR1555 -DRENDER_GSKIT_PS2
|
||||
PLATFORM_DEFINES += -Dmemcpy=mips_memcpy -Dmemset=mips_memset
|
||||
PLATFORM_DEFINES += -I$(PS2SDK)/ee/include -I$(PS2SDK)/common/include -Ips2/ -I$(PS2DEV)/gsKit/include
|
||||
PLATFORM_DEFINES := -DPS2 -D_EE -G0 -DFRONTEND_SUPPORTS_ABGR1555 -DRENDER_GSKIT_PS2
|
||||
PLATFORM_DEFINES += -I$(PS2SDK)/ee/include -I$(PS2SDK)/common/include -I$(PS2DEV)/gsKit/include
|
||||
STATIC_LINKING=1
|
||||
EXTERNAL_ZLIB=1
|
||||
|
||||
RETROARCH_OBJECTS += ps2/SMS_Utils.o
|
||||
HAVE_NTSC = 0
|
||||
|
||||
# PSP
|
||||
else ifeq ($(platform), psp1)
|
||||
TARGET := $(TARGET_NAME)_libretro_$(platform).a
|
||||
@@ -244,16 +228,47 @@ else ifeq ($(platform), rpi2)
|
||||
CFLAGS += -DARM
|
||||
CFLAGS += -marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard -funsafe-math-optimizations
|
||||
CFLAGS += -fomit-frame-pointer -fstrict-aliasing -ffast-math
|
||||
|
||||
# Raspberry Pi 3
|
||||
else ifeq ($(platform), rpi3)
|
||||
TARGET := $(TARGET_NAME)_libretro.so
|
||||
fpic := -fPIC
|
||||
SHARED := -shared -Wl,--version-script=src/drivers/libretro/link.T -Wl,-no-undefined
|
||||
CFLAGS += -DARM
|
||||
CFLAGS += -marm -mcpu=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard -funsafe-math-optimizations
|
||||
CFLAGS += -fomit-frame-pointer -fstrict-aliasing -ffast-math
|
||||
|
||||
# Raspberry Pi 3 (64 bit)
|
||||
else ifeq ($(platform), rpi3_64)
|
||||
TARGET := $(TARGET_NAME)_libretro.so
|
||||
fpic := -fPIC
|
||||
SHARED := -shared -Wl,--version-script=src/drivers/libretro/link.T -Wl,-no-undefined
|
||||
CFLAGS += -mcpu=cortex-a53 -mtune=cortex-a53 -funsafe-math-optimizations
|
||||
CFLAGS += -fomit-frame-pointer -fstrict-aliasing -ffast-math
|
||||
|
||||
# Raspberry Pi 4 (64-bit)
|
||||
else ifneq (,$(findstring rpi4,$(platform)))
|
||||
TARGET := $(TARGET_NAME)_libretro.so
|
||||
fpic := -fPIC
|
||||
SHARED := -shared -Wl,--version-script=src/drivers/libretro/link.T -Wl,-no-undefined
|
||||
CFLAGS += -mcpu=cortex-a72 -mtune=cortex-a72 -funsafe-math-optimizations
|
||||
CFLAGS += -fomit-frame-pointer -fstrict-aliasing -ffast-math
|
||||
|
||||
# Lightweight PS3 Homebrew SDK
|
||||
else ifeq ($(platform), psl1ght)
|
||||
TARGET := $(TARGET_NAME)_libretro_$(platform).a
|
||||
CC = $(PS3DEV)/ppu/bin/ppu-gcc$(EXE_EXT)
|
||||
AR = $(PS3DEV)/ppu/bin/ppu-ar$(EXE_EXT)
|
||||
PLATFORM_DEFINES := -D__CELLOS_LV2
|
||||
ENDIANNESS_DEFINES += -DMSB_FIRST
|
||||
STATIC_LINKING=1
|
||||
EXTERNAL_ZLIB=1
|
||||
else ifneq (,$(filter $(platform), ps3 psl1ght))
|
||||
ENDIANNESS_DEFINES = -DMSB_FIRST
|
||||
EXTERNAL_ZLIB = 1
|
||||
STATIC_LINKING = 1
|
||||
PLATFORM_DEFINES += -D__PS3__
|
||||
|
||||
ifeq ($(platform), psl1ght)
|
||||
PLATFORM_DEFINES += -D__PSL1GHT__
|
||||
endif
|
||||
|
||||
TARGET := $(TARGET_NAME)_libretro_$(platform).a
|
||||
CC = $(PS3DEV)/ppu/bin/ppu-$(COMMONLV)gcc$(EXE_EXT)
|
||||
CXX = $(PS3DEV)/ppu/bin/ppu-$(COMMONLV)g++$(EXE_EXT)
|
||||
AR = $(PS3DEV)/ppu/bin/ppu-$(COMMONLV)ar$(EXE_EXT)
|
||||
|
||||
# Xbox 360
|
||||
else ifeq ($(platform), xenon)
|
||||
@@ -380,8 +395,8 @@ else ifeq ($(platform), classic_armv8_a35)
|
||||
ARCH = arm
|
||||
BUILTIN_GPU = neon
|
||||
USE_DYNAREC = 1
|
||||
CFLAGS += -march=armv8-a
|
||||
LDFLAGS += -static-libgcc -static-libstdc++
|
||||
LDFLAGS += -lrt
|
||||
LDFLAGS += -marm -mcpu=cortex-a35 -mfpu=neon-fp-armv8 -mfloat-abi=hard -Ofast -flto -fuse-linker-plugin
|
||||
#######################################
|
||||
|
||||
# ARM
|
||||
@@ -424,6 +439,28 @@ else ifeq ($(platform), gcw0)
|
||||
PLATFORM_DEFINES += -ffast-math -march=mips32 -mtune=mips32r2 -mhard-float -fomit-frame-pointer
|
||||
EXTERNAL_ZLIB = 1
|
||||
|
||||
# RETROFW
|
||||
else ifeq ($(platform), retrofw)
|
||||
TARGET := $(TARGET_NAME)_libretro.so
|
||||
CC = /opt/retrofw-toolchain/usr/bin/mipsel-linux-gcc
|
||||
CXX = /opt/retrofw-toolchain/usr/bin/mipsel-linux-g++
|
||||
AR = /opt/retrofw-toolchain/usr/bin/mipsel-linux-ar
|
||||
fpic := -fPIC
|
||||
SHARED := -shared -Wl,--version-script=src/drivers/libretro/link.T -Wl,-no-undefined
|
||||
PLATFORM_DEFINES += -ffast-math -march=mips32 -mtune=mips32 -mhard-float -fomit-frame-pointer
|
||||
EXTERNAL_ZLIB = 1
|
||||
|
||||
# Miyoo
|
||||
else ifeq ($(platform), miyoo)
|
||||
TARGET := $(TARGET_NAME)_libretro.so
|
||||
CC = /opt/miyoo/usr/bin/arm-linux-gcc
|
||||
CXX = /opt/miyoo/usr/bin/arm-linux-g++
|
||||
AR = /opt/miyoo/usr/bin/arm-linux-ar
|
||||
fpic := -fPIC
|
||||
SHARED := -shared -Wl,--version-script=src/drivers/libretro/link.T -Wl,-no-undefined
|
||||
PLATFORM_DEFINES += -fomit-frame-pointer -ffast-math -mcpu=arm926ej-s
|
||||
EXTERNAL_ZLIB = 1
|
||||
|
||||
# Windows MSVC 2017 all architectures
|
||||
else ifneq (,$(findstring windows_msvc2017,$(platform)))
|
||||
CC = cl.exe
|
||||
@@ -511,7 +548,6 @@ else ifneq (,$(findstring windows_msvc2017,$(platform)))
|
||||
export INCLUDE := $(INCLUDE);$(WindowsSDKSharedIncludeDir);$(WindowsSDKUCRTIncludeDir);$(WindowsSDKUMIncludeDir)
|
||||
export LIB := $(LIB);$(WindowsSDKUCRTLibDir);$(WindowsSDKUMLibDir)
|
||||
TARGET := $(TARGET_NAME)_libretro.dll
|
||||
PSS_STYLE :=2
|
||||
LDFLAGS += -DLL
|
||||
|
||||
# Windows MSVC 2010 x64
|
||||
@@ -521,20 +557,20 @@ else ifeq ($(platform), windows_msvc2010_x64)
|
||||
|
||||
PATH := $(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../../VC/bin/amd64"):$(PATH)
|
||||
PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../IDE")
|
||||
INCLUDE := $(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../../VC/include")
|
||||
LIB := $(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../../VC/lib/amd64")
|
||||
BIN := $(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../../VC/bin")
|
||||
INCLUDE := $(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../../VC/include")
|
||||
|
||||
WindowsSdkDir := $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')lib/x64
|
||||
WindowsSdkDir ?= $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')lib/x64
|
||||
WindowsSdkDirInc := $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')Include
|
||||
WindowsSdkDirInc ?= $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')Include
|
||||
WindowsSdkDir := $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')
|
||||
WindowsSdkDir ?= $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')
|
||||
|
||||
INCFLAGS_PLATFORM = -I"$(WindowsSdkDirInc)"
|
||||
export INCLUDE := $(INCLUDE)
|
||||
export LIB := $(LIB);$(WindowsSdkDir)
|
||||
WindowsSDKIncludeDir := $(shell cygpath -w "$(WindowsSdkDir)\Include")
|
||||
WindowsSDKGlIncludeDir := $(shell cygpath -w "$(WindowsSdkDir)\Include\gl")
|
||||
WindowsSDKLibDir := $(shell cygpath -w "$(WindowsSdkDir)\Lib\x64")
|
||||
|
||||
INCFLAGS_PLATFORM = -I"$(WindowsSDKIncludeDir)"
|
||||
export INCLUDE := $(INCLUDE);$(WindowsSDKIncludeDir);$(WindowsSDKGlIncludeDir)
|
||||
export LIB := $(LIB);$(WindowsSDKLibDir)
|
||||
TARGET := $(TARGET_NAME)_libretro.dll
|
||||
PSS_STYLE :=2
|
||||
LDFLAGS += -DLL
|
||||
|
||||
# Windows MSVC 2010 x86
|
||||
@@ -544,20 +580,20 @@ else ifeq ($(platform), windows_msvc2010_x86)
|
||||
|
||||
PATH := $(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../../VC/bin"):$(PATH)
|
||||
PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../IDE")
|
||||
INCLUDE := $(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../../VC/include")
|
||||
LIB := $(shell IFS=$$'\n'; cygpath -w "$(VS100COMNTOOLS)../../VC/lib")
|
||||
BIN := $(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../../VC/bin")
|
||||
INCLUDE := $(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../../VC/include")
|
||||
|
||||
WindowsSdkDir := $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')lib
|
||||
WindowsSdkDir ?= $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')lib
|
||||
WindowsSdkDirInc := $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')Include
|
||||
WindowsSdkDirInc ?= $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')Include
|
||||
WindowsSdkDir := $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')
|
||||
WindowsSdkDir ?= $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')
|
||||
|
||||
INCFLAGS_PLATFORM = -I"$(WindowsSdkDirInc)"
|
||||
export INCLUDE := $(INCLUDE)
|
||||
export LIB := $(LIB);$(WindowsSdkDir)
|
||||
WindowsSDKIncludeDir := $(shell cygpath -w "$(WindowsSdkDir)\Include")
|
||||
WindowsSDKGlIncludeDir := $(shell cygpath -w "$(WindowsSdkDir)\Include\gl")
|
||||
WindowsSDKLibDir := $(shell cygpath -w "$(WindowsSdkDir)\Lib")
|
||||
|
||||
INCFLAGS_PLATFORM = -I"$(WindowsSDKIncludeDir)"
|
||||
export INCLUDE := $(INCLUDE);$(WindowsSDKIncludeDir);$(WindowsSDKGlIncludeDir)
|
||||
export LIB := $(LIB);$(WindowsSDKLibDir)
|
||||
TARGET := $(TARGET_NAME)_libretro.dll
|
||||
PSS_STYLE :=2
|
||||
LDFLAGS += -DLL
|
||||
|
||||
# Windows MSVC 2003 Xbox 1
|
||||
@@ -571,7 +607,6 @@ export INCLUDE := $(XDK)\xbox\include
|
||||
export LIB := $(XDK)\xbox\lib
|
||||
PATH := $(call unixcygpath,$(XDK)/xbox/bin/vc71):$(PATH)
|
||||
|
||||
PSS_STYLE :=2
|
||||
CFLAGS += -D_XBOX -D_XBOX1
|
||||
CXXFLAGS += -D_XBOX -D_XBOX1
|
||||
STATIC_LINKING=1
|
||||
@@ -587,7 +622,6 @@ export INCLUDE := $(XEDK)/include/xbox
|
||||
export LIB := $(XEDK)/lib/xbox
|
||||
PATH := $(call unixcygpath,$(XEDK)/bin/win32):$(PATH)
|
||||
|
||||
PSS_STYLE :=2
|
||||
CFLAGS += -D_XBOX -D_XBOX360
|
||||
CXXFLAGS += -D_XBOX -D_XBOX360
|
||||
ENDIANNESS_DEFINES += -DMSB_FIRST
|
||||
@@ -609,7 +643,6 @@ WindowsSdkDir := $(INETSDK)
|
||||
export INCLUDE := $(INCLUDE);$(INETSDK)/Include
|
||||
export LIB := $(LIB);$(WindowsSdkDir);$(INETSDK)/Lib
|
||||
TARGET := $(TARGET_NAME)_libretro.dll
|
||||
PSS_STYLE :=2
|
||||
LDFLAGS += -DLL
|
||||
CFLAGS += -D_CRT_SECURE_NO_DEPRECATE
|
||||
|
||||
@@ -624,12 +657,18 @@ INCLUDE := $(shell IFS=$$'\n'; cygpath "$(VS80COMNTOOLS)../../VC/include")
|
||||
LIB := $(shell IFS=$$'\n'; cygpath -w "$(VS80COMNTOOLS)../../VC/lib")
|
||||
BIN := $(shell IFS=$$'\n'; cygpath "$(VS80COMNTOOLS)../../VC/bin")
|
||||
|
||||
WindowsSdkDir := $(INETSDK)
|
||||
WindowsSdkDir := $(shell reg query "HKLM\SOFTWARE\Microsoft\MicrosoftSDK\InstalledSDKs\8F9E5EF3-A9A5-491B-A889-C58EFFECE8B3" -v "Install Dir" | grep -o '[A-Z]:\\.*')
|
||||
|
||||
export INCLUDE := $(INCLUDE);$(INETSDK)/Include
|
||||
export LIB := $(LIB);$(WindowsSdkDir);$(INETSDK)/Lib
|
||||
WindowsSDKIncludeDir := $(shell cygpath -w "$(WindowsSdkDir)\Include")
|
||||
WindowsSDKAtlIncludeDir := $(shell cygpath -w "$(WindowsSdkDir)\Include\atl")
|
||||
WindowsSDKCrtIncludeDir := $(shell cygpath -w "$(WindowsSdkDir)\Include\crt")
|
||||
WindowsSDKGlIncludeDir := $(shell cygpath -w "$(WindowsSdkDir)\Include\gl")
|
||||
WindowsSDKMfcIncludeDir := $(shell cygpath -w "$(WindowsSdkDir)\Include\mfc")
|
||||
WindowsSDKLibDir := $(shell cygpath -w "$(WindowsSdkDir)\Lib")
|
||||
|
||||
export INCLUDE := $(INCLUDE);$(WindowsSDKIncludeDir);$(WindowsSDKAtlIncludeDir);$(WindowsSDKCrtIncludeDir);$(WindowsSDKGlIncludeDir);$(WindowsSDKMfcIncludeDir);libretro-common/include/compat/msvc
|
||||
export LIB := $(LIB);$(WindowsSDKLibDir)
|
||||
TARGET := $(TARGET_NAME)_libretro.dll
|
||||
PSS_STYLE :=2
|
||||
LDFLAGS += -DLL
|
||||
CFLAGS += -D_CRT_SECURE_NO_DEPRECATE
|
||||
|
||||
@@ -649,7 +688,6 @@ WindowsSdkDir := $(INETSDK)
|
||||
export INCLUDE := $(INCLUDE);$(INETSDK)/Include
|
||||
export LIB := $(LIB);$(WindowsSdkDir);$(INETSDK)/Lib
|
||||
TARGET := $(TARGET_NAME)_libretro.dll
|
||||
PSS_STYLE :=2
|
||||
LDFLAGS += -DLL
|
||||
CFLAGS += -D_CRT_SECURE_NO_DEPRECATE
|
||||
|
||||
@@ -658,41 +696,27 @@ else
|
||||
TARGET := $(TARGET_NAME)_libretro.dll
|
||||
CC ?= gcc
|
||||
SHARED := -shared -static-libgcc -static-libstdc++ -s -Wl,--version-script=src/drivers/libretro/link.T
|
||||
PSS_STYLE :=2
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
ifneq (,$(findstring msvc,$(platform)))
|
||||
ifeq ($(STATIC_LINKING),1)
|
||||
CFLAGS += -MTd
|
||||
CXXFLAGS += -MTd
|
||||
else
|
||||
CFLAGS += -MDd
|
||||
CXXFLAGS += -MDd
|
||||
endif
|
||||
|
||||
CFLAGS += -Od -Zi -DDEBUG -D_DEBUG
|
||||
CXXFLAGS += -Od -Zi -DDEBUG -D_DEBUG
|
||||
CFLAGS += -MTd
|
||||
CXXFLAGS += -MTd
|
||||
CFLAGS += -Od -Zi -D_DEBUG
|
||||
CXXFLAGS += -Od -Zi -D_DEBUG
|
||||
else
|
||||
CFLAGS += -O0 -g -DDEBUG
|
||||
CXXFLAGS += -O0 -g -DDEBUG
|
||||
CFLAGS += -O0 -g
|
||||
CXXFLAGS += -O0 -g
|
||||
endif
|
||||
CFLAGS += -DDEBUG
|
||||
CXXFLAGS += -DDEBUG
|
||||
else
|
||||
ifneq (,$(findstring msvc,$(platform)))
|
||||
ifeq ($(STATIC_LINKING),1)
|
||||
CFLAGS += -MT
|
||||
CXXFLAGS += -MT
|
||||
else
|
||||
CFLAGS += -MD
|
||||
CXXFLAGS += -MD
|
||||
endif
|
||||
|
||||
CFLAGS += -O2 -DNDEBUG
|
||||
CXXFLAGS += -O2 -DNDEBUG
|
||||
else
|
||||
CFLAGS += -O2 -DNDEBUG
|
||||
CXXFLAGS += -O2 -DNDEBUG
|
||||
CFLAGS += -MT
|
||||
CXXFLAGS += -MT
|
||||
endif
|
||||
CFLAGS += -O2 -DNDEBUG
|
||||
CXXFLAGS += -O2 -DNDEBUG
|
||||
endif
|
||||
|
||||
ifneq ($(SANITIZER),)
|
||||
@@ -726,8 +750,6 @@ ifneq (,$(findstring msvc,$(platform)))
|
||||
COREDEFINES += -DINLINE=_inline
|
||||
endif
|
||||
|
||||
CFLAGS += -DWANT_GRIFFIN -Werror=implicit-function-declaration
|
||||
|
||||
OBJECTS := $(SOURCES_C:.c=.o)
|
||||
OBJECTS += $(RETROARCH_OBJECTS)
|
||||
|
||||
@@ -796,11 +818,6 @@ endif
|
||||
%.o: %.c
|
||||
$(CC) -c $(OBJOUT)$@ $< $(CFLAGS) $(INCFLAGS)
|
||||
|
||||
ifeq ($(platform), ps2)
|
||||
%.o: %.s
|
||||
ee-as -G0 $< -o $@
|
||||
endif
|
||||
|
||||
clean-objs:
|
||||
rm -f $(OBJECTS)
|
||||
|
||||
|
||||
@@ -4,3 +4,5 @@
|
||||
# FCE Ultra mappers modified
|
||||
FCEU "mappers modified" is an unofficial build of FCEU Ultra by CaH4e3, which supports a lot of new mappers including some obscure mappers such as one for unlicensed NES ROM's.
|
||||
|
||||
# Sequential targets Light Guns support added
|
||||
Support for Sequential targets Light Guns has been added. "Gun Aux A" serves as light sensor logic input.
|
||||
4
intl/.gitignore
vendored
Normal file
4
intl/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
__pycache__
|
||||
crowdin-cli.jar
|
||||
*.h
|
||||
*.json
|
||||
70
intl/activate.py
Executable file
70
intl/activate.py
Executable file
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import glob
|
||||
import random as r
|
||||
|
||||
# -------------------- MAIN -------------------- #
|
||||
|
||||
if __name__ == '__main__':
|
||||
DIR_PATH = os.path.dirname(os.path.realpath(__file__))
|
||||
if os.path.basename(DIR_PATH) != "intl":
|
||||
raise RuntimeError("Script is not in intl folder!")
|
||||
|
||||
BASE_PATH = os.path.dirname(DIR_PATH)
|
||||
WORKFLOW_PATH = os.path.join(BASE_PATH, ".github", "workflows")
|
||||
PREP_WF = os.path.join(WORKFLOW_PATH, "crowdin_prep.yml")
|
||||
TRANSLATE_WF = os.path.join(WORKFLOW_PATH, "crowdin_translate.yml")
|
||||
CORE_NAME = os.path.basename(BASE_PATH)
|
||||
CORE_OP_FILE = os.path.join(BASE_PATH, "**", "libretro_core_options.h")
|
||||
|
||||
core_options_hits = glob.glob(CORE_OP_FILE, recursive=True)
|
||||
|
||||
if len(core_options_hits) == 0:
|
||||
raise RuntimeError("libretro_core_options.h not found!")
|
||||
elif len(core_options_hits) > 1:
|
||||
print("More than one libretro_core_options.h file found:\n\n")
|
||||
for i, file in enumerate(core_options_hits):
|
||||
print(f"{i} {file}\n")
|
||||
|
||||
while True:
|
||||
user_choice = input("Please choose one ('q' will exit): ")
|
||||
if user_choice == 'q':
|
||||
exit(0)
|
||||
elif user_choice.isdigit():
|
||||
core_op_file = core_options_hits[int(user_choice)]
|
||||
break
|
||||
else:
|
||||
print("Please make a valid choice!\n\n")
|
||||
else:
|
||||
core_op_file = core_options_hits[0]
|
||||
|
||||
core_intl_file = os.path.join(os.path.dirname(core_op_file.replace(BASE_PATH, ''))[1:],
|
||||
'libretro_core_options_intl.h')
|
||||
core_op_file = os.path.join(os.path.dirname(core_op_file.replace(BASE_PATH, ''))[1:],
|
||||
'libretro_core_options.h')
|
||||
minutes = r.randrange(0, 59, 5)
|
||||
hour = r.randrange(0, 23)
|
||||
|
||||
with open(PREP_WF, 'r') as wf_file:
|
||||
prep_txt = wf_file.read()
|
||||
|
||||
prep_txt = prep_txt.replace("<CORE_NAME>", CORE_NAME)
|
||||
prep_txt = prep_txt.replace("<PATH/TO>/libretro_core_options.h",
|
||||
core_op_file)
|
||||
with open(PREP_WF, 'w') as wf_file:
|
||||
wf_file.write(prep_txt)
|
||||
|
||||
|
||||
with open(TRANSLATE_WF, 'r') as wf_file:
|
||||
translate_txt = wf_file.read()
|
||||
|
||||
translate_txt = translate_txt.replace('<0-59>', f"{minutes}")
|
||||
translate_txt = translate_txt.replace('<0-23>', f"{hour}")
|
||||
translate_txt = translate_txt.replace('# Fridays at , UTC',
|
||||
f"# Fridays at {hour%12}:{minutes} {'AM' if hour < 12 else 'PM'}, UTC")
|
||||
translate_txt = translate_txt.replace("<CORE_NAME>", CORE_NAME)
|
||||
translate_txt = translate_txt.replace('<PATH/TO>/libretro_core_options_intl.h',
|
||||
core_intl_file)
|
||||
with open(TRANSLATE_WF, 'w') as wf_file:
|
||||
wf_file.write(translate_txt)
|
||||
95
intl/core_option_regex.py
Normal file
95
intl/core_option_regex.py
Normal file
@@ -0,0 +1,95 @@
|
||||
import re
|
||||
|
||||
# 0: full struct; 1: up to & including first []; 2: content between first {}
|
||||
p_struct = re.compile(r'(struct\s*[a-zA-Z0-9_\s]+\[])\s*'
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+)\s*)*'
|
||||
r'=\s*' # =
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+)\s*)*'
|
||||
r'{((?:.|[\r\n])*?)\{\s*NULL,\s*NULL,\s*NULL\s*(?:.|[\r\n])*?},?(?:.|[\r\n])*?};') # captures full struct, it's beginning and it's content
|
||||
# 0: type name[]; 1: type; 2: name
|
||||
p_type_name = re.compile(r'(retro_core_option_[a-zA-Z0-9_]+)\s*'
|
||||
r'(option_cats([a-z_]{0,8})|option_defs([a-z_]{0,8}))\s*\[]')
|
||||
# 0: full option; 1: key; 2: description; 3: additional info; 4: key/value pairs
|
||||
p_option = re.compile(r'{\s*' # opening braces
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r'(\".*?\"|' # key start; group 1
|
||||
r'[a-zA-Z0-9_]+\s*\((?:.|[\r\n])*?\)|'
|
||||
r'[a-zA-Z0-9_]+\s*\[(?:.|[\r\n])*?]|'
|
||||
r'[a-zA-Z0-9_]+\s*\".*?\")\s*' # key end
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r',\s*' # comma
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r'(\".*?\")\s*' # description; group 2
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r',\s*' # comma
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r'((?:' # group 3
|
||||
r'(?:NULL|\"(?:.|[\r\n])*?\")\s*' # description in category, info, info in category, category
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r',?\s*' # comma
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r')+)'
|
||||
r'(?:' # defs only start
|
||||
r'{\s*' # opening braces
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r'((?:' # key/value pairs start; group 4
|
||||
r'{\s*' # opening braces
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r'(?:NULL|\".*?\")\s*' # option key
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r',\s*' # comma
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r'(?:NULL|\".*?\")\s*' # option value
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r'}\s*' # closing braces
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r',?\s*' # comma
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r')*)' # key/value pairs end
|
||||
r'}\s*' # closing braces
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r',?\s*' # comma
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r'(?:' # defaults start
|
||||
r'(?:NULL|\".*?\")\s*' # default value
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r',?\s*' # comma
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r')*' # defaults end
|
||||
r')?' # defs only end
|
||||
r'},') # closing braces
|
||||
# analyse option group 3
|
||||
p_info = re.compile(r'(NULL|\"(?:.|[\r\n])*?\")\s*' # description in category, info, info in category, category
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r',')
|
||||
p_info_cat = re.compile(r'(NULL|\"(?:.|[\r\n])*?\")')
|
||||
# analyse option group 4
|
||||
p_key_value = re.compile(r'{\s*' # opening braces
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r'(NULL|\".*?\")\s*' # option key; 1
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r',\s*' # comma
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r'(NULL|\".*?\")\s*' # option value; 2
|
||||
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
||||
r'}')
|
||||
|
||||
p_masked = re.compile(r'([A-Z_][A-Z0-9_]+)\s*(\"(?:"\s*"|\\\s*|.)*\")')
|
||||
|
||||
p_intl = re.compile(r'(struct retro_core_option_definition \*option_defs_intl\[RETRO_LANGUAGE_LAST]) = {'
|
||||
r'((?:.|[\r\n])*?)};')
|
||||
p_set = re.compile(r'static INLINE void libretro_set_core_options\(retro_environment_t environ_cb\)'
|
||||
r'(?:.|[\r\n])*?};?\s*#ifdef __cplusplus\s*}\s*#endif')
|
||||
|
||||
p_yaml = re.compile(r'"project_id": "[0-9]+".*\s*'
|
||||
r'"api_token": "([a-zA-Z0-9]+)".*\s*'
|
||||
r'"base_path": "\./intl".*\s*'
|
||||
r'"base_url": "https://api\.crowdin\.com".*\s*'
|
||||
r'"preserve_hierarchy": true.*\s*'
|
||||
r'"files": \[\s*'
|
||||
r'\{\s*'
|
||||
r'"source": "/_us/\*\.json",.*\s*'
|
||||
r'"translation": "/_%two_letters_code%/%original_file_name%",.*\s*'
|
||||
r'"skip_untranslated_strings": true.*\s*'
|
||||
r'},\s*'
|
||||
r']')
|
||||
620
intl/core_option_translation.py
Executable file
620
intl/core_option_translation.py
Executable file
@@ -0,0 +1,620 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""Core options text extractor
|
||||
|
||||
The purpose of this script is to set up & provide functions for automatic generation of 'libretro_core_options_intl.h'
|
||||
from 'libretro_core_options.h' using translations from Crowdin.
|
||||
|
||||
Both v1 and v2 structs are supported. It is, however, recommended to convert v1 files to v2 using the included
|
||||
'v1_to_v2_converter.py'.
|
||||
|
||||
Usage:
|
||||
python3 path/to/core_option_translation.py "path/to/where/libretro_core_options.h & libretro_core_options_intl.h/are" "core_name"
|
||||
|
||||
This script will:
|
||||
1.) create key words for & extract the texts from libretro_core_options.h & save them into intl/_us/core_options.h
|
||||
2.) do the same for any present translations in libretro_core_options_intl.h, saving those in their respective folder
|
||||
"""
|
||||
import core_option_regex as cor
|
||||
import re
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import urllib.request as req
|
||||
import shutil
|
||||
|
||||
# LANG_CODE_TO_R_LANG = {'_ar': 'RETRO_LANGUAGE_ARABIC',
|
||||
# '_ast': 'RETRO_LANGUAGE_ASTURIAN',
|
||||
# '_chs': 'RETRO_LANGUAGE_CHINESE_SIMPLIFIED',
|
||||
# '_cht': 'RETRO_LANGUAGE_CHINESE_TRADITIONAL',
|
||||
# '_cs': 'RETRO_LANGUAGE_CZECH',
|
||||
# '_cy': 'RETRO_LANGUAGE_WELSH',
|
||||
# '_da': 'RETRO_LANGUAGE_DANISH',
|
||||
# '_de': 'RETRO_LANGUAGE_GERMAN',
|
||||
# '_el': 'RETRO_LANGUAGE_GREEK',
|
||||
# '_eo': 'RETRO_LANGUAGE_ESPERANTO',
|
||||
# '_es': 'RETRO_LANGUAGE_SPANISH',
|
||||
# '_fa': 'RETRO_LANGUAGE_PERSIAN',
|
||||
# '_fi': 'RETRO_LANGUAGE_FINNISH',
|
||||
# '_fr': 'RETRO_LANGUAGE_FRENCH',
|
||||
# '_gl': 'RETRO_LANGUAGE_GALICIAN',
|
||||
# '_he': 'RETRO_LANGUAGE_HEBREW',
|
||||
# '_hu': 'RETRO_LANGUAGE_HUNGARIAN',
|
||||
# '_id': 'RETRO_LANGUAGE_INDONESIAN',
|
||||
# '_it': 'RETRO_LANGUAGE_ITALIAN',
|
||||
# '_ja': 'RETRO_LANGUAGE_JAPANESE',
|
||||
# '_ko': 'RETRO_LANGUAGE_KOREAN',
|
||||
# '_nl': 'RETRO_LANGUAGE_DUTCH',
|
||||
# '_oc': 'RETRO_LANGUAGE_OCCITAN',
|
||||
# '_pl': 'RETRO_LANGUAGE_POLISH',
|
||||
# '_pt_br': 'RETRO_LANGUAGE_PORTUGUESE_BRAZIL',
|
||||
# '_pt_pt': 'RETRO_LANGUAGE_PORTUGUESE_PORTUGAL',
|
||||
# '_ru': 'RETRO_LANGUAGE_RUSSIAN',
|
||||
# '_sk': 'RETRO_LANGUAGE_SLOVAK',
|
||||
# '_sv': 'RETRO_LANGUAGE_SWEDISH',
|
||||
# '_tr': 'RETRO_LANGUAGE_TURKISH',
|
||||
# '_uk': 'RETRO_LANGUAGE_UKRAINIAN',
|
||||
# '_us': 'RETRO_LANGUAGE_ENGLISH',
|
||||
# '_vn': 'RETRO_LANGUAGE_VIETNAMESE'}
|
||||
|
||||
# these are handled by RetroArch directly - no need to include them in core translations
|
||||
ON_OFFS = {'"enabled"', '"disabled"', '"true"', '"false"', '"on"', '"off"'}
|
||||
|
||||
|
||||
def remove_special_chars(text: str, char_set=0, allow_non_ascii=False) -> str:
|
||||
"""Removes special characters from a text.
|
||||
|
||||
:param text: String to be cleaned.
|
||||
:param char_set: 0 -> remove all ASCII special chars except for '_' & 'space' (default)
|
||||
1 -> remove invalid chars from file names
|
||||
:param allow_non_ascii: False -> all non-ascii characters will be removed (default)
|
||||
True -> non-ascii characters will be passed through
|
||||
:return: Clean text.
|
||||
"""
|
||||
command_chars = [chr(unicode) for unicode in tuple(range(0, 32)) + (127,)]
|
||||
special_chars = ([chr(unicode) for unicode in tuple(range(33, 48)) + tuple(range(58, 65)) + tuple(range(91, 95))
|
||||
+ (96,) + tuple(range(123, 127))],
|
||||
('\\', '/', ':', '*', '?', '"', '<', '>', '|', '#', '%',
|
||||
'&', '{', '}', '$', '!', '¸', "'", '@', '+', '='))
|
||||
res = text if allow_non_ascii \
|
||||
else text.encode('ascii', errors='ignore').decode('unicode-escape')
|
||||
|
||||
for cm in command_chars:
|
||||
res = res.replace(cm, '_')
|
||||
for sp in special_chars[char_set]:
|
||||
res = res.replace(sp, '_')
|
||||
while res.startswith('_'):
|
||||
res = res[1:]
|
||||
while res.endswith('_'):
|
||||
res = res[:-1]
|
||||
return res
|
||||
|
||||
|
||||
def clean_file_name(file_name: str) -> str:
|
||||
"""Removes characters which might make file_name inappropriate for files on some OS.
|
||||
|
||||
:param file_name: File name to be cleaned.
|
||||
:return: The clean file name.
|
||||
"""
|
||||
file_name = remove_special_chars(file_name, 1)
|
||||
file_name = re.sub(r'__+', '_', file_name.replace(' ', '_'))
|
||||
return file_name
|
||||
|
||||
|
||||
def get_struct_type_name(decl: str) -> tuple:
|
||||
""" Returns relevant parts of the struct declaration:
|
||||
type, name of the struct and the language appendix, if present.
|
||||
:param decl: The struct declaration matched by cor.p_type_name.
|
||||
:return: Tuple, e.g.: ('retro_core_option_definition', 'option_defs_us', '_us')
|
||||
"""
|
||||
struct_match = cor.p_type_name.search(decl)
|
||||
if struct_match:
|
||||
if struct_match.group(3):
|
||||
struct_type_name = struct_match.group(1, 2, 3)
|
||||
return struct_type_name
|
||||
elif struct_match.group(4):
|
||||
struct_type_name = struct_match.group(1, 2, 4)
|
||||
return struct_type_name
|
||||
else:
|
||||
struct_type_name = struct_match.group(1, 2)
|
||||
return struct_type_name
|
||||
else:
|
||||
raise ValueError(f'No or incomplete struct declaration: {decl}!\n'
|
||||
'Please make sure all structs are complete, including the type and name declaration.')
|
||||
|
||||
|
||||
def is_viable_non_dupe(text: str, comparison) -> bool:
|
||||
"""text must be longer than 2 ('""'), not 'NULL' and not in comparison.
|
||||
|
||||
:param text: String to be tested.
|
||||
:param comparison: Dictionary or set to search for text in.
|
||||
:return: bool
|
||||
"""
|
||||
return 2 < len(text) and text != 'NULL' and text not in comparison
|
||||
|
||||
|
||||
def is_viable_value(text: str) -> bool:
|
||||
"""text must be longer than 2 ('""'), not 'NULL' and text.lower() not in
|
||||
{'"enabled"', '"disabled"', '"true"', '"false"', '"on"', '"off"'}.
|
||||
|
||||
:param text: String to be tested.
|
||||
:return: bool
|
||||
"""
|
||||
return 2 < len(text) and text != 'NULL' and text.lower() not in ON_OFFS
|
||||
|
||||
|
||||
def create_non_dupe(base_name: str, opt_num: int, comparison) -> str:
|
||||
"""Makes sure base_name is not in comparison, and if it is it's renamed.
|
||||
|
||||
:param base_name: Name to check/make unique.
|
||||
:param opt_num: Number of the option base_name belongs to, used in making it unique.
|
||||
:param comparison: Dictionary or set to search for base_name in.
|
||||
:return: Unique name.
|
||||
"""
|
||||
h = base_name
|
||||
if h in comparison:
|
||||
n = 0
|
||||
h = h + '_O' + str(opt_num)
|
||||
h_end = len(h)
|
||||
while h in comparison:
|
||||
h = h[:h_end] + '_' + str(n)
|
||||
n += 1
|
||||
return h
|
||||
|
||||
|
||||
def get_texts(text: str) -> dict:
|
||||
"""Extracts the strings, which are to be translated/are the translations,
|
||||
from text and creates macro names for them.
|
||||
|
||||
:param text: The string to be parsed.
|
||||
:return: Dictionary of the form { '_<lang>': { 'macro': 'string', ... }, ... }.
|
||||
"""
|
||||
# all structs: group(0) full struct, group(1) beginning, group(2) content
|
||||
structs = cor.p_struct.finditer(text)
|
||||
hash_n_string = {}
|
||||
just_string = {}
|
||||
for struct in structs:
|
||||
struct_declaration = struct.group(1)
|
||||
struct_type_name = get_struct_type_name(struct_declaration)
|
||||
if 3 > len(struct_type_name):
|
||||
lang = '_us'
|
||||
else:
|
||||
lang = struct_type_name[2]
|
||||
if lang not in just_string:
|
||||
hash_n_string[lang] = {}
|
||||
just_string[lang] = set()
|
||||
|
||||
is_v2 = False
|
||||
pre_name = ''
|
||||
p = cor.p_info
|
||||
if 'retro_core_option_v2_definition' == struct_type_name[0]:
|
||||
is_v2 = True
|
||||
elif 'retro_core_option_v2_category' == struct_type_name[0]:
|
||||
pre_name = 'CATEGORY_'
|
||||
p = cor.p_info_cat
|
||||
|
||||
struct_content = struct.group(2)
|
||||
# 0: full option; 1: key; 2: description; 3: additional info; 4: key/value pairs
|
||||
struct_options = cor.p_option.finditer(struct_content)
|
||||
for opt, option in enumerate(struct_options):
|
||||
# group 1: key
|
||||
if option.group(1):
|
||||
opt_name = pre_name + option.group(1)
|
||||
# no special chars allowed in key
|
||||
opt_name = remove_special_chars(opt_name).upper().replace(' ', '_')
|
||||
else:
|
||||
raise ValueError(f'No option name (key) found in struct {struct_type_name[1]} option {opt}!')
|
||||
|
||||
# group 2: description0
|
||||
if option.group(2):
|
||||
desc0 = option.group(2)
|
||||
if is_viable_non_dupe(desc0, just_string[lang]):
|
||||
just_string[lang].add(desc0)
|
||||
m_h = create_non_dupe(re.sub(r'__+', '_', f'{opt_name}_LABEL'), opt, hash_n_string[lang])
|
||||
hash_n_string[lang][m_h] = desc0
|
||||
else:
|
||||
raise ValueError(f'No label found in struct {struct_type_name[1]} option {option.group(1)}!')
|
||||
|
||||
# group 3: desc1, info0, info1, category
|
||||
if option.group(3):
|
||||
infos = option.group(3)
|
||||
option_info = p.finditer(infos)
|
||||
if is_v2:
|
||||
desc1 = next(option_info).group(1)
|
||||
if is_viable_non_dupe(desc1, just_string[lang]):
|
||||
just_string[lang].add(desc1)
|
||||
m_h = create_non_dupe(re.sub(r'__+', '_', f'{opt_name}_LABEL_CAT'), opt, hash_n_string[lang])
|
||||
hash_n_string[lang][m_h] = desc1
|
||||
last = None
|
||||
m_h = None
|
||||
for j, info in enumerate(option_info):
|
||||
last = info.group(1)
|
||||
if is_viable_non_dupe(last, just_string[lang]):
|
||||
just_string[lang].add(last)
|
||||
m_h = create_non_dupe(re.sub(r'__+', '_', f'{opt_name}_INFO_{j}'), opt,
|
||||
hash_n_string[lang])
|
||||
hash_n_string[lang][m_h] = last
|
||||
if last in just_string[lang]: # category key should not be translated
|
||||
hash_n_string[lang].pop(m_h)
|
||||
just_string[lang].remove(last)
|
||||
else:
|
||||
for j, info in enumerate(option_info):
|
||||
gr1 = info.group(1)
|
||||
if is_viable_non_dupe(gr1, just_string[lang]):
|
||||
just_string[lang].add(gr1)
|
||||
m_h = create_non_dupe(re.sub(r'__+', '_', f'{opt_name}_INFO_{j}'), opt,
|
||||
hash_n_string[lang])
|
||||
hash_n_string[lang][m_h] = gr1
|
||||
else:
|
||||
raise ValueError(f'Too few arguments in struct {struct_type_name[1]} option {option.group(1)}!')
|
||||
|
||||
# group 4:
|
||||
if option.group(4):
|
||||
for j, kv_set in enumerate(cor.p_key_value.finditer(option.group(4))):
|
||||
set_key, set_value = kv_set.group(1, 2)
|
||||
if not is_viable_value(set_value):
|
||||
if not is_viable_value(set_key):
|
||||
continue
|
||||
set_value = set_key
|
||||
# re.fullmatch(r'(?:[+-][0-9]+)+', value[1:-1])
|
||||
if set_value not in just_string[lang] and not re.sub(r'[+-]', '', set_value[1:-1]).isdigit():
|
||||
clean_key = set_key[1:-1]
|
||||
clean_key = remove_special_chars(clean_key).upper().replace(' ', '_')
|
||||
m_h = create_non_dupe(re.sub(r'__+', '_', f"OPTION_VAL_{clean_key}"), opt, hash_n_string[lang])
|
||||
hash_n_string[lang][m_h] = set_value
|
||||
just_string[lang].add(set_value)
|
||||
return hash_n_string
|
||||
|
||||
|
||||
def create_msg_hash(intl_dir_path: str, core_name: str, keyword_string_dict: dict) -> dict:
|
||||
"""Creates '<core_name>.h' files in 'intl/_<lang>/' containing the macro name & string combinations.
|
||||
|
||||
:param intl_dir_path: Path to the intl directory.
|
||||
:param core_name: Name of the core, used for the files' paths.
|
||||
:param keyword_string_dict: Dictionary of the form { '_<lang>': { 'macro': 'string', ... }, ... }.
|
||||
:return: Dictionary of the form { '_<lang>': 'path/to/file (./intl/_<lang>/<core_name>.h)', ... }.
|
||||
"""
|
||||
files = {}
|
||||
for localisation in keyword_string_dict:
|
||||
path = os.path.join(intl_dir_path, core_name) # intl/<core_name>/
|
||||
files[localisation] = os.path.join(path, localisation + '.h') # intl/<core_name>/_<lang>.h
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
with open(files[localisation], 'w', encoding='utf-8') as crowdin_file:
|
||||
out_text = ''
|
||||
for keyword in keyword_string_dict[localisation]:
|
||||
out_text = f'{out_text}{keyword} {keyword_string_dict[localisation][keyword]}\n'
|
||||
crowdin_file.write(out_text)
|
||||
return files
|
||||
|
||||
|
||||
def h2json(file_paths: dict) -> dict:
|
||||
"""Converts .h files pointed to by file_paths into .jsons.
|
||||
|
||||
:param file_paths: Dictionary of the form { '_<lang>': 'path/to/file (./intl/_<lang>/<core_name>.h)', ... }.
|
||||
:return: Dictionary of the form { '_<lang>': 'path/to/file (./intl/_<lang>/<core_name>.json)', ... }.
|
||||
"""
|
||||
jsons = {}
|
||||
for file_lang in file_paths:
|
||||
if not os.path.isfile(file_paths[file_lang]):
|
||||
continue
|
||||
|
||||
jsons[file_lang] = file_paths[file_lang][:-2] + '.json'
|
||||
|
||||
p = cor.p_masked
|
||||
|
||||
with open(file_paths[file_lang], 'r+', encoding='utf-8') as h_file:
|
||||
text = h_file.read()
|
||||
result = p.finditer(text)
|
||||
messages = {}
|
||||
for msg in result:
|
||||
key, val = msg.group(1, 2)
|
||||
if key not in messages:
|
||||
if key and val:
|
||||
# unescape & remove "\n"
|
||||
messages[key] = re.sub(r'"\s*(?:(?:/\*(?:.|[\r\n])*?\*/|//.*[\r\n]+)\s*)*"',
|
||||
'\\\n', val[1:-1].replace('\\\"', '"'))
|
||||
else:
|
||||
print(f"DUPLICATE KEY in {file_paths[file_lang]}: {key}")
|
||||
with open(jsons[file_lang], 'w', encoding='utf-8') as json_file:
|
||||
json.dump(messages, json_file, indent=2)
|
||||
|
||||
return jsons
|
||||
|
||||
|
||||
def json2h(intl_dir_path: str, file_list) -> None:
|
||||
"""Converts .json file in json_file_path into an .h ready to be included in C code.
|
||||
|
||||
:param intl_dir_path: Path to the intl/<core_name> directory.
|
||||
:param file_list: Iterator of os.DirEntry objects. Contains localisation files to convert.
|
||||
:return: None
|
||||
"""
|
||||
|
||||
p = cor.p_masked
|
||||
|
||||
def update(s_messages, s_template, s_source_messages, file_name):
|
||||
translation = ''
|
||||
template_messages = p.finditer(s_template)
|
||||
for tp_msg in template_messages:
|
||||
old_key = tp_msg.group(1)
|
||||
if old_key in s_messages and s_messages[old_key] != s_source_messages[old_key]:
|
||||
tl_msg_val = s_messages[old_key]
|
||||
tl_msg_val = tl_msg_val.replace('"', '\\\"').replace('\n', '') # escape
|
||||
translation = ''.join((translation, '#define ', old_key, file_name.upper(), f' "{tl_msg_val}"\n'))
|
||||
|
||||
else: # Remove English duplicates and non-translatable strings
|
||||
translation = ''.join((translation, '#define ', old_key, file_name.upper(), ' NULL\n'))
|
||||
return translation
|
||||
|
||||
us_h = os.path.join(intl_dir_path, '_us.h')
|
||||
us_json = os.path.join(intl_dir_path, '_us.json')
|
||||
|
||||
with open(us_h, 'r', encoding='utf-8') as template_file:
|
||||
template = template_file.read()
|
||||
with open(us_json, 'r+', encoding='utf-8') as source_json_file:
|
||||
source_messages = json.load(source_json_file)
|
||||
|
||||
for file in file_list:
|
||||
if file.name.lower().startswith('_us') \
|
||||
or file.name.lower().endswith('.h') \
|
||||
or file.is_dir():
|
||||
continue
|
||||
|
||||
with open(file.path, 'r+', encoding='utf-8') as json_file:
|
||||
messages = json.load(json_file)
|
||||
new_translation = update(messages, template, source_messages, os.path.splitext(file.name)[0])
|
||||
with open(os.path.splitext(file.path)[0] + '.h', 'w', encoding='utf-8') as h_file:
|
||||
h_file.seek(0)
|
||||
h_file.write(new_translation)
|
||||
h_file.truncate()
|
||||
return
|
||||
|
||||
|
||||
def get_crowdin_client(dir_path: str) -> str:
|
||||
"""Makes sure the Crowdin CLI client is present. If it isn't, it is fetched & extracted.
|
||||
|
||||
:return: The path to 'crowdin-cli.jar'.
|
||||
"""
|
||||
jar_name = 'crowdin-cli.jar'
|
||||
jar_path = os.path.join(dir_path, jar_name)
|
||||
|
||||
if not os.path.isfile(jar_path):
|
||||
print('Downloading crowdin-cli.jar')
|
||||
crowdin_cli_file = os.path.join(dir_path, 'crowdin-cli.zip')
|
||||
crowdin_cli_url = 'https://downloads.crowdin.com/cli/v3/crowdin-cli.zip'
|
||||
req.urlretrieve(crowdin_cli_url, crowdin_cli_file)
|
||||
import zipfile
|
||||
with zipfile.ZipFile(crowdin_cli_file, 'r') as zip_ref:
|
||||
jar_dir = zip_ref.namelist()[0]
|
||||
for file in zip_ref.namelist():
|
||||
if file.endswith(jar_name):
|
||||
jar_file = file
|
||||
break
|
||||
zip_ref.extract(jar_file)
|
||||
os.rename(jar_file, jar_path)
|
||||
os.remove(crowdin_cli_file)
|
||||
shutil.rmtree(jar_dir)
|
||||
return jar_path
|
||||
|
||||
|
||||
def create_intl_file(localisation_file_path: str, intl_dir_path: str, text: str, file_path: str) -> None:
|
||||
"""Creates 'libretro_core_options_intl.h' from Crowdin translations.
|
||||
|
||||
:param localisation_file_path: Path to 'libretro_core_options_intl.h'
|
||||
:param intl_dir_path: Path to the intl/<core_name> directory.
|
||||
:param text: Content of the 'libretro_core_options.h' being translated.
|
||||
:param file_path: Path to the '_us.h' file, containing the original English texts.
|
||||
:return: None
|
||||
"""
|
||||
msg_dict = {}
|
||||
lang_up = ''
|
||||
|
||||
def replace_pair(pair_match):
|
||||
"""Replaces a key-value-pair of an option with the macros corresponding to the language.
|
||||
|
||||
:param pair_match: The re match object representing the key-value-pair block.
|
||||
:return: Replacement string.
|
||||
"""
|
||||
offset = pair_match.start(0)
|
||||
if pair_match.group(1): # key
|
||||
if pair_match.group(2) in msg_dict: # value
|
||||
val = msg_dict[pair_match.group(2)] + lang_up
|
||||
elif pair_match.group(1) in msg_dict: # use key if value not viable (e.g. NULL)
|
||||
val = msg_dict[pair_match.group(1)] + lang_up
|
||||
else:
|
||||
return pair_match.group(0)
|
||||
else:
|
||||
return pair_match.group(0)
|
||||
res = pair_match.group(0)[:pair_match.start(2) - offset] + val \
|
||||
+ pair_match.group(0)[pair_match.end(2) - offset:]
|
||||
return res
|
||||
|
||||
def replace_info(info_match):
|
||||
"""Replaces the 'additional strings' of an option with the macros corresponding to the language.
|
||||
|
||||
:param info_match: The re match object representing the 'additional strings' block.
|
||||
:return: Replacement string.
|
||||
"""
|
||||
offset = info_match.start(0)
|
||||
if info_match.group(1) in msg_dict:
|
||||
res = info_match.group(0)[:info_match.start(1) - offset] + \
|
||||
msg_dict[info_match.group(1)] + lang_up + \
|
||||
info_match.group(0)[info_match.end(1) - offset:]
|
||||
return res
|
||||
else:
|
||||
return info_match.group(0)
|
||||
|
||||
def replace_option(option_match):
|
||||
"""Replaces strings within an option
|
||||
'{ "opt_key", "label", "additional strings", ..., { {"key", "value"}, ... }, ... }'
|
||||
within a struct with the macros corresponding to the language:
|
||||
'{ "opt_key", MACRO_LABEL, MACRO_STRINGS, ..., { {"key", MACRO_VALUE}, ... }, ... }'
|
||||
|
||||
:param option_match: The re match object representing the option.
|
||||
:return: Replacement string.
|
||||
"""
|
||||
# label
|
||||
offset = option_match.start(0)
|
||||
if option_match.group(2):
|
||||
res = option_match.group(0)[:option_match.start(2) - offset] + msg_dict[option_match.group(2)] + lang_up
|
||||
else:
|
||||
return option_match.group(0)
|
||||
# additional block
|
||||
if option_match.group(3):
|
||||
res = res + option_match.group(0)[option_match.end(2) - offset:option_match.start(3) - offset]
|
||||
new_info = p.sub(replace_info, option_match.group(3))
|
||||
res = res + new_info
|
||||
else:
|
||||
return res + option_match.group(0)[option_match.end(2) - offset:]
|
||||
# key-value-pairs
|
||||
if option_match.group(4):
|
||||
res = res + option_match.group(0)[option_match.end(3) - offset:option_match.start(4) - offset]
|
||||
new_pairs = cor.p_key_value.sub(replace_pair, option_match.group(4))
|
||||
res = res + new_pairs + option_match.group(0)[option_match.end(4) - offset:]
|
||||
else:
|
||||
res = res + option_match.group(0)[option_match.end(3) - offset:]
|
||||
|
||||
return res
|
||||
|
||||
# ------------------------------------------------------------------------------------
|
||||
|
||||
with open(file_path, 'r+', encoding='utf-8') as template: # intl/<core_name>/_us.h
|
||||
masked_msgs = cor.p_masked.finditer(template.read())
|
||||
|
||||
for msg in masked_msgs:
|
||||
msg_dict[msg.group(2)] = msg.group(1)
|
||||
|
||||
# top of the file - in case there is no file to copy it from
|
||||
out_txt = "#ifndef LIBRETRO_CORE_OPTIONS_INTL_H__\n" \
|
||||
"#define LIBRETRO_CORE_OPTIONS_INTL_H__\n\n" \
|
||||
"#if defined(_MSC_VER) && (_MSC_VER >= 1500 && _MSC_VER < 1900)\n" \
|
||||
"/* https://support.microsoft.com/en-us/kb/980263 */\n" \
|
||||
'#pragma execution_character_set("utf-8")\n' \
|
||||
"#pragma warning(disable:4566)\n" \
|
||||
"#endif\n\n" \
|
||||
"#include <libretro.h>\n\n" \
|
||||
'#ifdef __cplusplus\n' \
|
||||
'extern "C" {\n' \
|
||||
'#endif\n'
|
||||
|
||||
if os.path.isfile(localisation_file_path):
|
||||
# copy top of the file for re-use
|
||||
with open(localisation_file_path, 'r', encoding='utf-8') as intl: # libretro_core_options_intl.h
|
||||
in_text = intl.read()
|
||||
intl_start = re.search(re.escape('/*\n'
|
||||
' ********************************\n'
|
||||
' * Core Option Definitions\n'
|
||||
' ********************************\n'
|
||||
'*/\n'), in_text)
|
||||
if intl_start:
|
||||
out_txt = in_text[:intl_start.end(0)]
|
||||
else:
|
||||
intl_start = re.search(re.escape('#ifdef __cplusplus\n'
|
||||
'extern "C" {\n'
|
||||
'#endif\n'), in_text)
|
||||
if intl_start:
|
||||
out_txt = in_text[:intl_start.end(0)]
|
||||
|
||||
# only write to file, if there is anything worthwhile to write!
|
||||
overwrite = False
|
||||
|
||||
# iterate through localisation files
|
||||
files = {}
|
||||
for file in os.scandir(intl_dir_path):
|
||||
files[file.name] = {'is_file': file.is_file(), 'path': file.path}
|
||||
for file in sorted(files): # intl/<core_name>/_*
|
||||
if files[file]['is_file'] \
|
||||
and file.startswith('_') \
|
||||
and file.endswith('.h') \
|
||||
and not file.startswith('_us'):
|
||||
translation_path = files[file]['path'] # <core_name>_<lang>.h
|
||||
# all structs: group(0) full struct, group(1) beginning, group(2) content
|
||||
struct_groups = cor.p_struct.finditer(text)
|
||||
lang_low = os.path.splitext(file)[0].lower()
|
||||
lang_up = lang_low.upper()
|
||||
out_txt = out_txt + f'/* RETRO_LANGUAGE{lang_up} */\n\n' # /* RETRO_LANGUAGE_NM */
|
||||
|
||||
# copy adjusted translations (makros)
|
||||
with open(translation_path, 'r+', encoding='utf-8') as f_in: # <core name>.h
|
||||
out_txt = out_txt + f_in.read() + '\n'
|
||||
# replace English texts with makros
|
||||
for construct in struct_groups:
|
||||
declaration = construct.group(1)
|
||||
struct_type_name = get_struct_type_name(declaration)
|
||||
if 3 > len(struct_type_name): # no language specifier
|
||||
new_decl = re.sub(re.escape(struct_type_name[1]), struct_type_name[1] + lang_low, declaration)
|
||||
else:
|
||||
new_decl = re.sub(re.escape(struct_type_name[2]), lang_low, declaration)
|
||||
if '_us' != struct_type_name[2]:
|
||||
continue
|
||||
|
||||
p = cor.p_info
|
||||
if 'retro_core_option_v2_category' == struct_type_name[0]:
|
||||
p = cor.p_info_cat
|
||||
offset_construct = construct.start(0)
|
||||
start = construct.end(1) - offset_construct
|
||||
end = construct.start(2) - offset_construct
|
||||
out_txt = out_txt + new_decl + construct.group(0)[start:end]
|
||||
|
||||
content = construct.group(2)
|
||||
new_content = cor.p_option.sub(replace_option, content)
|
||||
|
||||
start = construct.end(2) - offset_construct
|
||||
out_txt = out_txt + new_content + construct.group(0)[start:] + '\n'
|
||||
|
||||
# for v2
|
||||
if 'retro_core_option_v2_definition' == struct_type_name[0]:
|
||||
out_txt = out_txt + f'struct retro_core_options_v2 options{lang_low}' \
|
||||
' = {\n' \
|
||||
f' option_cats{lang_low},\n' \
|
||||
f' option_defs{lang_low}\n' \
|
||||
'};\n\n'
|
||||
# if it got this far, we've got something to write
|
||||
overwrite = True
|
||||
|
||||
# only write to file, if there is anything worthwhile to write!
|
||||
if overwrite:
|
||||
with open(localisation_file_path, 'w', encoding='utf-8') as intl:
|
||||
intl.write(out_txt + '\n#ifdef __cplusplus\n'
|
||||
'}\n#endif\n'
|
||||
'\n#endif')
|
||||
return
|
||||
|
||||
|
||||
# -------------------- MAIN -------------------- #
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
if os.path.isfile(sys.argv[1]):
|
||||
_temp = os.path.dirname(sys.argv[1])
|
||||
else:
|
||||
_temp = sys.argv[1]
|
||||
while _temp.endswith('/') or _temp.endswith('\\'):
|
||||
_temp = _temp[:-1]
|
||||
TARGET_DIR_PATH = _temp
|
||||
except IndexError:
|
||||
TARGET_DIR_PATH = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
||||
print("No path provided, assuming parent directory:\n" + TARGET_DIR_PATH)
|
||||
|
||||
CORE_NAME = clean_file_name(sys.argv[2])
|
||||
|
||||
DIR_PATH = os.path.dirname(os.path.realpath(__file__))
|
||||
H_FILE_PATH = os.path.join(TARGET_DIR_PATH, 'libretro_core_options.h')
|
||||
INTL_FILE_PATH = os.path.join(TARGET_DIR_PATH, 'libretro_core_options_intl.h')
|
||||
|
||||
print('Getting texts from libretro_core_options.h')
|
||||
with open(H_FILE_PATH, 'r+', encoding='utf-8') as _h_file:
|
||||
_main_text = _h_file.read()
|
||||
_hash_n_str = get_texts(_main_text)
|
||||
_files = create_msg_hash(DIR_PATH, CORE_NAME, _hash_n_str)
|
||||
_source_jsons = h2json(_files)
|
||||
|
||||
print('Getting texts from libretro_core_options_intl.h')
|
||||
if os.path.isfile(INTL_FILE_PATH):
|
||||
with open(INTL_FILE_PATH, 'r+', encoding='utf-8') as _intl_file:
|
||||
_intl_text = _intl_file.read()
|
||||
_hash_n_str_intl = get_texts(_intl_text)
|
||||
_intl_files = create_msg_hash(DIR_PATH, CORE_NAME, _hash_n_str_intl)
|
||||
_intl_jsons = h2json(_intl_files)
|
||||
|
||||
print('\nAll done!')
|
||||
13
intl/crowdin.yaml
Normal file
13
intl/crowdin.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
"project_id": "380544"
|
||||
"api_token": "_secret_"
|
||||
"base_url": "https://api.crowdin.com"
|
||||
"preserve_hierarchy": true
|
||||
|
||||
"files":
|
||||
[
|
||||
{
|
||||
"source": "/intl/_core_name_/_us.json",
|
||||
"dest": "/_core_name_/_core_name_.json",
|
||||
"translation": "/intl/_core_name_/_%two_letters_code%.json",
|
||||
},
|
||||
]
|
||||
30
intl/crowdin_prep.py
Executable file
30
intl/crowdin_prep.py
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import core_option_translation as t
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
if t.os.path.isfile(t.sys.argv[1]):
|
||||
_temp = t.os.path.dirname(t.sys.argv[1])
|
||||
else:
|
||||
_temp = t.sys.argv[1]
|
||||
while _temp.endswith('/') or _temp.endswith('\\'):
|
||||
_temp = _temp[:-1]
|
||||
TARGET_DIR_PATH = _temp
|
||||
except IndexError:
|
||||
TARGET_DIR_PATH = t.os.path.dirname(t.os.path.dirname(t.os.path.realpath(__file__)))
|
||||
print("No path provided, assuming parent directory:\n" + TARGET_DIR_PATH)
|
||||
|
||||
CORE_NAME = t.clean_file_name(t.sys.argv[2])
|
||||
DIR_PATH = t.os.path.dirname(t.os.path.realpath(__file__))
|
||||
H_FILE_PATH = t.os.path.join(TARGET_DIR_PATH, 'libretro_core_options.h')
|
||||
|
||||
print('Getting texts from libretro_core_options.h')
|
||||
with open(H_FILE_PATH, 'r+', encoding='utf-8') as _h_file:
|
||||
_main_text = _h_file.read()
|
||||
_hash_n_str = t.get_texts(_main_text)
|
||||
_files = t.create_msg_hash(DIR_PATH, CORE_NAME, _hash_n_str)
|
||||
|
||||
_source_jsons = t.h2json(_files)
|
||||
|
||||
print('\nAll done!')
|
||||
93
intl/crowdin_source_upload.py
Executable file
93
intl/crowdin_source_upload.py
Executable file
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import re
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import urllib.request
|
||||
import zipfile
|
||||
import core_option_translation as t
|
||||
|
||||
# -------------------- MAIN -------------------- #
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Check Crowdin API Token and core name
|
||||
try:
|
||||
API_KEY = sys.argv[1]
|
||||
CORE_NAME = t.clean_file_name(sys.argv[2])
|
||||
except IndexError as e:
|
||||
print('Please provide Crowdin API Token and core name!')
|
||||
raise e
|
||||
|
||||
DIR_PATH = t.os.path.dirname(t.os.path.realpath(__file__))
|
||||
YAML_PATH = t.os.path.join(DIR_PATH, 'crowdin.yaml')
|
||||
|
||||
# Apply Crowdin API Key
|
||||
with open(YAML_PATH, 'r') as crowdin_config_file:
|
||||
crowdin_config = crowdin_config_file.read()
|
||||
crowdin_config = re.sub(r'"api_token": "_secret_"',
|
||||
f'"api_token": "{API_KEY}"',
|
||||
crowdin_config, 1)
|
||||
crowdin_config = re.sub(r'/_core_name_',
|
||||
f'/{CORE_NAME}'
|
||||
, crowdin_config)
|
||||
with open(YAML_PATH, 'w') as crowdin_config_file:
|
||||
crowdin_config_file.write(crowdin_config)
|
||||
|
||||
try:
|
||||
# Download Crowdin CLI
|
||||
jar_name = 'crowdin-cli.jar'
|
||||
jar_path = t.os.path.join(DIR_PATH, jar_name)
|
||||
crowdin_cli_file = 'crowdin-cli.zip'
|
||||
crowdin_cli_url = 'https://downloads.crowdin.com/cli/v3/' + crowdin_cli_file
|
||||
crowdin_cli_path = t.os.path.join(DIR_PATH, crowdin_cli_file)
|
||||
|
||||
if not os.path.isfile(t.os.path.join(DIR_PATH, jar_name)):
|
||||
print('download crowdin-cli.jar')
|
||||
urllib.request.urlretrieve(crowdin_cli_url, crowdin_cli_path)
|
||||
with zipfile.ZipFile(crowdin_cli_path, 'r') as zip_ref:
|
||||
jar_dir = t.os.path.join(DIR_PATH, zip_ref.namelist()[0])
|
||||
for file in zip_ref.namelist():
|
||||
if file.endswith(jar_name):
|
||||
jar_file = file
|
||||
break
|
||||
zip_ref.extract(jar_file, path=DIR_PATH)
|
||||
os.rename(t.os.path.join(DIR_PATH, jar_file), jar_path)
|
||||
os.remove(crowdin_cli_path)
|
||||
shutil.rmtree(jar_dir)
|
||||
|
||||
print('upload source *.json')
|
||||
subprocess.run(['java', '-jar', jar_path, 'upload', 'sources', '--config', YAML_PATH])
|
||||
|
||||
# Reset Crowdin API Key
|
||||
with open(YAML_PATH, 'r') as crowdin_config_file:
|
||||
crowdin_config = crowdin_config_file.read()
|
||||
crowdin_config = re.sub(r'"api_token": ".*?"',
|
||||
'"api_token": "_secret_"',
|
||||
crowdin_config, 1)
|
||||
|
||||
# TODO this is NOT safe!
|
||||
crowdin_config = re.sub(re.escape(f'/{CORE_NAME}'),
|
||||
'/_core_name_',
|
||||
crowdin_config)
|
||||
|
||||
with open(YAML_PATH, 'w') as crowdin_config_file:
|
||||
crowdin_config_file.write(crowdin_config)
|
||||
|
||||
except Exception as e:
|
||||
# Try really hard to reset Crowdin API Key
|
||||
with open(YAML_PATH, 'r') as crowdin_config_file:
|
||||
crowdin_config = crowdin_config_file.read()
|
||||
crowdin_config = re.sub(r'"api_token": ".*?"',
|
||||
'"api_token": "_secret_"',
|
||||
crowdin_config, 1)
|
||||
|
||||
# TODO this is NOT safe!
|
||||
crowdin_config = re.sub(re.escape(f'/{CORE_NAME}'),
|
||||
'/_core_name_',
|
||||
crowdin_config)
|
||||
|
||||
with open(YAML_PATH, 'w') as crowdin_config_file:
|
||||
crowdin_config_file.write(crowdin_config)
|
||||
raise e
|
||||
39
intl/crowdin_translate.py
Executable file
39
intl/crowdin_translate.py
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import core_option_translation as t
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
if t.os.path.isfile(t.sys.argv[1]):
|
||||
_temp = t.os.path.dirname(t.sys.argv[1])
|
||||
else:
|
||||
_temp = t.sys.argv[1]
|
||||
while _temp.endswith('/') or _temp.endswith('\\'):
|
||||
_temp = _temp[:-1]
|
||||
TARGET_DIR_PATH = _temp
|
||||
except IndexError:
|
||||
TARGET_DIR_PATH = t.os.path.dirname(t.os.path.dirname(t.os.path.realpath(__file__)))
|
||||
print("No path provided, assuming parent directory:\n" + TARGET_DIR_PATH)
|
||||
|
||||
CORE_NAME = t.clean_file_name(t.sys.argv[2])
|
||||
DIR_PATH = t.os.path.dirname(t.os.path.realpath(__file__))
|
||||
LOCALISATIONS_PATH = t.os.path.join(DIR_PATH, CORE_NAME)
|
||||
US_FILE_PATH = t.os.path.join(LOCALISATIONS_PATH, '_us.h')
|
||||
H_FILE_PATH = t.os.path.join(TARGET_DIR_PATH, 'libretro_core_options.h')
|
||||
INTL_FILE_PATH = t.os.path.join(TARGET_DIR_PATH, 'libretro_core_options_intl.h')
|
||||
|
||||
print('Getting texts from libretro_core_options.h')
|
||||
with open(H_FILE_PATH, 'r+', encoding='utf-8') as _h_file:
|
||||
_main_text = _h_file.read()
|
||||
_hash_n_str = t.get_texts(_main_text)
|
||||
_files = t.create_msg_hash(DIR_PATH, CORE_NAME, _hash_n_str)
|
||||
_source_jsons = t.h2json(_files)
|
||||
|
||||
print('Converting translations *.json to *.h:')
|
||||
localisation_files = t.os.scandir(LOCALISATIONS_PATH)
|
||||
t.json2h(LOCALISATIONS_PATH, localisation_files)
|
||||
|
||||
print('Constructing libretro_core_options_intl.h')
|
||||
t.create_intl_file(INTL_FILE_PATH, LOCALISATIONS_PATH, _main_text, _files["_us"])
|
||||
|
||||
print('\nAll done!')
|
||||
93
intl/crowdin_translation_download.py
Executable file
93
intl/crowdin_translation_download.py
Executable file
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import re
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import urllib.request
|
||||
import zipfile
|
||||
import core_option_translation as t
|
||||
|
||||
# -------------------- MAIN -------------------- #
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Check Crowdin API Token and core name
|
||||
try:
|
||||
API_KEY = sys.argv[1]
|
||||
CORE_NAME = t.clean_file_name(sys.argv[2])
|
||||
except IndexError as e:
|
||||
print('Please provide Crowdin API Token and core name!')
|
||||
raise e
|
||||
|
||||
DIR_PATH = t.os.path.dirname(t.os.path.realpath(__file__))
|
||||
YAML_PATH = t.os.path.join(DIR_PATH, 'crowdin.yaml')
|
||||
|
||||
# Apply Crowdin API Key
|
||||
with open(YAML_PATH, 'r') as crowdin_config_file:
|
||||
crowdin_config = crowdin_config_file.read()
|
||||
crowdin_config = re.sub(r'"api_token": "_secret_"',
|
||||
f'"api_token": "{API_KEY}"',
|
||||
crowdin_config, 1)
|
||||
crowdin_config = re.sub(r'/_core_name_',
|
||||
f'/{CORE_NAME}'
|
||||
, crowdin_config)
|
||||
with open(YAML_PATH, 'w') as crowdin_config_file:
|
||||
crowdin_config_file.write(crowdin_config)
|
||||
|
||||
try:
|
||||
# Download Crowdin CLI
|
||||
jar_name = 'crowdin-cli.jar'
|
||||
jar_path = t.os.path.join(DIR_PATH, jar_name)
|
||||
crowdin_cli_file = 'crowdin-cli.zip'
|
||||
crowdin_cli_url = 'https://downloads.crowdin.com/cli/v3/' + crowdin_cli_file
|
||||
crowdin_cli_path = t.os.path.join(DIR_PATH, crowdin_cli_file)
|
||||
|
||||
if not os.path.isfile(t.os.path.join(DIR_PATH, jar_name)):
|
||||
print('download crowdin-cli.jar')
|
||||
urllib.request.urlretrieve(crowdin_cli_url, crowdin_cli_path)
|
||||
with zipfile.ZipFile(crowdin_cli_path, 'r') as zip_ref:
|
||||
jar_dir = t.os.path.join(DIR_PATH, zip_ref.namelist()[0])
|
||||
for file in zip_ref.namelist():
|
||||
if file.endswith(jar_name):
|
||||
jar_file = file
|
||||
break
|
||||
zip_ref.extract(jar_file, path=DIR_PATH)
|
||||
os.rename(t.os.path.join(DIR_PATH, jar_file), jar_path)
|
||||
os.remove(crowdin_cli_path)
|
||||
shutil.rmtree(jar_dir)
|
||||
|
||||
print('download translation *.json')
|
||||
subprocess.run(['java', '-jar', jar_path, 'download', '--config', YAML_PATH])
|
||||
|
||||
# Reset Crowdin API Key
|
||||
with open(YAML_PATH, 'r') as crowdin_config_file:
|
||||
crowdin_config = crowdin_config_file.read()
|
||||
crowdin_config = re.sub(r'"api_token": ".*?"',
|
||||
'"api_token": "_secret_"',
|
||||
crowdin_config, 1)
|
||||
|
||||
# TODO this is NOT safe!
|
||||
crowdin_config = re.sub(re.escape(f'/{CORE_NAME}'),
|
||||
'/_core_name_',
|
||||
crowdin_config)
|
||||
|
||||
with open(YAML_PATH, 'w') as crowdin_config_file:
|
||||
crowdin_config_file.write(crowdin_config)
|
||||
|
||||
except Exception as e:
|
||||
# Try really hard to reset Crowdin API Key
|
||||
with open(YAML_PATH, 'r') as crowdin_config_file:
|
||||
crowdin_config = crowdin_config_file.read()
|
||||
crowdin_config = re.sub(r'"api_token": ".*?"',
|
||||
'"api_token": "_secret_"',
|
||||
crowdin_config, 1)
|
||||
|
||||
# TODO this is NOT safe!
|
||||
crowdin_config = re.sub(re.escape(f'/{CORE_NAME}'),
|
||||
'/_core_name_',
|
||||
crowdin_config)
|
||||
|
||||
with open(YAML_PATH, 'w') as crowdin_config_file:
|
||||
crowdin_config_file.write(crowdin_config)
|
||||
raise e
|
||||
16
intl/download_workflow.py
Executable file
16
intl/download_workflow.py
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
try:
|
||||
api_key = sys.argv[1]
|
||||
core_name = sys.argv[2]
|
||||
dir_path = sys.argv[3]
|
||||
except IndexError as e:
|
||||
print('Please provide path to libretro_core_options.h, Crowdin API Token and core name!')
|
||||
raise e
|
||||
|
||||
subprocess.run(['python3', 'intl/crowdin_prep.py', dir_path, core_name])
|
||||
subprocess.run(['python3', 'intl/crowdin_translation_download.py', api_key, core_name])
|
||||
subprocess.run(['python3', 'intl/crowdin_translate.py', dir_path, core_name])
|
||||
125
intl/initial_sync.py
Executable file
125
intl/initial_sync.py
Executable file
@@ -0,0 +1,125 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import re
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import urllib.request
|
||||
import zipfile
|
||||
import core_option_translation as t
|
||||
|
||||
# -------------------- MAIN -------------------- #
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Check Crowdin API Token and core name
|
||||
try:
|
||||
API_KEY = sys.argv[1]
|
||||
CORE_NAME = t.clean_file_name(sys.argv[2])
|
||||
except IndexError as e:
|
||||
print('Please provide Crowdin API Token and core name!')
|
||||
raise e
|
||||
|
||||
DIR_PATH = os.path.dirname(os.path.realpath(__file__))
|
||||
YAML_PATH = os.path.join(DIR_PATH, 'crowdin.yaml')
|
||||
|
||||
# Apply Crowdin API Key
|
||||
with open(YAML_PATH, 'r') as crowdin_config_file:
|
||||
crowdin_config = crowdin_config_file.read()
|
||||
crowdin_config = re.sub(r'"api_token": "_secret_"',
|
||||
f'"api_token": "{API_KEY}"',
|
||||
crowdin_config, 1)
|
||||
crowdin_config = re.sub(r'/_core_name_',
|
||||
f'/{CORE_NAME}'
|
||||
, crowdin_config)
|
||||
with open(YAML_PATH, 'w') as crowdin_config_file:
|
||||
crowdin_config_file.write(crowdin_config)
|
||||
|
||||
try:
|
||||
# Download Crowdin CLI
|
||||
jar_name = 'crowdin-cli.jar'
|
||||
jar_path = os.path.join(DIR_PATH, jar_name)
|
||||
crowdin_cli_file = 'crowdin-cli.zip'
|
||||
crowdin_cli_url = 'https://downloads.crowdin.com/cli/v3/' + crowdin_cli_file
|
||||
crowdin_cli_path = os.path.join(DIR_PATH, crowdin_cli_file)
|
||||
|
||||
if not os.path.isfile(os.path.join(DIR_PATH, jar_name)):
|
||||
print('download crowdin-cli.jar')
|
||||
urllib.request.urlretrieve(crowdin_cli_url, crowdin_cli_path)
|
||||
with zipfile.ZipFile(crowdin_cli_path, 'r') as zip_ref:
|
||||
jar_dir = os.path.join(DIR_PATH, zip_ref.namelist()[0])
|
||||
for file in zip_ref.namelist():
|
||||
if file.endswith(jar_name):
|
||||
jar_file = file
|
||||
break
|
||||
zip_ref.extract(jar_file, path=DIR_PATH)
|
||||
os.rename(os.path.join(DIR_PATH, jar_file), jar_path)
|
||||
os.remove(crowdin_cli_path)
|
||||
shutil.rmtree(jar_dir)
|
||||
|
||||
print('upload source & translations *.json')
|
||||
subprocess.run(['java', '-jar', jar_path, 'upload', 'sources', '--config', YAML_PATH])
|
||||
subprocess.run(['java', '-jar', jar_path, 'upload', 'translations', '--config', YAML_PATH])
|
||||
|
||||
print('wait for crowdin server to process data')
|
||||
time.sleep(10)
|
||||
|
||||
print('download translation *.json')
|
||||
subprocess.run(['java', '-jar', jar_path, 'download', '--config', YAML_PATH])
|
||||
|
||||
# Reset Crowdin API Key
|
||||
with open(YAML_PATH, 'r') as crowdin_config_file:
|
||||
crowdin_config = crowdin_config_file.read()
|
||||
crowdin_config = re.sub(r'"api_token": ".*?"', '"api_token": "_secret_"', crowdin_config, 1)
|
||||
|
||||
# TODO this is NOT safe!
|
||||
crowdin_config = re.sub(re.escape(f'/{CORE_NAME}'),
|
||||
'/_core_name_',
|
||||
crowdin_config)
|
||||
|
||||
with open(YAML_PATH, 'w') as crowdin_config_file:
|
||||
crowdin_config_file.write(crowdin_config)
|
||||
|
||||
with open('intl/upload_workflow.py', 'r') as workflow:
|
||||
workflow_config = workflow.read()
|
||||
workflow_config = workflow_config.replace(
|
||||
"subprocess.run(['python3', 'intl/core_option_translation.py', dir_path, core_name])",
|
||||
"subprocess.run(['python3', 'intl/crowdin_prep.py', dir_path, core_name])"
|
||||
)
|
||||
workflow_config = workflow_config.replace(
|
||||
"subprocess.run(['python3', 'intl/initial_sync.py', api_key, core_name])",
|
||||
"subprocess.run(['python3', 'intl/crowdin_source_upload.py', api_key, core_name])"
|
||||
)
|
||||
with open('intl/upload_workflow.py', 'w') as workflow:
|
||||
workflow.write(workflow_config)
|
||||
|
||||
with open('intl/download_workflow.py', 'r') as workflow:
|
||||
workflow_config = workflow.read()
|
||||
workflow_config = workflow_config.replace(
|
||||
"subprocess.run(['python3', 'intl/core_option_translation.py', dir_path, core_name])",
|
||||
"subprocess.run(['python3', 'intl/crowdin_prep.py', dir_path, core_name])"
|
||||
)
|
||||
workflow_config = workflow_config.replace(
|
||||
"subprocess.run(['python3', 'intl/initial_sync.py', api_key, core_name])",
|
||||
"subprocess.run(['python3', 'intl/crowdin_translation_download.py', api_key, core_name])"
|
||||
)
|
||||
with open('intl/download_workflow.py', 'w') as workflow:
|
||||
workflow.write(workflow_config)
|
||||
|
||||
except Exception as e:
|
||||
# Try really hard to reset Crowdin API Key
|
||||
with open(YAML_PATH, 'r') as crowdin_config_file:
|
||||
crowdin_config = crowdin_config_file.read()
|
||||
crowdin_config = re.sub(r'"api_token": ".*?"',
|
||||
'"api_token": "_secret_"',
|
||||
crowdin_config, 1)
|
||||
|
||||
# TODO this is NOT safe!
|
||||
crowdin_config = re.sub(re.escape(f'/{CORE_NAME}'),
|
||||
'/_core_name_',
|
||||
crowdin_config)
|
||||
|
||||
with open(YAML_PATH, 'w') as crowdin_config_file:
|
||||
crowdin_config_file.write(crowdin_config)
|
||||
raise e
|
||||
30
intl/remove_initial_cycle.py
Executable file
30
intl/remove_initial_cycle.py
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
with open('intl/upload_workflow.py', 'r') as workflow:
|
||||
workflow_config = workflow.read()
|
||||
|
||||
workflow_config = workflow_config.replace(
|
||||
"subprocess.run(['python3', 'intl/core_option_translation.py', dir_path, core_name])",
|
||||
"subprocess.run(['python3', 'intl/crowdin_prep.py', dir_path, core_name])"
|
||||
)
|
||||
workflow_config = workflow_config.replace(
|
||||
"subprocess.run(['python3', 'intl/initial_sync.py', api_key, core_name])",
|
||||
"subprocess.run(['python3', 'intl/crowdin_source_upload.py', api_key, core_name])"
|
||||
)
|
||||
with open('intl/upload_workflow.py', 'w') as workflow:
|
||||
workflow.write(workflow_config)
|
||||
|
||||
|
||||
with open('intl/download_workflow.py', 'r') as workflow:
|
||||
workflow_config = workflow.read()
|
||||
|
||||
workflow_config = workflow_config.replace(
|
||||
"subprocess.run(['python3', 'intl/core_option_translation.py', dir_path, core_name])",
|
||||
"subprocess.run(['python3', 'intl/crowdin_prep.py', dir_path, core_name])"
|
||||
)
|
||||
workflow_config = workflow_config.replace(
|
||||
"subprocess.run(['python3', 'intl/initial_sync.py', api_key, core_name])",
|
||||
"subprocess.run(['python3', 'intl/crowdin_translation_download.py', api_key, core_name])"
|
||||
)
|
||||
with open('intl/download_workflow.py', 'w') as workflow:
|
||||
workflow.write(workflow_config)
|
||||
15
intl/upload_workflow.py
Executable file
15
intl/upload_workflow.py
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
try:
|
||||
api_key = sys.argv[1]
|
||||
core_name = sys.argv[2]
|
||||
dir_path = sys.argv[3]
|
||||
except IndexError as e:
|
||||
print('Please provide path to libretro_core_options.h, Crowdin API Token and core name!')
|
||||
raise e
|
||||
|
||||
subprocess.run(['python3', 'intl/crowdin_prep.py', dir_path, core_name])
|
||||
subprocess.run(['python3', 'intl/crowdin_source_upload.py', api_key, core_name])
|
||||
476
intl/v1_to_v2_converter.py
Executable file
476
intl/v1_to_v2_converter.py
Executable file
@@ -0,0 +1,476 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""Core options v1 to v2 converter
|
||||
|
||||
Just run this script as follows, to convert 'libretro_core_options.h' & 'Libretro_coreoptions_intl.h' to v2:
|
||||
python3 "/path/to/v1_to_v2_converter.py" "/path/to/where/libretro_core_options.h & Libretro_coreoptions_intl.h/are"
|
||||
|
||||
The original files will be preserved as *.v1
|
||||
"""
|
||||
import core_option_regex as cor
|
||||
import os
|
||||
import sys
|
||||
import glob
|
||||
|
||||
|
||||
def create_v2_code_file(struct_text, file_name):
|
||||
def replace_option(option_match):
|
||||
_offset = option_match.start(0)
|
||||
|
||||
if option_match.group(3):
|
||||
res = option_match.group(0)[:option_match.end(2) - _offset] + ',\n NULL' + \
|
||||
option_match.group(0)[option_match.end(2) - _offset:option_match.end(3) - _offset] + \
|
||||
'NULL,\n NULL,\n ' + option_match.group(0)[option_match.end(3) - _offset:]
|
||||
else:
|
||||
return option_match.group(0)
|
||||
|
||||
return res
|
||||
|
||||
comment_v1 = '/*\n' \
|
||||
' ********************************\n' \
|
||||
' * VERSION: 1.3\n' \
|
||||
' ********************************\n' \
|
||||
' *\n' \
|
||||
' * - 1.3: Move translations to libretro_core_options_intl.h\n' \
|
||||
' * - libretro_core_options_intl.h includes BOM and utf-8\n' \
|
||||
' * fix for MSVC 2010-2013\n' \
|
||||
' * - Added HAVE_NO_LANGEXTRA flag to disable translations\n' \
|
||||
' * on platforms/compilers without BOM support\n' \
|
||||
' * - 1.2: Use core options v1 interface when\n' \
|
||||
' * RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION is >= 1\n' \
|
||||
' * (previously required RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION == 1)\n' \
|
||||
' * - 1.1: Support generation of core options v0 retro_core_option_value\n' \
|
||||
' * arrays containing options with a single value\n' \
|
||||
' * - 1.0: First commit\n' \
|
||||
'*/\n'
|
||||
|
||||
comment_v2 = '/*\n' \
|
||||
' ********************************\n' \
|
||||
' * VERSION: 2.0\n' \
|
||||
' ********************************\n' \
|
||||
' *\n' \
|
||||
' * - 2.0: Add support for core options v2 interface\n' \
|
||||
' * - 1.3: Move translations to libretro_core_options_intl.h\n' \
|
||||
' * - libretro_core_options_intl.h includes BOM and utf-8\n' \
|
||||
' * fix for MSVC 2010-2013\n' \
|
||||
' * - Added HAVE_NO_LANGEXTRA flag to disable translations\n' \
|
||||
' * on platforms/compilers without BOM support\n' \
|
||||
' * - 1.2: Use core options v1 interface when\n' \
|
||||
' * RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION is >= 1\n' \
|
||||
' * (previously required RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION == 1)\n' \
|
||||
' * - 1.1: Support generation of core options v0 retro_core_option_value\n' \
|
||||
' * arrays containing options with a single value\n' \
|
||||
' * - 1.0: First commit\n' \
|
||||
'*/\n'
|
||||
|
||||
p_intl = cor.p_intl
|
||||
p_set = cor.p_set
|
||||
new_set = 'static INLINE void libretro_set_core_options(retro_environment_t environ_cb,\n' \
|
||||
' bool *categories_supported)\n' \
|
||||
'{\n' \
|
||||
' unsigned version = 0;\n' \
|
||||
'#ifndef HAVE_NO_LANGEXTRA\n' \
|
||||
' unsigned language = 0;\n' \
|
||||
'#endif\n' \
|
||||
'\n' \
|
||||
' if (!environ_cb || !categories_supported)\n' \
|
||||
' return;\n' \
|
||||
'\n' \
|
||||
' *categories_supported = false;\n' \
|
||||
'\n' \
|
||||
' if (!environ_cb(RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION, &version))\n' \
|
||||
' version = 0;\n' \
|
||||
'\n' \
|
||||
' if (version >= 2)\n' \
|
||||
' {\n' \
|
||||
'#ifndef HAVE_NO_LANGEXTRA\n' \
|
||||
' struct retro_core_options_v2_intl core_options_intl;\n' \
|
||||
'\n' \
|
||||
' core_options_intl.us = &options_us;\n' \
|
||||
' core_options_intl.local = NULL;\n' \
|
||||
'\n' \
|
||||
' if (environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &language) &&\n' \
|
||||
' (language < RETRO_LANGUAGE_LAST) && (language != RETRO_LANGUAGE_ENGLISH))\n' \
|
||||
' core_options_intl.local = options_intl[language];\n' \
|
||||
'\n' \
|
||||
' *categories_supported = environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL,\n' \
|
||||
' &core_options_intl);\n' \
|
||||
'#else\n' \
|
||||
' *categories_supported = environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2,\n' \
|
||||
' &options_us);\n' \
|
||||
'#endif\n' \
|
||||
' }\n' \
|
||||
' else\n' \
|
||||
' {\n' \
|
||||
' size_t i, j;\n' \
|
||||
' size_t option_index = 0;\n' \
|
||||
' size_t num_options = 0;\n' \
|
||||
' struct retro_core_option_definition\n' \
|
||||
' *option_v1_defs_us = NULL;\n' \
|
||||
'#ifndef HAVE_NO_LANGEXTRA\n' \
|
||||
' size_t num_options_intl = 0;\n' \
|
||||
' struct retro_core_option_v2_definition\n' \
|
||||
' *option_defs_intl = NULL;\n' \
|
||||
' struct retro_core_option_definition\n' \
|
||||
' *option_v1_defs_intl = NULL;\n' \
|
||||
' struct retro_core_options_intl\n' \
|
||||
' core_options_v1_intl;\n' \
|
||||
'#endif\n' \
|
||||
' struct retro_variable *variables = NULL;\n' \
|
||||
' char **values_buf = NULL;\n' \
|
||||
'\n' \
|
||||
' /* Determine total number of options */\n' \
|
||||
' while (true)\n' \
|
||||
' {\n' \
|
||||
' if (option_defs_us[num_options].key)\n' \
|
||||
' num_options++;\n' \
|
||||
' else\n' \
|
||||
' break;\n' \
|
||||
' }\n' \
|
||||
'\n' \
|
||||
' if (version >= 1)\n' \
|
||||
' {\n' \
|
||||
' /* Allocate US array */\n' \
|
||||
' option_v1_defs_us = (struct retro_core_option_definition *)\n' \
|
||||
' calloc(num_options + 1, sizeof(struct retro_core_option_definition));\n' \
|
||||
'\n' \
|
||||
' /* Copy parameters from option_defs_us array */\n' \
|
||||
' for (i = 0; i < num_options; i++)\n' \
|
||||
' {\n' \
|
||||
' struct retro_core_option_v2_definition *option_def_us = &option_defs_us[i];\n' \
|
||||
' struct retro_core_option_value *option_values = option_def_us->values;\n' \
|
||||
' struct retro_core_option_definition *option_v1_def_us = &option_v1_defs_us[i];\n' \
|
||||
' struct retro_core_option_value *option_v1_values = option_v1_def_us->values;\n' \
|
||||
'\n' \
|
||||
' option_v1_def_us->key = option_def_us->key;\n' \
|
||||
' option_v1_def_us->desc = option_def_us->desc;\n' \
|
||||
' option_v1_def_us->info = option_def_us->info;\n' \
|
||||
' option_v1_def_us->default_value = option_def_us->default_value;\n' \
|
||||
'\n' \
|
||||
' /* Values must be copied individually... */\n' \
|
||||
' while (option_values->value)\n' \
|
||||
' {\n' \
|
||||
' option_v1_values->value = option_values->value;\n' \
|
||||
' option_v1_values->label = option_values->label;\n' \
|
||||
'\n' \
|
||||
' option_values++;\n' \
|
||||
' option_v1_values++;\n' \
|
||||
' }\n' \
|
||||
' }\n' \
|
||||
'\n' \
|
||||
'#ifndef HAVE_NO_LANGEXTRA\n' \
|
||||
' if (environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &language) &&\n' \
|
||||
' (language < RETRO_LANGUAGE_LAST) && (language != RETRO_LANGUAGE_ENGLISH) &&\n' \
|
||||
' options_intl[language])\n' \
|
||||
' option_defs_intl = options_intl[language]->definitions;\n' \
|
||||
'\n' \
|
||||
' if (option_defs_intl)\n' \
|
||||
' {\n' \
|
||||
' /* Determine number of intl options */\n' \
|
||||
' while (true)\n' \
|
||||
' {\n' \
|
||||
' if (option_defs_intl[num_options_intl].key)\n' \
|
||||
' num_options_intl++;\n' \
|
||||
' else\n' \
|
||||
' break;\n' \
|
||||
' }\n' \
|
||||
'\n' \
|
||||
' /* Allocate intl array */\n' \
|
||||
' option_v1_defs_intl = (struct retro_core_option_definition *)\n' \
|
||||
' calloc(num_options_intl + 1, sizeof(struct retro_core_option_definition));\n' \
|
||||
'\n' \
|
||||
' /* Copy parameters from option_defs_intl array */\n' \
|
||||
' for (i = 0; i < num_options_intl; i++)\n' \
|
||||
' {\n' \
|
||||
' struct retro_core_option_v2_definition *option_def_intl = &option_defs_intl[i];\n' \
|
||||
' struct retro_core_option_value *option_values = option_def_intl->values;\n' \
|
||||
' struct retro_core_option_definition *option_v1_def_intl = &option_v1_defs_intl[i];\n' \
|
||||
' struct retro_core_option_value *option_v1_values = option_v1_def_intl->values;\n' \
|
||||
'\n' \
|
||||
' option_v1_def_intl->key = option_def_intl->key;\n' \
|
||||
' option_v1_def_intl->desc = option_def_intl->desc;\n' \
|
||||
' option_v1_def_intl->info = option_def_intl->info;\n' \
|
||||
' option_v1_def_intl->default_value = option_def_intl->default_value;\n' \
|
||||
'\n' \
|
||||
' /* Values must be copied individually... */\n' \
|
||||
' while (option_values->value)\n' \
|
||||
' {\n' \
|
||||
' option_v1_values->value = option_values->value;\n' \
|
||||
' option_v1_values->label = option_values->label;\n' \
|
||||
'\n' \
|
||||
' option_values++;\n' \
|
||||
' option_v1_values++;\n' \
|
||||
' }\n' \
|
||||
' }\n' \
|
||||
' }\n' \
|
||||
'\n' \
|
||||
' core_options_v1_intl.us = option_v1_defs_us;\n' \
|
||||
' core_options_v1_intl.local = option_v1_defs_intl;\n' \
|
||||
'\n' \
|
||||
' environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL, &core_options_v1_intl);\n' \
|
||||
'#else\n' \
|
||||
' environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS, option_v1_defs_us);\n' \
|
||||
'#endif\n' \
|
||||
' }\n' \
|
||||
' else\n' \
|
||||
' {\n' \
|
||||
' /* Allocate arrays */\n' \
|
||||
' variables = (struct retro_variable *)calloc(num_options + 1,\n' \
|
||||
' sizeof(struct retro_variable));\n' \
|
||||
' values_buf = (char **)calloc(num_options, sizeof(char *));\n' \
|
||||
'\n' \
|
||||
' if (!variables || !values_buf)\n' \
|
||||
' goto error;\n' \
|
||||
'\n' \
|
||||
' /* Copy parameters from option_defs_us array */\n' \
|
||||
' for (i = 0; i < num_options; i++)\n' \
|
||||
' {\n' \
|
||||
' const char *key = option_defs_us[i].key;\n' \
|
||||
' const char *desc = option_defs_us[i].desc;\n' \
|
||||
' const char *default_value = option_defs_us[i].default_value;\n' \
|
||||
' struct retro_core_option_value *values = option_defs_us[i].values;\n' \
|
||||
' size_t buf_len = 3;\n' \
|
||||
' size_t default_index = 0;\n' \
|
||||
'\n' \
|
||||
' values_buf[i] = NULL;\n' \
|
||||
'\n' \
|
||||
' if (desc)\n' \
|
||||
' {\n' \
|
||||
' size_t num_values = 0;\n' \
|
||||
'\n' \
|
||||
' /* Determine number of values */\n' \
|
||||
' while (true)\n' \
|
||||
' {\n' \
|
||||
' if (values[num_values].value)\n' \
|
||||
' {\n' \
|
||||
' /* Check if this is the default value */\n' \
|
||||
' if (default_value)\n' \
|
||||
' if (strcmp(values[num_values].value, default_value) == 0)\n' \
|
||||
' default_index = num_values;\n' \
|
||||
'\n' \
|
||||
' buf_len += strlen(values[num_values].value);\n' \
|
||||
' num_values++;\n' \
|
||||
' }\n' \
|
||||
' else\n' \
|
||||
' break;\n' \
|
||||
' }\n' \
|
||||
'\n' \
|
||||
' /* Build values string */\n' \
|
||||
' if (num_values > 0)\n' \
|
||||
' {\n' \
|
||||
' buf_len += num_values - 1;\n' \
|
||||
' buf_len += strlen(desc);\n' \
|
||||
'\n' \
|
||||
' values_buf[i] = (char *)calloc(buf_len, sizeof(char));\n' \
|
||||
' if (!values_buf[i])\n' \
|
||||
' goto error;\n' \
|
||||
'\n' \
|
||||
' strcpy(values_buf[i], desc);\n' \
|
||||
' strcat(values_buf[i], "; ");\n' \
|
||||
'\n' \
|
||||
' /* Default value goes first */\n' \
|
||||
' strcat(values_buf[i], values[default_index].value);\n' \
|
||||
'\n' \
|
||||
' /* Add remaining values */\n' \
|
||||
' for (j = 0; j < num_values; j++)\n' \
|
||||
' {\n' \
|
||||
' if (j != default_index)\n' \
|
||||
' {\n' \
|
||||
' strcat(values_buf[i], "|");\n' \
|
||||
' strcat(values_buf[i], values[j].value);\n' \
|
||||
' }\n' \
|
||||
' }\n' \
|
||||
' }\n' \
|
||||
' }\n' \
|
||||
'\n' \
|
||||
' variables[option_index].key = key;\n' \
|
||||
' variables[option_index].value = values_buf[i];\n' \
|
||||
' option_index++;\n' \
|
||||
' }\n' \
|
||||
'\n' \
|
||||
' /* Set variables */\n' \
|
||||
' environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables);\n' \
|
||||
' }\n' \
|
||||
'\n' \
|
||||
'error:\n' \
|
||||
' /* Clean up */\n' \
|
||||
'\n' \
|
||||
' if (option_v1_defs_us)\n' \
|
||||
' {\n' \
|
||||
' free(option_v1_defs_us);\n' \
|
||||
' option_v1_defs_us = NULL;\n' \
|
||||
' }\n' \
|
||||
'\n' \
|
||||
'#ifndef HAVE_NO_LANGEXTRA\n' \
|
||||
' if (option_v1_defs_intl)\n' \
|
||||
' {\n' \
|
||||
' free(option_v1_defs_intl);\n' \
|
||||
' option_v1_defs_intl = NULL;\n' \
|
||||
' }\n' \
|
||||
'#endif\n' \
|
||||
'\n' \
|
||||
' if (values_buf)\n' \
|
||||
' {\n' \
|
||||
' for (i = 0; i < num_options; i++)\n' \
|
||||
' {\n' \
|
||||
' if (values_buf[i])\n' \
|
||||
' {\n' \
|
||||
' free(values_buf[i]);\n' \
|
||||
' values_buf[i] = NULL;\n' \
|
||||
' }\n' \
|
||||
' }\n' \
|
||||
'\n' \
|
||||
' free(values_buf);\n' \
|
||||
' values_buf = NULL;\n' \
|
||||
' }\n' \
|
||||
'\n' \
|
||||
' if (variables)\n' \
|
||||
' {\n' \
|
||||
' free(variables);\n' \
|
||||
' variables = NULL;\n' \
|
||||
' }\n' \
|
||||
' }\n' \
|
||||
'}\n' \
|
||||
'\n' \
|
||||
'#ifdef __cplusplus\n' \
|
||||
'}\n' \
|
||||
'#endif'
|
||||
|
||||
struct_groups = cor.p_struct.finditer(struct_text)
|
||||
out_text = struct_text
|
||||
|
||||
for construct in struct_groups:
|
||||
repl_text = ''
|
||||
declaration = construct.group(1)
|
||||
struct_match = cor.p_type_name.search(declaration)
|
||||
if struct_match:
|
||||
if struct_match.group(3):
|
||||
struct_type_name_lang = struct_match.group(1, 2, 3)
|
||||
declaration_end = declaration[struct_match.end(1):]
|
||||
elif struct_match.group(4):
|
||||
struct_type_name_lang = struct_match.group(1, 2, 4)
|
||||
declaration_end = declaration[struct_match.end(1):]
|
||||
else:
|
||||
struct_type_name_lang = sum((struct_match.group(1, 2), ('_us',)), ())
|
||||
declaration_end = f'{declaration[struct_match.end(1):struct_match.end(2)]}_us' \
|
||||
f'{declaration[struct_match.end(2):]}'
|
||||
else:
|
||||
return -1
|
||||
|
||||
if 'retro_core_option_definition' == struct_type_name_lang[0]:
|
||||
import shutil
|
||||
shutil.copy(file_name, file_name + '.v1')
|
||||
new_declaration = f'\nstruct retro_core_option_v2_category option_cats{struct_type_name_lang[2]}[] = ' \
|
||||
'{\n { NULL, NULL, NULL },\n' \
|
||||
'};\n\n' \
|
||||
+ declaration[:struct_match.start(1)] + \
|
||||
'retro_core_option_v2_definition' \
|
||||
+ declaration_end
|
||||
offset = construct.start(0)
|
||||
repl_text = repl_text + cor.re.sub(cor.re.escape(declaration), new_declaration,
|
||||
construct.group(0)[:construct.start(2) - offset])
|
||||
content = construct.group(2)
|
||||
new_content = cor.p_option.sub(replace_option, content)
|
||||
|
||||
repl_text = repl_text + new_content + cor.re.sub(r'{\s*NULL,\s*NULL,\s*NULL,\s*{\{0}},\s*NULL\s*},\s*};',
|
||||
'{ NULL, NULL, NULL, NULL, NULL, NULL, {{0}}, NULL },\n};'
|
||||
'\n\nstruct retro_core_options_v2 options' +
|
||||
struct_type_name_lang[2] + ' = {\n'
|
||||
f' option_cats{struct_type_name_lang[2]},\n'
|
||||
f' option_defs{struct_type_name_lang[2]}\n'
|
||||
'};',
|
||||
construct.group(0)[construct.end(2) - offset:])
|
||||
out_text = cor.re.sub(cor.re.escape(construct.group(0)), repl_text, out_text)
|
||||
else:
|
||||
return -2
|
||||
with open(file_name, 'w', encoding='utf-8') as code_file:
|
||||
out_text = cor.re.sub(cor.re.escape(comment_v1), comment_v2, out_text)
|
||||
intl = p_intl.search(out_text)
|
||||
if intl:
|
||||
new_intl = out_text[:intl.start(1)] \
|
||||
+ 'struct retro_core_options_v2 *options_intl[RETRO_LANGUAGE_LAST]' \
|
||||
+ out_text[intl.end(1):intl.start(2)] \
|
||||
+ '\n &options_us, /* RETRO_LANGUAGE_ENGLISH */\n' \
|
||||
' &options_ja, /* RETRO_LANGUAGE_JAPANESE */\n' \
|
||||
' &options_fr, /* RETRO_LANGUAGE_FRENCH */\n' \
|
||||
' &options_es, /* RETRO_LANGUAGE_SPANISH */\n' \
|
||||
' &options_de, /* RETRO_LANGUAGE_GERMAN */\n' \
|
||||
' &options_it, /* RETRO_LANGUAGE_ITALIAN */\n' \
|
||||
' &options_nl, /* RETRO_LANGUAGE_DUTCH */\n' \
|
||||
' &options_pt_br, /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */\n' \
|
||||
' &options_pt_pt, /* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */\n' \
|
||||
' &options_ru, /* RETRO_LANGUAGE_RUSSIAN */\n' \
|
||||
' &options_ko, /* RETRO_LANGUAGE_KOREAN */\n' \
|
||||
' &options_cht, /* RETRO_LANGUAGE_CHINESE_TRADITIONAL */\n' \
|
||||
' &options_chs, /* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */\n' \
|
||||
' &options_eo, /* RETRO_LANGUAGE_ESPERANTO */\n' \
|
||||
' &options_pl, /* RETRO_LANGUAGE_POLISH */\n' \
|
||||
' &options_vn, /* RETRO_LANGUAGE_VIETNAMESE */\n' \
|
||||
' &options_ar, /* RETRO_LANGUAGE_ARABIC */\n' \
|
||||
' &options_el, /* RETRO_LANGUAGE_GREEK */\n' \
|
||||
' &options_tr, /* RETRO_LANGUAGE_TURKISH */\n' \
|
||||
' &options_sv, /* RETRO_LANGUAGE_SLOVAK */\n' \
|
||||
' &options_fa, /* RETRO_LANGUAGE_PERSIAN */\n' \
|
||||
' &options_he, /* RETRO_LANGUAGE_HEBREW */\n' \
|
||||
' &options_ast, /* RETRO_LANGUAGE_ASTURIAN */\n' \
|
||||
' &options_fi, /* RETRO_LANGUAGE_FINNISH */\n' \
|
||||
+ out_text[intl.end(2):]
|
||||
out_text = p_set.sub(new_set, new_intl)
|
||||
else:
|
||||
out_text = p_set.sub(new_set, out_text)
|
||||
code_file.write(out_text)
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
# -------------------- MAIN -------------------- #
|
||||
|
||||
if __name__ == '__main__':
|
||||
DIR_PATH = os.path.dirname(os.path.realpath(__file__))
|
||||
if os.path.basename(DIR_PATH) != "intl":
|
||||
raise RuntimeError("Script is not in intl folder!")
|
||||
|
||||
BASE_PATH = os.path.dirname(DIR_PATH)
|
||||
CORE_OP_FILE = os.path.join(BASE_PATH, "**", "libretro_core_options.h")
|
||||
|
||||
core_options_hits = glob.glob(CORE_OP_FILE, recursive=True)
|
||||
|
||||
if len(core_options_hits) == 0:
|
||||
raise RuntimeError("libretro_core_options.h not found!")
|
||||
elif len(core_options_hits) > 1:
|
||||
print("More than one libretro_core_options.h file found:\n\n")
|
||||
for i, file in enumerate(core_options_hits):
|
||||
print(f"{i} {file}\n")
|
||||
|
||||
while True:
|
||||
user_choice = input("Please choose one ('q' will exit): ")
|
||||
if user_choice == 'q':
|
||||
exit(0)
|
||||
elif user_choice.isdigit():
|
||||
core_op_file = core_options_hits[int(user_choice)]
|
||||
break
|
||||
else:
|
||||
print("Please make a valid choice!\n\n")
|
||||
else:
|
||||
core_op_file = core_options_hits[0]
|
||||
|
||||
H_FILE_PATH = core_op_file
|
||||
INTL_FILE_PATH = core_op_file.replace("libretro_core_options.h", 'libretro_core_options_intl.h')
|
||||
|
||||
for file in (H_FILE_PATH, INTL_FILE_PATH):
|
||||
if os.path.isfile(file):
|
||||
with open(file, 'r+', encoding='utf-8') as h_file:
|
||||
text = h_file.read()
|
||||
try:
|
||||
test = create_v2_code_file(text, file)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
test = -1
|
||||
if -1 > test:
|
||||
print('Your file looks like it already is v2? (' + file + ')')
|
||||
continue
|
||||
if 0 > test:
|
||||
print('An error occured! Please make sure to use the complete v1 struct! (' + file + ')')
|
||||
continue
|
||||
else:
|
||||
print(file + ' not found.')
|
||||
202
ps2/SMS_Utils.s
202
ps2/SMS_Utils.s
@@ -1,202 +0,0 @@
|
||||
/*
|
||||
# ___ _ _ ___
|
||||
# | | | | |
|
||||
# ___| | | ___| PS2DEV Open Source Project.
|
||||
#----------------------------------------------------------
|
||||
# MUL64 is pulled from some binary library (I don't remember which one).
|
||||
# mips_memcpy routine is pulled from 'sde' library from MIPS.
|
||||
#
|
||||
*/
|
||||
.set noat
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
|
||||
.globl MUL64
|
||||
.globl mips_memcpy
|
||||
.globl mips_memset
|
||||
|
||||
.text
|
||||
|
||||
MUL64:
|
||||
pmultuw $v0, $a0, $a1
|
||||
dsra32 $a2, $a0, 0
|
||||
dsra32 $v1, $a1, 0
|
||||
mult $v1, $a0, $v1
|
||||
mult1 $a2, $a2, $a1
|
||||
addu $v1, $v1, $a2
|
||||
dsll32 $v1, $v1, 0
|
||||
jr $ra
|
||||
daddu $v0, $v0, $v1
|
||||
|
||||
mips_memcpy:
|
||||
addu $v0, $a0, $zero
|
||||
beqz $a2, 1f
|
||||
sltiu $t2, $a2, 12
|
||||
bnez $t2, 2f
|
||||
xor $v1, $a1, $a0
|
||||
andi $v1, $v1, 7
|
||||
negu $a3, $a0
|
||||
beqz $v1, 3f
|
||||
andi $a3, $a3, 7
|
||||
beqz $a3, 4f
|
||||
subu $a2, $a2, $a3
|
||||
ldr $v1, 0($a1)
|
||||
ldl $v1, 7($a1)
|
||||
addu $a1, $a1, $a3
|
||||
sdr $v1, 0($a0)
|
||||
addu $a0, $a0, $a3
|
||||
4:
|
||||
andi $v1, $a2, 31
|
||||
subu $a3, $a2, $v1
|
||||
beqz $a3, 5f
|
||||
addu $a2, $v1, $zero
|
||||
addu $a3, $a3, $a1
|
||||
6:
|
||||
ldr $v1, 0($a1)
|
||||
ldl $v1, 7($a1)
|
||||
ldr $t0, 8($a1)
|
||||
ldl $t0, 15($a1)
|
||||
ldr $t1, 16($a1)
|
||||
ldl $t1, 23($a1)
|
||||
ldr $t2, 24($a1)
|
||||
ldl $t2, 31($a1)
|
||||
sd $v1, 0($a0)
|
||||
sd $t0, 8($a0)
|
||||
sd $t1, 16($a0)
|
||||
addiu $a1, $a1, 32
|
||||
addiu $a0, $a0, 32
|
||||
bne $a1, $a3, 6b
|
||||
sd $t2, -8($a0)
|
||||
5:
|
||||
andi $v1, $a2, 7
|
||||
subu $a3, $a2, $v1
|
||||
beqz $a3, 2f
|
||||
addu $a2, $v1, $zero
|
||||
addu $a3, $a3, $a1
|
||||
7:
|
||||
ldr $v1, 0($a1)
|
||||
ldl $v1, 7($a1)
|
||||
addiu $a1, $a1, 8
|
||||
addiu $a0, $a0, 8
|
||||
nop
|
||||
bne $a1, $a3, 7b
|
||||
sd $v1, -8($a0)
|
||||
beq $zero, $zero, 2f
|
||||
nop
|
||||
3:
|
||||
beqz $a3, 8f
|
||||
subu $a2, $a2, $a3
|
||||
ldr $v1, 0($a1)
|
||||
addu $a1, $a1, $a3
|
||||
sdr $v1, 0($a0)
|
||||
addu $a0, $a0, $a3
|
||||
8:
|
||||
andi $v1, $a2, 31
|
||||
subu $a3, $a2, $v1
|
||||
beqz $a3, 9f
|
||||
addu $a2, $v1, $zero
|
||||
addu $a3, $a3, $a1
|
||||
10:
|
||||
ld $v1, 0($a1)
|
||||
ld $t0, 8($a1)
|
||||
ld $t1, 16($a1)
|
||||
ld $t2, 24($a1)
|
||||
sd $v1, 0($a0)
|
||||
sd $t0, 8($a0)
|
||||
sd $t1, 16($a0)
|
||||
addiu $a1, $a1, 32
|
||||
addiu $a0, $a0, 32
|
||||
bne $a1, $a3, 10b
|
||||
sd $t2, -8($a0)
|
||||
9:
|
||||
andi $v1, $a2, 7
|
||||
subu $a3, $a2, $v1
|
||||
beqz $a3, 2f
|
||||
addu $a2, $v1, $zero
|
||||
addu $a3, $a3, $a1
|
||||
11:
|
||||
ld $v1, 0($a1)
|
||||
addiu $a1, $a1, 8
|
||||
addiu $a0, $a0, 8
|
||||
nop
|
||||
nop
|
||||
bne $a1, $a3, 11b
|
||||
sd $v1, -8($a0)
|
||||
2:
|
||||
beqz $a2, 1f
|
||||
addu $a3, $a2, $a1
|
||||
12:
|
||||
lbu $v1, 0($a1)
|
||||
addiu $a1, $a1, 1
|
||||
addiu $a0, $a0, 1
|
||||
nop
|
||||
nop
|
||||
bne $a1, $a3, 12b
|
||||
sb $v1, -1($a0)
|
||||
1:
|
||||
jr $ra
|
||||
nop
|
||||
|
||||
mips_memset:
|
||||
beqz $a2, 1f
|
||||
sltiu $at, $a2, 16
|
||||
bnez $at, 2f
|
||||
andi $a1, $a1, 0xFF
|
||||
dsll $at, $a1, 0x8
|
||||
or $a1, $a1, $at
|
||||
dsll $at, $a1, 0x10
|
||||
or $a1, $a1, $at
|
||||
dsll32 $at, $a1, 0x0
|
||||
or $a1, $a1, $at
|
||||
andi $v1, $a0, 0x7
|
||||
beqz $v1, 3f
|
||||
li $a3, 8
|
||||
subu $a3, $a3, $v1
|
||||
subu $a2, $a2, $a3
|
||||
sdr $a1, 0($a0)
|
||||
addu $a0, $a0, $a3
|
||||
3:
|
||||
andi $v1, $a2, 0x1f
|
||||
subu $a3, $a2, $v1
|
||||
beqz $a3, 4f
|
||||
move $a2, $v1
|
||||
addu $a3, $a3, $a0
|
||||
5:
|
||||
sd $a1, 0($a0)
|
||||
sd $a1, 8($a0)
|
||||
sd $a1, 16($a0)
|
||||
addiu $a0, $a0, 32
|
||||
sd $a1, -8($a0)
|
||||
bne $a0, $a3, 5b
|
||||
4:
|
||||
andi $v1, $a2, 0x7
|
||||
subu $a3, $a2, $v1
|
||||
beqz $a3, 2f
|
||||
move $a2, $v1
|
||||
addu $a3, $a3, $a0
|
||||
6:
|
||||
addiu $a0, $a0, 8
|
||||
beq $a0, $a3, 2f
|
||||
sd $a1, -8($a0)
|
||||
addiu $a0, $a0, 8
|
||||
beq $a0, $a3, 2f
|
||||
sd $a1, -8($a0)
|
||||
addiu $a0, $a0, 8
|
||||
bne $a0, $a3, 6b
|
||||
sd $a1, -8($a0)
|
||||
2:
|
||||
beqz $a2, 1f
|
||||
addu $a3, $a2, $a0
|
||||
7:
|
||||
addiu $a0, $a0, 1
|
||||
beq $a0, $a3, 1f
|
||||
sb $a1, -1($a0)
|
||||
addiu $a0, $a0, 1
|
||||
beq $a0, $a3, 1f
|
||||
sb $a1, -1($a0)
|
||||
addiu $a0, $a0, 1
|
||||
bne $a0, $a3, 7b
|
||||
sb $a1, -1($a0)
|
||||
1:
|
||||
jr $ra
|
||||
nop
|
||||
@@ -1,8 +0,0 @@
|
||||
#ifndef INTTYPES_H
|
||||
#define INTTYPES_H
|
||||
|
||||
#define PRId64 "ld"
|
||||
#define PRIu64 "lu"
|
||||
#define PRIuPTR "lu"
|
||||
|
||||
#endif //INTTYPES_H
|
||||
33
ps2/stdint.h
33
ps2/stdint.h
@@ -1,33 +0,0 @@
|
||||
#ifndef STDINT_H
|
||||
#define STDINT_H
|
||||
|
||||
typedef unsigned long uintptr_t;
|
||||
typedef signed long intptr_t;
|
||||
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef signed long int64_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned long uint64_t;
|
||||
|
||||
typedef unsigned long uint_least32_t;
|
||||
typedef unsigned short uint_least16_t;
|
||||
|
||||
#define STDIN_FILENO 0 /* standard input file descriptor */
|
||||
#define STDOUT_FILENO 1 /* standard output file descriptor */
|
||||
#define STDERR_FILENO 2 /* standard error file descriptor */
|
||||
|
||||
#define INT8_C(val) val##c
|
||||
#define INT16_C(val) val##h
|
||||
#define INT32_C(val) val##i
|
||||
#define INT64_C(val) val##l
|
||||
|
||||
#define UINT8_C(val) val##uc
|
||||
#define UINT16_C(val) val##uh
|
||||
#define UINT32_C(val) val##ui
|
||||
#define UINT64_C(val) val##ul
|
||||
|
||||
#endif //STDINT_H
|
||||
@@ -35,29 +35,45 @@
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 mode;
|
||||
static uint8 vrc2_chr[8], vrc2_prg[2], vrc2_mirr;
|
||||
static uint8 mmc3_regs[10], mmc3_ctrl, mmc3_mirr;
|
||||
static uint8 IRQCount, IRQLatch, IRQa;
|
||||
static uint8 IRQReload;
|
||||
static uint8 mmc1_regs[4], mmc1_buffer, mmc1_shift;
|
||||
static uint8 vrc2_chr[8] = { 0 };
|
||||
static uint8 vrc2_prg[2] = { 0 };
|
||||
static uint8 vrc2_mirr = 0;
|
||||
|
||||
static uint8 mmc3_regs[10] = { 0 };
|
||||
static uint8 mmc3_ctrl = 0;
|
||||
static uint8 mmc3_mirr = 0;
|
||||
|
||||
static uint8 mmc1_regs[4] = { 0 };
|
||||
static uint8 mmc1_buffer = 0;
|
||||
static uint8 mmc1_shift = 0;
|
||||
|
||||
static uint8 IRQCount = 0;
|
||||
static uint8 IRQLatch = 0;
|
||||
static uint8 IRQa = 0;
|
||||
static uint8 IRQReload = 0;
|
||||
static uint8 mode = 0;
|
||||
|
||||
static uint32 isHuang2 = 0;
|
||||
|
||||
extern uint32 ROM_size;
|
||||
extern uint32 VROM_size;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &mode, 1, "MODE" },
|
||||
{ vrc2_chr, 8, "VRCC" },
|
||||
{ vrc2_prg, 2, "VRCP" },
|
||||
{ &vrc2_mirr, 1, "VRCM" },
|
||||
{ mmc3_regs, 10, "M3RG" },
|
||||
{ &mmc3_ctrl, 1, "M3CT" },
|
||||
{ &mmc3_mirr, 1, "M3MR" },
|
||||
{ &IRQReload, 1, "IRQR" },
|
||||
{ &IRQCount, 1, "IRQC" },
|
||||
{ &IRQLatch, 1, "IRQL" },
|
||||
{ &IRQa, 1, "IRQA" },
|
||||
{ mmc1_regs, 4, "M1RG" },
|
||||
{ &mode, 1, "MODE" },
|
||||
{ vrc2_chr, 8, "VRCC" },
|
||||
{ vrc2_prg, 2, "VRCP" },
|
||||
{ &vrc2_mirr, 1, "VRCM" },
|
||||
{ mmc3_regs, 10, "M3RG" },
|
||||
{ &mmc3_ctrl, 1, "M3CT" },
|
||||
{ &mmc3_mirr, 1, "M3MR" },
|
||||
{ &IRQReload, 1, "IRQR" },
|
||||
{ &IRQCount, 1, "IRQC" },
|
||||
{ &IRQLatch, 1, "IRQL" },
|
||||
{ &IRQa, 1, "IRQA" },
|
||||
{ mmc1_regs, 4, "M1RG" },
|
||||
{ &mmc1_buffer, 1, "M1BF" },
|
||||
{ &mmc1_shift, 1, "M1MR" },
|
||||
{ &mmc1_shift, 1, "M1MR" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@@ -83,6 +99,8 @@ static void SyncPRG(void) {
|
||||
{
|
||||
uint8 bank = mmc1_regs[3] & 0xF;
|
||||
if (mmc1_regs[0] & 8) {
|
||||
if (isHuang2)
|
||||
bank >>= 1;
|
||||
if (mmc1_regs[0] & 4) {
|
||||
setprg16(0x8000, bank);
|
||||
setprg16(0xC000, 0x0F);
|
||||
@@ -92,9 +110,9 @@ static void SyncPRG(void) {
|
||||
}
|
||||
} else
|
||||
setprg32(0x8000, bank >> 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SyncCHR(void) {
|
||||
@@ -250,10 +268,10 @@ static DECLFW(UNLSL12Write) {
|
||||
mmc1_regs[n] = mmc1_buffer;
|
||||
mmc1_buffer = mmc1_shift = 0;
|
||||
switch (n) {
|
||||
case 0: SyncMIR();
|
||||
case 2: SyncCHR();
|
||||
case 0: SyncMIR(); break;
|
||||
case 2: SyncCHR(); break;
|
||||
case 3:
|
||||
case 1: SyncPRG();
|
||||
case 1: SyncPRG(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -322,4 +340,7 @@ void UNLSL12_Init(CartInfo *info) {
|
||||
GameHBIRQHook = UNLSL12HBIRQ;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
/* PRG 128K and CHR 128K is Huang-2 */
|
||||
if (ROM_size == 8 && VROM_size == 16)
|
||||
isHuang2 = 1;
|
||||
}
|
||||
|
||||
@@ -56,15 +56,11 @@ static void M121CW(uint32 A, uint8 V) {
|
||||
}
|
||||
|
||||
static void M121PW(uint32 A, uint8 V) {
|
||||
setprg8(A, (V & 0x1F) | ((EXPREGS[3] & 0x80) >> 2));
|
||||
if (EXPREGS[5] & 0x3F) {
|
||||
/* FCEU_printf("prot banks: %02x %02x %02x %02x\n",V,EXPREGS[2],EXPREGS[1],EXPREGS[0]); */
|
||||
setprg8(A, (V & 0x1F) | ((EXPREGS[3] & 0x80) >> 2));
|
||||
setprg8(0xE000, (EXPREGS[0]) | ((EXPREGS[3] & 0x80) >> 2));
|
||||
setprg8(0xC000, (EXPREGS[1]) | ((EXPREGS[3] & 0x80) >> 2));
|
||||
setprg8(0xA000, (EXPREGS[2]) | ((EXPREGS[3] & 0x80) >> 2));
|
||||
} else {
|
||||
/* FCEU_printf("gen banks: %04x %02x\n",A,V); */
|
||||
setprg8(A, (V & 0x1F) | ((EXPREGS[3] & 0x80) >> 2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
136
src/boards/126-422-534.c
Normal file
136
src/boards/126-422-534.c
Normal file
@@ -0,0 +1,136 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020 NewRisingSun
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* Mapper 422: "Normal" version of the mapper. Represents UNIF boards BS-400R and BS-4040R.
|
||||
Mapper 126: Power Joy version of the mapper, connecting CHR A18 and A19 in reverse order.
|
||||
Mapper 534: Waixing version of the mapper, inverting the reload value of the MMC3 scanline counter.
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 reverseCHR_A18_A19;
|
||||
static uint8 invertC000;
|
||||
static uint8 dipSwitch;
|
||||
|
||||
static void wrapPRG(uint32 A, uint8 V) {
|
||||
int prgAND = EXPREGS[0] &0x40? 0x0F: 0x1F; /* 128 KiB or 256 KiB inner PRG bank selection */
|
||||
int prgOR =(EXPREGS[0] <<4 &0x70 | EXPREGS[0] <<3 &0x180) &~prgAND; /* outer PRG bank */
|
||||
switch(EXPREGS[3] &3) {
|
||||
case 0: /* MMC3 PRG mode */
|
||||
break;
|
||||
case 1:
|
||||
case 2: /* NROM-128 mode: MMC3 register 6 applies throughout $8000-$FFFF, MMC3 A13 replaced with CPU A13. */
|
||||
V =DRegBuf[6] &~1 | A >>13 &1;
|
||||
setprg8(A ^0x4000, V &prgAND | prgOR); /* wrapPRG is only called with A containing the switchable banks, so we need to manually switch the normally fixed banks in this mode as well. */
|
||||
break;
|
||||
case 3: /* NROM-256 mode: MMC3 register 6 applies throughout $8000-$FFFF, MMC3 A13-14 replaced with CPU A13-14. */
|
||||
V =DRegBuf[6] &~3 | A >>13 &3;
|
||||
setprg8(A ^0x4000, (V ^2) &prgAND | prgOR); /* wrapPRG is only called with A containing the switchable banks, so we need to manually switch the normally fixed banks in this mode as well. */
|
||||
break;
|
||||
}
|
||||
setprg8(A, V &prgAND | prgOR);
|
||||
}
|
||||
|
||||
static void wrapCHR(uint32 A, uint8 V) {
|
||||
int chrAND = EXPREGS[0] &0x80? 0x7F: 0xFF; /* 128 KiB or 256 KiB innter CHR bank selection */
|
||||
int chrOR; /* outer CHR bank */
|
||||
if (reverseCHR_A18_A19) /* Mapper 126 swaps CHR A18 and A19 */
|
||||
chrOR =(EXPREGS[0] <<4 &0x080 | EXPREGS[0] <<3 &0x100 | EXPREGS[0] <<5 &0x200) &~chrAND;
|
||||
else
|
||||
chrOR =EXPREGS[0] <<4 &0x380 &~chrAND;
|
||||
|
||||
if (EXPREGS[3] &0x10) /* CNROM mode: 8 KiB inner CHR bank comes from outer bank register #2 */
|
||||
setchr8(EXPREGS[2] &(chrAND >>3) | chrOR >>3);
|
||||
else /* MMC3 CHR mode */
|
||||
setchr1(A, (V & chrAND) | chrOR);
|
||||
}
|
||||
|
||||
static DECLFW(writeWRAM) {
|
||||
if (~EXPREGS[3] &0x80) {
|
||||
/* Lock bit clear: Update any outer bank register */
|
||||
EXPREGS[A &3] =V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
} else
|
||||
if ((A &3) ==2) {
|
||||
/* Lock bit set: Only update the bottom one or two bits of the CNROM bank */
|
||||
int latchMask =EXPREGS[2] &0x10? 1: 3; /* 16 or 32 KiB inner CHR bank selection */
|
||||
EXPREGS[2] &=~latchMask;
|
||||
EXPREGS[2] |= V &latchMask;
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
CartBW(A, V);
|
||||
}
|
||||
|
||||
static DECLFR(readDIP) {
|
||||
uint8 result =CartBR(A);
|
||||
if (EXPREGS[1] &1) result =result &~3 | dipSwitch &3; /* Replace bottom two bits with solder pad or DIP switch setting if so selected */
|
||||
return result;
|
||||
}
|
||||
|
||||
static DECLFW(writeIRQ) {
|
||||
MMC3_IRQWrite(A, V ^0xFF);
|
||||
}
|
||||
|
||||
static void reset(void) {
|
||||
dipSwitch++; /* Soft-resetting cycles through solder pad or DIP switch settings */
|
||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void power(void) {
|
||||
dipSwitch =0;
|
||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x6000, 0x7FFF, writeWRAM);
|
||||
SetReadHandler(0x8000, 0xFFFF, readDIP);
|
||||
if (invertC000) SetWriteHandler(0xC000, 0xDFFF, writeIRQ); /* Mapper 534 inverts the MMC3 scanline counter reload value */
|
||||
}
|
||||
|
||||
static void init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 512, 256, 8, info->battery);
|
||||
cwrap = wrapCHR;
|
||||
pwrap = wrapPRG;
|
||||
|
||||
info->Power = power;
|
||||
info->Reset = reset;
|
||||
|
||||
AddExState(EXPREGS, 4, 0, "EXPR");
|
||||
AddExState(&dipSwitch, 1, 0, "DPSW");
|
||||
}
|
||||
|
||||
void Mapper126_Init(CartInfo *info) {
|
||||
reverseCHR_A18_A19 = 1;
|
||||
invertC000 = 0;
|
||||
init(info);
|
||||
}
|
||||
|
||||
void Mapper422_Init(CartInfo *info) {
|
||||
reverseCHR_A18_A19 = 0;
|
||||
invertC000 = 0;
|
||||
init(info);
|
||||
}
|
||||
|
||||
void Mapper534_Init(CartInfo *info) {
|
||||
reverseCHR_A18_A19 = 0;
|
||||
invertC000 = 1;
|
||||
init(info);
|
||||
}
|
||||
105
src/boards/126.c
105
src/boards/126.c
@@ -1,105 +0,0 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2019 Libretro Team
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* Mapper 126, PowerJoy 84-in-1 Multicart (PJ-008*/
|
||||
/* reference from nestopia since not available in nesdev */
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint16 GetExChrExBank() {
|
||||
uint16 bank = (uint16)EXPREGS[0];
|
||||
return ((~bank << 0 & 0x080 & ((uint16)EXPREGS[2])) | (bank << 4 & 0x080 & bank) |
|
||||
(bank << 3 & 0x100) | (bank << 5 & 0x200));
|
||||
}
|
||||
|
||||
static void UpdateChrBank(void) {
|
||||
uint16 bank = (uint16)EXPREGS[2] & 0x0F;
|
||||
bank |= GetExChrExBank() >> 3;
|
||||
setchr8(bank);
|
||||
}
|
||||
|
||||
static void M126CW(uint32 A, uint8 V) {
|
||||
if (!(EXPREGS[3] & 0x10)) {
|
||||
uint16 bank = (uint16)V & (((uint16)EXPREGS[0] & 0x80) - 1);
|
||||
bank |= GetExChrExBank();
|
||||
setchr1(A, bank);
|
||||
}
|
||||
}
|
||||
|
||||
static void M126PW(uint32 A, uint8 V) {
|
||||
uint16 bank = (uint16)V;
|
||||
uint16 preg = (uint16)EXPREGS[0];
|
||||
bank &= ((~preg >> 2) & 0x10) | 0x0F;
|
||||
bank |= ((preg & (0x06 | (preg & 0x40) >> 6)) << 4) | ((preg & 0x10) << 3);
|
||||
if (!(EXPREGS[3] & 0x03))
|
||||
setprg8(A, bank);
|
||||
else if ((A - 0x8000) == ((MMC3_cmd << 8) & 0x4000)) { /* TODO: Clean this */
|
||||
if ((EXPREGS[3] & 0x3) == 0x3)
|
||||
setprg32(0x8000, (bank >> 2));
|
||||
else {
|
||||
setprg16(0x8000, (bank >> 1));
|
||||
setprg16(0xc000, (bank >> 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(M126Write) {
|
||||
A &= 0x03;
|
||||
if(A == 0x01 || A == 0x02 || ((A == 0x00 || A == 0x03) && !(EXPREGS[3] & 0x80))) {
|
||||
if (EXPREGS[A] != V) {
|
||||
EXPREGS[A] = V;
|
||||
if (EXPREGS[3] & 0x10)
|
||||
UpdateChrBank();
|
||||
else
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void M126StateRestore(int v) {
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
|
||||
if (EXPREGS[3] & 0x10)
|
||||
UpdateChrBank();
|
||||
}
|
||||
|
||||
static void M126Reset(void) {
|
||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void M126Power(void) {
|
||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x6000, 0x7FFF, M126Write);
|
||||
}
|
||||
|
||||
void Mapper126_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 2048, 1023, 0, 0);
|
||||
cwrap = M126CW;
|
||||
pwrap = M126PW;
|
||||
info->Power = M126Power;
|
||||
info->Reset = M126Reset;
|
||||
GameStateRestore = M126StateRestore;
|
||||
AddExState(EXPREGS, 4, 0, "EXPR");
|
||||
}
|
||||
96
src/boards/134.c
Normal file
96
src/boards/134.c
Normal file
@@ -0,0 +1,96 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* Chipset used on various PCBs named WX-KB4K, T4A54A, BS-5652... */
|
||||
/* "Rockman 3" on YH-322 and "King of Fighters 97" on "Super 6-in-1" enable interrupts without initializing the frame IRQ register and therefore freeze on real hardware.
|
||||
They can run if another game is selected that does initialize the frame IRQ register, then soft-resetting to the menu and selecting the previously-freezing games. */
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 dip;
|
||||
|
||||
static void Mapper134_PRGWrap(uint32 A, uint8 V) {
|
||||
int prgAND =EXPREGS[1] &0x04? 0x0F: 0x1F;
|
||||
int prgOR =EXPREGS[1] <<4 &0x30 | EXPREGS[0] <<2 &0x40;
|
||||
if (EXPREGS[1] &0x80) { /* NROM mode */
|
||||
if (EXPREGS[1] &0x08) { /* NROM-128 mode */
|
||||
setprg8(0x8000, (DRegBuf[6] &~1 |0) &prgAND | prgOR &~prgAND);
|
||||
setprg8(0xA000, (DRegBuf[6] &~1 |1) &prgAND | prgOR &~prgAND);
|
||||
setprg8(0xC000, (DRegBuf[6] &~1 |0) &prgAND | prgOR &~prgAND);
|
||||
setprg8(0xE000, (DRegBuf[6] &~1 |1) &prgAND | prgOR &~prgAND);
|
||||
} else { /* NROM-256 mode */
|
||||
setprg8(0x8000, (DRegBuf[6] &~3 |0) &prgAND | prgOR &~prgAND);
|
||||
setprg8(0xA000, (DRegBuf[6] &~3 |1) &prgAND | prgOR &~prgAND);
|
||||
setprg8(0xC000, (DRegBuf[6] &~3 |2) &prgAND | prgOR &~prgAND);
|
||||
setprg8(0xE000, (DRegBuf[6] &~3 |3) &prgAND | prgOR &~prgAND);
|
||||
}
|
||||
} else
|
||||
setprg8(A, V &prgAND | prgOR &~prgAND);
|
||||
}
|
||||
|
||||
static void Mapper134_CHRWrap(uint32 A, uint8 V) {
|
||||
int chrAND =EXPREGS[1] &0x40? 0x7F: 0xFF;
|
||||
int chrOR =EXPREGS[1] <<3 &0x180 | EXPREGS[0] <<4 &0x200;
|
||||
if (EXPREGS[0] &0x08) V =EXPREGS[2] <<3 | A >>10 &7; /* In CNROM mode, outer bank register 2 replaces the MMC3's CHR registers, and CHR A10-A12 are PPU A10-A12. */
|
||||
setchr1(A, V &chrAND | chrOR &~chrAND);
|
||||
}
|
||||
|
||||
static DECLFR(Mapper134_Read) {
|
||||
return EXPREGS[0] &0x40? dip: CartBR(A);
|
||||
}
|
||||
|
||||
static DECLFW(Mapper134_Write) {
|
||||
if (~EXPREGS[0] &0x80) {
|
||||
EXPREGS[A &3] =V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
} else
|
||||
if ((A &3) ==2) {
|
||||
EXPREGS[A &3] =EXPREGS[A &3] &~3 | V &3;
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
CartBW(A, V);
|
||||
}
|
||||
|
||||
static void Mapper134_Reset(void) {
|
||||
dip++;
|
||||
dip &= 15;
|
||||
EXPREGS[0] =EXPREGS[1] =EXPREGS[2] =EXPREGS[3] =0;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void Mapper134_Power(void) {
|
||||
dip =0;
|
||||
EXPREGS[0] =EXPREGS[1] =EXPREGS[2] =EXPREGS[3] =0;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x6000, 0x7FFF, Mapper134_Write);
|
||||
SetReadHandler(0x8000, 0xFFFF, Mapper134_Read);
|
||||
}
|
||||
|
||||
void Mapper134_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 256, 256, info->iNES2? (info->PRGRamSize + info->PRGRamSaveSize) /1024: 8, info->battery);
|
||||
cwrap = Mapper134_CHRWrap;
|
||||
pwrap = Mapper134_PRGWrap;
|
||||
info->Power = Mapper134_Power;
|
||||
info->Reset = Mapper134_Reset;
|
||||
AddExState(EXPREGS, 4, 0, "EXPR");
|
||||
AddExState(&dip, 1, 0, "DIPS");
|
||||
}
|
||||
@@ -63,11 +63,19 @@ static void Sync(void) {
|
||||
setprg8(0xC000, preg[2]);
|
||||
setprg8(0xE000, preg[3]);
|
||||
setmirror(((latched >> 6) & 1) ^ 1);
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
static DECLFW(M15Write) {
|
||||
latchea = A;
|
||||
latched = V;
|
||||
/* cah4e3 02.10.19 once again, there may be either two similar mapper 15 exist. the one for 110in1 or 168in1 carts with complex multi game features.
|
||||
and another implified version for subor/waixing chinese originals and hacks with no different modes, working only in mode 0 and which does not
|
||||
expect there is any CHR write protection. protecting CHR writes only for mode 3 fixes the problem, all roms may be run on the same source again. */
|
||||
if((latchea & 3) == 3)
|
||||
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0);
|
||||
else
|
||||
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1);
|
||||
Sync();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2015 CaH4e3
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* "Blood Of Jurassic" protected MMC3 based board (GD-98 Cart ID, 158B PCB ID)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 lut[8] = { 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x0F, 0x00 };
|
||||
|
||||
static void UNL158BPW(uint32 A, uint8 V) {
|
||||
if (EXPREGS[0] & 0x80) {
|
||||
uint32 bank = EXPREGS[0] & 7;
|
||||
if(EXPREGS[0] & 0x20) { /* 32Kb mode */
|
||||
setprg32(0x8000, bank >> 1);
|
||||
} else { /* 16Kb mode */
|
||||
setprg16(0x8000, bank);
|
||||
setprg16(0xC000, bank);
|
||||
}
|
||||
} else {
|
||||
setprg8(A, V & 0xF);
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(UNL158BProtWrite) {
|
||||
EXPREGS[A & 7] = V;
|
||||
switch(A & 7) {
|
||||
case 0:
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
break;
|
||||
case 7:
|
||||
FCEU_printf("UNK PROT WRITE\n");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static DECLFR(UNL158BProtRead) {
|
||||
return X.DB | lut[A & 7];
|
||||
}
|
||||
|
||||
static void UNL158BPower(void) {
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x5000, 0x5FFF, UNL158BProtWrite);
|
||||
SetReadHandler(0x5000, 0x5FFF, UNL158BProtRead);
|
||||
}
|
||||
|
||||
void UNL158B_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 128, 128, 0, 0);
|
||||
pwrap = UNL158BPW;
|
||||
info->Power = UNL158BPower;
|
||||
AddExState(EXPREGS, 8, 0, "EXPR");
|
||||
}
|
||||
119
src/boards/162.c
Normal file
119
src/boards/162.c
Normal file
@@ -0,0 +1,119 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
* Copyright (C) 2019 Libretro Team
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* Waixing FS304 PCB */
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 *WRAM;
|
||||
static uint32 WRAMSIZE;
|
||||
static uint8 reg[4];
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ reg, 4, "REGS" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void sync()
|
||||
{
|
||||
setprg32(0x8000, reg[2] <<4 | reg[0] &0x0C /* PRG A17-A20 always normal from $5000 and $5200 */
|
||||
| ( reg[3] &0x04 ? 0x00 : 0x02) /* PRG A16 is 1 if $5300.2=0 */
|
||||
| ( reg[3] &0x04 ?(reg[0] &0x02): 0x00) /* PRG A16 is $5000.1 if %5300.2=1 */
|
||||
| ( reg[3] &0x01? 0x00 : reg[1] >>1 &0x01) /* PRG A15 is $5100.1 if $5300.0=0 */
|
||||
| (~reg[3] &0x04 && reg[3] &0x01? 0x01 : 0x00) /* PRG A15 is 1 if $5300.2=0 and $5300.0=1 */
|
||||
| ( reg[3] &0x04 && reg[3] &0x01?(reg[0] &0x01): 0x00) /* PRG A15 is $5000.0 if $5300.2=1 and $5300.0=1 */
|
||||
);
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
if (~reg[0] &0x80)
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
static void hblank(void) {
|
||||
if (reg[0] &0x80 && scanline <239)
|
||||
{ /* Actual hardware cannot look at the current scanline number, but instead latches PA09 on PA13 rises. This does not seem possible with the current PPU emulation however. */
|
||||
setchr4(0x0000, scanline >=127? 1: 0);
|
||||
setchr4(0x1000, scanline >=127? 1: 0);
|
||||
}
|
||||
else
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
static DECLFR(readReg)
|
||||
{
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
static DECLFW(writeReg)
|
||||
{
|
||||
reg[A >>8 &3] = V;
|
||||
sync();
|
||||
}
|
||||
|
||||
static void power(void)
|
||||
{
|
||||
memset(reg, 0, sizeof(reg));
|
||||
sync();
|
||||
SetReadHandler (0x5000, 0x57FF, readReg);
|
||||
SetWriteHandler(0x5000, 0x57FF, writeReg);
|
||||
SetReadHandler (0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
}
|
||||
|
||||
static void reset(void)
|
||||
{
|
||||
memset(reg, 0, sizeof(reg));
|
||||
sync();
|
||||
}
|
||||
|
||||
static void close(void)
|
||||
{
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
sync();
|
||||
}
|
||||
|
||||
void Mapper162_Init (CartInfo *info)
|
||||
{
|
||||
info->Power = power;
|
||||
info->Reset = reset;
|
||||
info->Close = close;
|
||||
GameHBIRQHook = hblank;
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(StateRegs, ~0, 0, 0);
|
||||
|
||||
WRAMSIZE = info->iNES2? (info->PRGRamSize + info->PRGRamSaveSize): 8192;
|
||||
WRAM = (uint8*) FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
|
||||
if (info->battery) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
info->SaveGameLen[0] = WRAMSIZE;
|
||||
}
|
||||
}
|
||||
124
src/boards/163.c
Normal file
124
src/boards/163.c
Normal file
@@ -0,0 +1,124 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
* Copyright (C) 2019 Libretro Team
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* Nanjing FC-001 PCB */
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 *WRAM;
|
||||
static uint32 WRAMSIZE;
|
||||
static uint8 reg[4];
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ reg, 4, "REGS" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void sync()
|
||||
{
|
||||
setprg32(0x8000, reg[2] <<4 | reg[0] &0xF | (reg[3] &0x04? 0x00: 0x03));
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
if (~reg[0] &0x80)
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
static void hblank(void) {
|
||||
if (reg[0] &0x80 && scanline <239)
|
||||
{ /* Actual hardware cannot look at the current scanline number, but instead latches PA09 on PA13 rises. This does not seem possible with the current PPU emulation however. */
|
||||
setchr4(0x0000, scanline >=127? 1: 0);
|
||||
setchr4(0x1000, scanline >=127? 1: 0);
|
||||
}
|
||||
else
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
static DECLFR(readReg)
|
||||
{
|
||||
return ~reg[1] &0x04;
|
||||
}
|
||||
|
||||
static DECLFW(writeReg)
|
||||
{
|
||||
uint8 index = A >>8 &3;
|
||||
|
||||
/* Swap bits of registers 0-2 again if the "swap bits" bit is set. Exclude register 2 on when PRG-ROM is 1 MiB. */
|
||||
if (reg[3] &0x01 && index <= (ROM_size == 64? 1: 2))
|
||||
V = V &~3 | V >>1 &1 | V <<1 &2;
|
||||
|
||||
if (A &1)
|
||||
{
|
||||
if (reg[1] &0x01 && ~V &0x01) reg[1] ^=0x04; /* If A0=1, flip feedback bit on falling edges of D0 */
|
||||
} /* If A0=0, write to register */
|
||||
else
|
||||
reg[index] = V;
|
||||
sync();
|
||||
}
|
||||
|
||||
static void power(void)
|
||||
{
|
||||
memset(reg, 0, sizeof(reg));
|
||||
sync();
|
||||
SetReadHandler (0x5000, 0x57FF, readReg);
|
||||
SetWriteHandler(0x5000, 0x57FF, writeReg);
|
||||
SetReadHandler (0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
}
|
||||
|
||||
static void reset(void)
|
||||
{
|
||||
memset(reg, 0, sizeof(reg));
|
||||
sync();
|
||||
}
|
||||
|
||||
static void close(void)
|
||||
{
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
sync();
|
||||
}
|
||||
|
||||
void Mapper163_Init (CartInfo *info)
|
||||
{
|
||||
info->Power = power;
|
||||
info->Reset = reset;
|
||||
info->Close = close;
|
||||
GameHBIRQHook = hblank;
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(StateRegs, ~0, 0, 0);
|
||||
|
||||
WRAMSIZE = info->iNES2? (info->PRGRamSize + info->PRGRamSaveSize): 8192;
|
||||
WRAM = (uint8*) FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
|
||||
if (info->battery) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
info->SaveGameLen[0] = WRAMSIZE;
|
||||
}
|
||||
}
|
||||
281
src/boards/164.c
281
src/boards/164.c
@@ -1,7 +1,9 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel 2006 CaH4e3
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
* Copyright (C) 2019 Libretro Team
|
||||
*
|
||||
* 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
|
||||
@@ -16,217 +18,120 @@
|
||||
* 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
|
||||
*
|
||||
* It seems that 162/163/164 mappers are the same mapper with just different
|
||||
* mapper modes enabled or disabled in software or hardware, need more nanjing
|
||||
* carts
|
||||
*/
|
||||
|
||||
/* Dongda PEC-9588 educational computer. Provides the same 1bpp all-points-addressable graphics mode.
|
||||
Its chipset was later used for the Yancheng cy2000-3 PCB, used on most of the games that display "Union Bond" at the start.
|
||||
Some of them also use the 1bpp mode for a few screens!
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "eeprom_93C66.h"
|
||||
|
||||
static uint8 laststrobe, trigger;
|
||||
static uint8 reg[8];
|
||||
static uint8 *WRAM = NULL;
|
||||
static uint8 *WRAM;
|
||||
static uint32 WRAMSIZE;
|
||||
|
||||
static writefunc pcmwrite;
|
||||
|
||||
static void (*WSync)(void);
|
||||
|
||||
static uint8 reg[8];
|
||||
static uint8 eeprom_data[512];
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &laststrobe, 1, "STB" },
|
||||
{ &trigger, 1, "TRG" },
|
||||
{ reg, 8, "REGS" },
|
||||
{ 0 }
|
||||
{ reg, 8, "REGS" },
|
||||
{ eeprom_data, 512, "EEPR" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
setprg32(0x8000, (reg[0] << 4) | (reg[1] & 0xF));
|
||||
setchr8(0);
|
||||
static void sync()
|
||||
{
|
||||
uint8 prgLow = reg[0] &0x0F | reg[0] >>1 &0x10;
|
||||
uint8 prgHigh = reg[1] <<5;
|
||||
switch (reg[0] >>5 &2 | reg[0] >>4 &1)
|
||||
{
|
||||
case 0: /* UNROM-512 */
|
||||
setprg16(0x8000, prgHigh | prgLow);
|
||||
setprg16(0xC000, prgHigh | 0x1F);
|
||||
break;
|
||||
case 1: /* Open Bus on Yancheng cy2000-3 PCB, expansion cartridge on the Dongda PEC-9588 */
|
||||
break;
|
||||
case 2: /* UNROM-448+64. Very strange mode, used for the LOGO program on the Dongda PEC-9588 */
|
||||
setprg16(0x8000, prgHigh | prgLow);
|
||||
setprg16(0xC000, prgHigh |(prgLow >=0x1C? 0x1C: 0x1E));
|
||||
break;
|
||||
case 3: /* UNROM-128 or BNROM */
|
||||
if (prgLow &0x10)
|
||||
{
|
||||
setprg16(0x8000, prgHigh | prgLow <<1 &0x10 | prgLow &0x0F);
|
||||
setprg16(0xC000, prgHigh | prgLow <<1 &0x10 | 0x0F);
|
||||
}
|
||||
else
|
||||
setprg32(0x8000, prgHigh >>1 | prgLow);
|
||||
break;
|
||||
}
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
|
||||
setchr8(0);
|
||||
PEC586Hack = !!(reg[0] &0x80);
|
||||
|
||||
setmirror(reg[0] &0x10 && ~reg[3] &0x80? MI_H: MI_V);
|
||||
|
||||
eeprom_93C66_write(reg[2] &0x10, reg[2] &0x04, reg[2] &0x01);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
WSync();
|
||||
static DECLFR(readReg)
|
||||
{
|
||||
return eeprom_93C66_read()? 0x00: 0x04;
|
||||
}
|
||||
|
||||
static DECLFR(ReadLow) {
|
||||
switch (A & 0x7700) {
|
||||
case 0x5100: return reg[2] | reg[0] | reg[1] | (reg[3] ^ 0xff); break;
|
||||
case 0x5500:
|
||||
if (trigger)
|
||||
return reg[2] | reg[1]; /* Lei Dian Huang Bi Ka Qiu Chuan Shuo (NJ046) may broke other games */
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
return 4;
|
||||
static DECLFW(writeReg)
|
||||
{
|
||||
reg[A >>8 &7] = V;
|
||||
sync();
|
||||
}
|
||||
|
||||
static void M163HB(void) {
|
||||
if (reg[1] & 0x80) {
|
||||
if (scanline == 239) {
|
||||
setchr4(0x0000, 0);
|
||||
setchr4(0x1000, 0);
|
||||
} else if (scanline == 127) {
|
||||
setchr4(0x0000, 1);
|
||||
setchr4(0x1000, 1);
|
||||
}
|
||||
#if 0
|
||||
if(scanline>=127) /* Hu Lu Jin Gang (NJ039) (Ch) [!] don't like it */
|
||||
{
|
||||
setchr4(0x0000,1);
|
||||
setchr4(0x1000,1);
|
||||
}
|
||||
else
|
||||
{
|
||||
setchr4(0x0000,0);
|
||||
setchr4(0x1000,0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
static void power(void)
|
||||
{
|
||||
memset(reg, 0, sizeof(reg));
|
||||
eeprom_93C66_init();
|
||||
sync();
|
||||
SetReadHandler (0x5400, 0x57FF, readReg);
|
||||
SetWriteHandler(0x5000, 0x57FF, writeReg);
|
||||
SetReadHandler (0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
}
|
||||
|
||||
static DECLFW(Write) {
|
||||
switch (A & 0x7300) {
|
||||
case 0x5100: reg[0] = V; WSync(); break;
|
||||
case 0x5000: reg[1] = V; WSync(); break;
|
||||
case 0x5300: reg[2] = V; break;
|
||||
case 0x5200: reg[3] = V; WSync(); break;
|
||||
}
|
||||
static void reset(void)
|
||||
{
|
||||
memset(reg, 0, sizeof(reg));
|
||||
sync();
|
||||
}
|
||||
|
||||
static void Power(void) {
|
||||
memset(reg, 0, 8);
|
||||
reg[1] = 0xFF;
|
||||
SetWriteHandler(0x5000, 0x5FFF, Write);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
WSync();
|
||||
static void close(void)
|
||||
{
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
static void Close(void) {
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
sync();
|
||||
}
|
||||
|
||||
void Mapper164_Init(CartInfo *info) {
|
||||
info->Power = Power;
|
||||
info->Close = Close;
|
||||
WSync = Sync;
|
||||
void Mapper164_Init (CartInfo *info)
|
||||
{
|
||||
info->Power = power;
|
||||
info->Reset = reset;
|
||||
info->Close = close;
|
||||
|
||||
WRAMSIZE = 8192;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(StateRegs, ~0, 0, 0);
|
||||
|
||||
if (info->battery) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
info->SaveGameLen[0] = WRAMSIZE;
|
||||
}
|
||||
WRAMSIZE = info->iNES2? (info->PRGRamSize + (info->PRGRamSaveSize &~0x7FF)): 8192;
|
||||
WRAM = (uint8*) FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
static DECLFW(Write2) {
|
||||
if (A == 0x5101) {
|
||||
if (laststrobe && !V) {
|
||||
trigger ^= 1;
|
||||
}
|
||||
laststrobe = V;
|
||||
} else if (A == 0x5100 && V == 6) /* damn those protected games */
|
||||
setprg32(0x8000, 3);
|
||||
else
|
||||
switch (A & 0x7300) {
|
||||
case 0x5200: reg[0] = V; WSync(); break;
|
||||
case 0x5000: reg[1] = V; WSync(); if (!(reg[1] & 0x80) && (scanline < 128)) setchr8(0); /* setchr8(0); */ break;
|
||||
case 0x5300: reg[2] = V; break;
|
||||
case 0x5100: reg[3] = V; WSync(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Power2(void) {
|
||||
memset(reg, 0, 8);
|
||||
laststrobe = 1;
|
||||
pcmwrite = GetWriteHandler(0x4011);
|
||||
SetReadHandler(0x5000, 0x5FFF, ReadLow);
|
||||
SetWriteHandler(0x5000, 0x5FFF, Write2);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
WSync();
|
||||
}
|
||||
|
||||
void Mapper163_Init(CartInfo *info) {
|
||||
info->Power = Power2;
|
||||
info->Close = Close;
|
||||
WSync = Sync;
|
||||
GameHBIRQHook = M163HB;
|
||||
|
||||
WRAMSIZE = 8192;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
|
||||
if (info->battery) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
info->SaveGameLen[0] = WRAMSIZE;
|
||||
}
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
static void Sync3(void) {
|
||||
setchr8(0);
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
switch (reg[3] & 7) {
|
||||
case 0:
|
||||
case 2: setprg32(0x8000, (reg[0] & 0xc) | (reg[1] & 2) | ((reg[2] & 0xf) << 4)); break;
|
||||
case 1:
|
||||
case 3: setprg32(0x8000, (reg[0] & 0xc) | (reg[2] & 0xf) << 4); break;
|
||||
case 4:
|
||||
case 6: setprg32(0x8000, (reg[0] & 0xe) | ((reg[1] >> 1) & 1) | ((reg[2] & 0xf) << 4)); break;
|
||||
case 5:
|
||||
case 7: setprg32(0x8000, (reg[0] & 0xf) | ((reg[2] & 0xf) << 4)); break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(Write3) {
|
||||
/* FCEU_printf("bs %04x %02x\n",A,V); */
|
||||
reg[(A >> 8) & 3] = V;
|
||||
WSync();
|
||||
}
|
||||
|
||||
static void Power3(void) {
|
||||
reg[0] = 3;
|
||||
reg[1] = 0;
|
||||
reg[2] = 0;
|
||||
reg[3] = 7;
|
||||
SetWriteHandler(0x5000, 0x5FFF, Write3);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
WSync();
|
||||
}
|
||||
|
||||
void UNLFS304_Init(CartInfo *info) {
|
||||
info->Power = Power3;
|
||||
info->Close = Close;
|
||||
WSync = Sync3;
|
||||
|
||||
WRAMSIZE = 8192;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
|
||||
if (info->battery) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
info->SaveGameLen[0] = WRAMSIZE;
|
||||
}
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
eeprom_93C66_storage = eeprom_data;
|
||||
info->battery = 1;
|
||||
info->SaveGame[0] = eeprom_data;
|
||||
info->SaveGameLen[0] = 512;
|
||||
}
|
||||
|
||||
@@ -136,6 +136,11 @@ static void M178Power(void) {
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void M178Reset(void) {
|
||||
/* Always reset to menu */
|
||||
reg[0] = reg[1] = reg[2] = reg[3] = 0;
|
||||
Sync();
|
||||
}
|
||||
static void M178SndClk(int a) {
|
||||
if (pcm_enable) {
|
||||
pcm_latch -= a;
|
||||
@@ -158,6 +163,7 @@ static void StateRestore(int version) {
|
||||
|
||||
void Mapper178_Init(CartInfo *info) {
|
||||
info->Power = M178Power;
|
||||
info->Reset = M178Reset;
|
||||
info->Close = M178Close;
|
||||
GameStateRestore = StateRestore;
|
||||
MapIRQHook = M178SndClk;
|
||||
|
||||
97
src/boards/195.c
Normal file
97
src/boards/195.c
Normal file
@@ -0,0 +1,97 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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"
|
||||
#include "mmc3.h"
|
||||
|
||||
writefunc writePPU;
|
||||
static uint8 *CHRRAM;
|
||||
static uint32 CHRRAMSIZE;
|
||||
static uint8 mask;
|
||||
static uint8 compare;
|
||||
extern uint32 RefreshAddr;
|
||||
|
||||
static void Mapper195_CHRWrap(uint32 A, uint8 V) {
|
||||
if ((V &mask) ==compare)
|
||||
setchr1r(0x10, A, V);
|
||||
else
|
||||
setchr1r(0, A, V);
|
||||
}
|
||||
|
||||
static const uint8 compares[8] = { 0x28, 0x00, 0x4C, 0x64, 0x46, 0x7C, 0x04, 0xFF };
|
||||
static DECLFW(Mapper195_InterceptPPUWrite) {
|
||||
if (RefreshAddr <0x2000) {
|
||||
int addr =RefreshAddr;
|
||||
int reg, bank;
|
||||
|
||||
if (MMC3_cmd &0x80) addr ^=0x1000;
|
||||
if (addr <0x1000)
|
||||
reg =addr >>11;
|
||||
else
|
||||
reg =(addr >>10) -2;
|
||||
|
||||
bank =DRegBuf[reg];
|
||||
if (bank &0x80) {
|
||||
if (bank &0x10) {
|
||||
mask =0x00;
|
||||
compare =0xFF;
|
||||
} else {
|
||||
int index =(bank &0x02? 1: 0) | (bank &0x08? 2: 0) | (bank &0x40? 4: 0);
|
||||
mask =bank &0x40? 0xFE: 0xFC;
|
||||
compare =compares[index];
|
||||
}
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
writePPU(A, V);
|
||||
}
|
||||
|
||||
static void Mapper195_Power(void) {
|
||||
mask =0xFC;
|
||||
compare =0x00;
|
||||
GenMMC3Power();
|
||||
setprg4r(0x10, 0x5000, 2);
|
||||
SetWriteHandler(0x5000, 0x5FFF, CartBW);
|
||||
SetReadHandler(0x5000, 0x5FFF, CartBR);
|
||||
|
||||
if (GetWriteHandler(0x2007) !=Mapper195_InterceptPPUWrite) {
|
||||
writePPU =GetWriteHandler(0x2007);
|
||||
SetWriteHandler(0x2007, 0x2007, Mapper195_InterceptPPUWrite);
|
||||
}
|
||||
}
|
||||
|
||||
void Mapper195_Close(void) {
|
||||
if (CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
}
|
||||
|
||||
void Mapper195_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 512, 256, 16, info->battery);
|
||||
cwrap = Mapper195_CHRWrap;
|
||||
info->Power = Mapper195_Power;
|
||||
info->Reset = MMC3RegReset;
|
||||
info->Close = Mapper195_Close;
|
||||
CHRRAMSIZE =4096;
|
||||
CHRRAM =(uint8*)FCEU_gmalloc(CHRRAMSIZE);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1);
|
||||
AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR");
|
||||
AddExState(&mask, 1, 0, "EXP0");
|
||||
AddExState(&compare, 1, 0, "EXP1");
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2006 CaH4e3
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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
|
||||
@@ -16,83 +16,24 @@
|
||||
* 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
|
||||
*
|
||||
* Dragon Ball Z 2 - Gekishin Freeza! (C)
|
||||
* Dragon Ball Z Gaiden - Saiya Jin Zetsumetsu Keikaku (C)
|
||||
* San Guo Zhi 2 (C)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 *CHRRAM = NULL;
|
||||
static uint32 CHRRAMSIZE;
|
||||
|
||||
static void M199PW(uint32 A, uint8 V) {
|
||||
setprg8(A, V);
|
||||
setprg8(0xC000, EXPREGS[0]);
|
||||
setprg8(0xE000, EXPREGS[1]);
|
||||
static void Mapper199_CHRWrap(uint32 A, uint8 V) {
|
||||
setchr8(0); /* Unbanked CHR RAM */
|
||||
}
|
||||
|
||||
static void M199CW(uint32 A, uint8 V) {
|
||||
setchr1r((V < 8) ? 0x10 : 0x00, A, V);
|
||||
setchr1r((DRegBuf[0] < 8) ? 0x10 : 0x00, 0x0000, DRegBuf[0]);
|
||||
setchr1r((EXPREGS[2] < 8) ? 0x10 : 0x00, 0x0400, EXPREGS[2]);
|
||||
setchr1r((DRegBuf[1] < 8) ? 0x10 : 0x00, 0x0800, DRegBuf[1]);
|
||||
setchr1r((EXPREGS[3] < 8) ? 0x10 : 0x00, 0x0c00, EXPREGS[3]);
|
||||
}
|
||||
|
||||
static void M199MW(uint8 V) {
|
||||
/* FCEU_printf("%02x\n",V); */
|
||||
switch (V & 3) {
|
||||
case 0: setmirror(MI_V); break;
|
||||
case 1: setmirror(MI_H); break;
|
||||
case 2: setmirror(MI_0); break;
|
||||
case 3: setmirror(MI_1); break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(M199Write) {
|
||||
if ((A == 0x8001) && (MMC3_cmd & 8)) {
|
||||
EXPREGS[MMC3_cmd & 3] = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
} else
|
||||
if (A < 0xC000)
|
||||
MMC3_CMDWrite(A, V);
|
||||
else
|
||||
MMC3_IRQWrite(A, V);
|
||||
}
|
||||
|
||||
static void M199Power(void) {
|
||||
EXPREGS[0] = ~1;
|
||||
EXPREGS[1] = ~0;
|
||||
EXPREGS[2] = 1;
|
||||
EXPREGS[3] = 3;
|
||||
static void Mapper199_Power(void) {
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x8000, 0xFFFF, M199Write);
|
||||
}
|
||||
|
||||
static void M199Close(void) {
|
||||
GenMMC3Close();
|
||||
if (CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
setprg4r(0x10, 0x5000, 2);
|
||||
SetWriteHandler(0x5000, 0x5FFF, CartBW);
|
||||
SetReadHandler(0x5000, 0x5FFF, CartBR);
|
||||
}
|
||||
|
||||
void Mapper199_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 512, 256, 8, info->battery);
|
||||
cwrap = M199CW;
|
||||
pwrap = M199PW;
|
||||
mwrap = M199MW;
|
||||
info->Power = M199Power;
|
||||
info->Close = M199Close;
|
||||
|
||||
CHRRAMSIZE = 8192;
|
||||
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1);
|
||||
AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR");
|
||||
|
||||
AddExState(EXPREGS, 4, 0, "EXPR");
|
||||
GenMMC3_Init(info, 1024, 0, 16, info->battery);
|
||||
cwrap = Mapper199_CHRWrap;
|
||||
info->Power = Mapper199_Power;
|
||||
info->Reset = MMC3RegReset;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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
|
||||
@@ -17,10 +18,17 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* 2022-2-14
|
||||
* - add support for submapper 1, Mortal Kombat (JJ-01) (Ch) [!]
|
||||
* - add mirroring
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 submapper;
|
||||
|
||||
static const uint8 lut[256] = {
|
||||
0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x49, 0x19, 0x09, 0x59, 0x49, 0x19, 0x09,
|
||||
0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x51, 0x41, 0x11, 0x01, 0x51, 0x41, 0x11, 0x01,
|
||||
@@ -41,11 +49,21 @@ static const uint8 lut[256] = {
|
||||
};
|
||||
|
||||
static void M208PW(uint32 A, uint8 V) {
|
||||
setprg32(0x8000, EXPREGS[5]);
|
||||
if (submapper == 1)
|
||||
setprg32(0x8000, DRegBuf[6] >> 2);
|
||||
else
|
||||
setprg32(0x8000, (EXPREGS[5] & 0x1) | ((EXPREGS[5] >> 3) & 0x2));
|
||||
}
|
||||
|
||||
static void M208MW(uint8 V) {
|
||||
if (submapper == 1)
|
||||
setmirror((V & 1) ^ 1);
|
||||
else
|
||||
setmirror(((EXPREGS[5] >> 5) & 1) ^ 1);
|
||||
}
|
||||
|
||||
static DECLFW(M208Write) {
|
||||
EXPREGS[5] = (V & 0x1) | ((V >> 3) & 0x2);
|
||||
EXPREGS[5] = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
}
|
||||
|
||||
@@ -61,7 +79,7 @@ static DECLFR(M208ProtRead) {
|
||||
}
|
||||
|
||||
static void M208Power(void) {
|
||||
EXPREGS[5] = 3;
|
||||
EXPREGS[5] = 0x11;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x4800, 0x4fff, M208Write);
|
||||
SetWriteHandler(0x6800, 0x6fff, M208Write);
|
||||
@@ -73,6 +91,8 @@ static void M208Power(void) {
|
||||
void Mapper208_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 128, 256, 0, 0);
|
||||
pwrap = M208PW;
|
||||
mwrap = M208MW;
|
||||
info->Power = M208Power;
|
||||
AddExState(EXPREGS, 6, 0, "EXPR");
|
||||
submapper = info->submapper;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020 negativeExponent
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -19,7 +19,6 @@
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "../ines.h"
|
||||
|
||||
static void M218Power(void) {
|
||||
setchr8(0);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2011 CaH4e3
|
||||
* Copyright (C) 2019 Libretro Team
|
||||
* Copyright (C) 2020 negativeExponent
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* 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
|
||||
|
||||
87
src/boards/233.c
Normal file
87
src/boards/233.c
Normal file
@@ -0,0 +1,87 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
* Copyright (C) 2009 qeed
|
||||
* Copyright (C) 2019 Libretro Team
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
/* Updated 2019-07-12
|
||||
* Mapper 233 - UNIF 42in1ResetSwitch - reset-based switching
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 latche;
|
||||
static uint8 reset;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &reset, 1, "RST" },
|
||||
{ &latche, 1, "LATC" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
uint8 bank = (latche & 0x1f) | (reset << 5);
|
||||
|
||||
if (!(latche & 0x20))
|
||||
setprg32(0x8000, bank >> 1);
|
||||
else {
|
||||
setprg16(0x8000, bank);
|
||||
setprg16(0xC000, bank);
|
||||
}
|
||||
|
||||
switch ((latche >> 6) & 3) {
|
||||
case 0: setmirror(MI_0); break;
|
||||
case 1: setmirror(MI_V); break;
|
||||
case 2: setmirror(MI_H); break;
|
||||
case 3: setmirror(MI_1); break;
|
||||
}
|
||||
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
static DECLFW(M233Write) {
|
||||
latche = V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M233Power(void) {
|
||||
latche = reset = 0;
|
||||
Sync();
|
||||
SetWriteHandler(0x8000, 0xFFFF, M233Write);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M233Reset(void) {
|
||||
latche = 0;
|
||||
reset ^= 1;
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper233_Init(CartInfo *info) {
|
||||
info->Power = M233Power;
|
||||
info->Reset = M233Reset;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
GameStateRestore = StateRestore;
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
* Copyright (C) 2020 negativeExponent
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* 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
|
||||
@@ -20,28 +20,26 @@
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "../ines.h"
|
||||
|
||||
static uint8 *CHRRAM;
|
||||
static uint32 CHRRAMSIZE;
|
||||
|
||||
static uint16 cmdreg;
|
||||
static uint8 unrom, reg, type, openbus;
|
||||
static uint8 unrom, reg, openbus;
|
||||
|
||||
static uint32 PRGROMSize;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &cmdreg, 2 | FCEUSTATE_RLSB, "CREG" },
|
||||
{ &unrom, 1, "UNRM" },
|
||||
{ ®, 1, "UNRG" },
|
||||
{ &type, 1, "TYPE" },
|
||||
{ &openbus, 1, "OPNB" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
if (type && unrom) {
|
||||
setprg16(0x8000, 0x80 | reg & 7);
|
||||
setprg16(0xC000, 0x80 | 7);
|
||||
if (unrom) {
|
||||
uint8 PRGPageSize = PRGROMSize / 16384;
|
||||
setprg16(0x8000, (PRGPageSize & 0xC0) | (reg & 7));
|
||||
setprg16(0xC000, (PRGPageSize & 0xC0) | 7);
|
||||
setchr8(0);
|
||||
setmirror(MI_V);
|
||||
} else {
|
||||
@@ -50,7 +48,7 @@ static void Sync(void) {
|
||||
setmirror(MI_0);
|
||||
else
|
||||
setmirror(((cmdreg >> 13) & 1) ^ 1);
|
||||
if (bank >= PRGsize[0] / 32768)
|
||||
if (bank >= PRGROMSize / 32768)
|
||||
openbus = 1;
|
||||
else if (cmdreg & 0x800) {
|
||||
setprg16(0x8000, (bank << 1) | ((cmdreg >> 12) & 1));
|
||||
@@ -75,15 +73,11 @@ static DECLFW(M235Write) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M235Close(void) {
|
||||
if (CHRRAM)
|
||||
FCEU_free(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
}
|
||||
|
||||
static void M235Reset(void) {
|
||||
cmdreg = 0;
|
||||
unrom = (unrom + type) & 1;
|
||||
reg = 0;
|
||||
if (PRGROMSize & 0x20000)
|
||||
unrom = (unrom + 1) & 1;
|
||||
Sync();
|
||||
}
|
||||
|
||||
@@ -91,6 +85,7 @@ static void M235Power(void) {
|
||||
SetWriteHandler(0x8000, 0xFFFF, M235Write);
|
||||
SetReadHandler(0x8000, 0xFFFF, M235Read);
|
||||
cmdreg = 0;
|
||||
reg = 0;
|
||||
Sync();
|
||||
}
|
||||
|
||||
@@ -101,22 +96,7 @@ static void M235Restore(int version) {
|
||||
void Mapper235_Init(CartInfo *info) {
|
||||
info->Reset = M235Reset;
|
||||
info->Power = M235Power;
|
||||
info->Close = M235Close;
|
||||
GameStateRestore = M235Restore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
|
||||
/* some nes 2.0 header do can have no chr-ram.
|
||||
* one such cart is 210-in-1 and Contra 4-in-1 (212-in-1,212 Hong Kong,Reset Based)(Unl).nes (0x745A6791)
|
||||
*/
|
||||
if (CHRsize[0] == 0) {
|
||||
CHRRAMSIZE = 8192;
|
||||
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE);
|
||||
SetupCartCHRMapping(0, CHRRAM, CHRRAMSIZE, 1);
|
||||
AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM");
|
||||
}
|
||||
|
||||
type = 0;
|
||||
/* carts with unrom game, reset-based */
|
||||
if ((info->CRC32) == 0x745A6791) /* 210-in-1 and Contra 4-in-1 (212-in-1,212 Hong Kong,Reset Based)(Unl).nes */
|
||||
type = 1;
|
||||
PRGROMSize = info->PRGRomSize;
|
||||
}
|
||||
|
||||
111
src/boards/236.c
Normal file
111
src/boards/236.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2012 CaH4e3
|
||||
*
|
||||
* 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 reg[2];
|
||||
static uint8 dip;
|
||||
static uint8 chrramvariant;
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ reg, 2, "REG " },
|
||||
{ &dip, 1, "DIP " },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
int prg;
|
||||
int chr;
|
||||
if (chrramvariant)
|
||||
{
|
||||
prg = reg[1] &7 | reg[0] <<3;
|
||||
chr = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
prg = reg[1] & 0x0F;
|
||||
chr = reg[0] & 0x0F;
|
||||
}
|
||||
switch (reg[1] >>4 &3)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
setprg16(0x8000, prg);
|
||||
setprg16(0xC000, prg |7);
|
||||
break;
|
||||
case 2:
|
||||
setprg32(0x8000, prg >>1);
|
||||
break;
|
||||
case 3:
|
||||
setprg16(0x8000, prg);
|
||||
setprg16(0xC000, prg);
|
||||
break;
|
||||
}
|
||||
setchr8(chr);
|
||||
setmirror((reg[0] >>5 &1) ^1);
|
||||
}
|
||||
|
||||
static DECLFR(M236Read)
|
||||
{
|
||||
if ((reg[1] >>4 &3) ==1)
|
||||
return CartBR(A &~0xF | dip &0xF);
|
||||
else
|
||||
return CartBR(A);
|
||||
}
|
||||
|
||||
static DECLFW(M236WriteReg)
|
||||
{
|
||||
reg[A >>14 &1] =A &0xFF;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M236Power(void)
|
||||
{
|
||||
dip = 0;
|
||||
reg[0] = 0;
|
||||
reg[1] = 0;
|
||||
Sync();
|
||||
SetWriteHandler(0x8000, 0xFFFF, M236WriteReg);
|
||||
SetReadHandler(0x8000, 0xFFFF, M236Read);
|
||||
}
|
||||
|
||||
static void M236Reset(void)
|
||||
{
|
||||
++dip;
|
||||
/* Soft-reset returns to menu */
|
||||
reg[0] = 0;
|
||||
reg[1] = 0;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper236_Init(CartInfo *info)
|
||||
{
|
||||
info->Power = M236Power;
|
||||
info->Reset = M236Reset;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
GameStateRestore = StateRestore;
|
||||
chrramvariant = info->CHRRomSize == 0;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020 negativeExponent
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -34,9 +34,11 @@ static void M267PW(uint32 A, uint8 V) {
|
||||
}
|
||||
|
||||
static DECLFW(M267Write) {
|
||||
EXPREGS[0] = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
if (!(EXPREGS[0] & 0x80)) {
|
||||
EXPREGS[0] = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static void M267Reset(void) {
|
||||
@@ -47,14 +49,14 @@ static void M267Reset(void) {
|
||||
static void M267Power(void) {
|
||||
EXPREGS[0] = 0;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x6000, 0x6FFF, M267Write);
|
||||
SetWriteHandler(0x6000, 0x7FFF, M267Write);
|
||||
}
|
||||
|
||||
void Mapper267_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 128, 128, 0, 0);
|
||||
GenMMC3_Init(info, 256, 128, 0, 0);
|
||||
cwrap = M267CW;
|
||||
pwrap = M267PW;
|
||||
info->Reset = M267Reset;
|
||||
info->Power = M267Power;
|
||||
AddExState(EXPREGS, 4, 0, "EXPR");
|
||||
AddExState(EXPREGS, 1, 0, "EXPR");
|
||||
}
|
||||
|
||||
157
src/boards/268.c
Normal file
157
src/boards/268.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 *CHRRAM =NULL;
|
||||
static uint8 submapper;
|
||||
|
||||
static void Mapper268_PRGWrap(uint32 A, uint8 V) {
|
||||
int prgMaskMMC3, prgMaskGNROM, prgOffset;
|
||||
|
||||
prgMaskMMC3 =(EXPREGS[3] &0x10? 0x00: 0x0F) /* PRG A13-A16 */
|
||||
|(EXPREGS[0] &0x40? 0x00: 0x10) /* PRG A17 */
|
||||
|(EXPREGS[1] &0x80? 0x00: 0x20) /* PRG A18 */
|
||||
|(EXPREGS[1] &0x40? 0x40: 0x00) /* PRG A19 */
|
||||
|(EXPREGS[1] &0x20? 0x80: 0x00) /* PRG A20 */
|
||||
;
|
||||
switch(submapper &~1) {
|
||||
default: /* Original implementation */
|
||||
prgMaskGNROM =EXPREGS[3] &0x10? (EXPREGS[1] &0x02? 0x03: 0x01): 0x00;
|
||||
prgOffset =EXPREGS[3] &0x00E
|
||||
|EXPREGS[0] <<4 &0x070
|
||||
|EXPREGS[1] <<3 &0x080
|
||||
|EXPREGS[1] <<6 &0x300
|
||||
|EXPREGS[0] <<6 &0xC00;
|
||||
break;
|
||||
case 2: /* Later revision with different arrangement of register 1 */
|
||||
prgMaskGNROM =EXPREGS[3] &0x10? (EXPREGS[1] &0x10? 0x01: 0x03): 0x00;
|
||||
prgOffset =EXPREGS[3] &0x00E
|
||||
|EXPREGS[0] <<4 &0x070
|
||||
|EXPREGS[1] <<4 &0x080
|
||||
|EXPREGS[1] <<6 &0x100
|
||||
|EXPREGS[1] <<8 &0x200
|
||||
|EXPREGS[0] <<6 &0xC00;
|
||||
break;
|
||||
case 4: /* LD622D: PRG A20-21 moved to register 0 */
|
||||
prgMaskGNROM =EXPREGS[3] &0x10? (EXPREGS[1] &0x02? 0x03: 0x01): 0x00;
|
||||
prgOffset =EXPREGS[3] &0x00E
|
||||
|EXPREGS[0] <<4 &0x070
|
||||
|EXPREGS[0] <<3 &0x180;
|
||||
break;
|
||||
case 6: /* J-852C: CHR A17 selects between two PRG chips */
|
||||
prgMaskGNROM =EXPREGS[3] &0x10? (EXPREGS[1] &0x02? 0x03: 0x01): 0x00;
|
||||
prgOffset =EXPREGS[3] &0x00E
|
||||
|EXPREGS[0] <<4 &0x070
|
||||
|EXPREGS[1] <<3 &0x080
|
||||
|EXPREGS[1] <<6 &0x300
|
||||
|EXPREGS[0] <<6 &0xC00;
|
||||
prgOffset &=ROM_size -1;
|
||||
if (EXPREGS[0] &0x80? !!(EXPREGS[0] &0x08): !!(DRegBuf[0] &0x80)) prgOffset |=ROM_size;
|
||||
break;
|
||||
}
|
||||
prgOffset &=~(prgMaskMMC3 | prgMaskGNROM);
|
||||
setprg8(A, V &prgMaskMMC3 | prgOffset | A >>13 &prgMaskGNROM);
|
||||
|
||||
/* CHR-RAM write protect on submapper 8/9) */
|
||||
SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], (submapper &~1) ==8 && EXPREGS[0] &0x10? 0: 1);
|
||||
}
|
||||
|
||||
static void Mapper268_CHRWrap(uint32 A, uint8 V) {
|
||||
int chrMaskMMC3, chrMaskGNROM, chrOffset;
|
||||
|
||||
chrMaskMMC3 =EXPREGS[3] &0x10? 0x00: EXPREGS[0] &0x80? 0x7F: 0xFF;
|
||||
chrMaskGNROM =EXPREGS[3] &0x10? 0x07: 0x00;
|
||||
chrOffset =EXPREGS[0] <<4 &0x380 | EXPREGS[2] <<3 &0x078;
|
||||
chrOffset &=~(chrMaskMMC3 | chrMaskGNROM);
|
||||
|
||||
setchr1r(CHRRAM && EXPREGS[4] &0x01 && (V &0xFE) ==(EXPREGS[4] &0xFE)? 0x10: 0x00, A, V &chrMaskMMC3 | chrOffset | A >>10 &chrMaskGNROM);
|
||||
}
|
||||
|
||||
static DECLFR(Mapper268_ReadWRAM) {
|
||||
return A001B &0xA0? CartBR(A): X.DB;
|
||||
}
|
||||
|
||||
static DECLFW(Mapper268_WriteWRAM) {
|
||||
if (A001B &0x80 && ~A001B &0x40 || A001B &0x20) CartBW(A, V);
|
||||
}
|
||||
|
||||
static DECLFW(Mapper268_WriteReg) {
|
||||
int index =A &7;
|
||||
if (~submapper &1) Mapper268_WriteWRAM(A, V);
|
||||
if (~EXPREGS[3] &0x80 || index ==2) {
|
||||
if (index ==2) {
|
||||
if (EXPREGS[2] &0x80) V =V &0x0F | EXPREGS[2] &~0x0F;
|
||||
V &=~EXPREGS[2] >>3 &0xE |0xF1;
|
||||
}
|
||||
EXPREGS[index] =V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static void Mapper268_Reset(void) {
|
||||
EXPREGS[0] =EXPREGS[1] =EXPREGS[2] =EXPREGS[3] =EXPREGS[4] =EXPREGS[5] =0;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void Mapper268_Power(void) {
|
||||
EXPREGS[0] =EXPREGS[1] =EXPREGS[2] =EXPREGS[3] =EXPREGS[4] =EXPREGS[5] =0;
|
||||
GenMMC3Power();
|
||||
SetReadHandler(0x6000, 0x7FFF, Mapper268_ReadWRAM);
|
||||
if (submapper &1) {
|
||||
SetWriteHandler(0x5000, 0x5FFF, Mapper268_WriteReg);
|
||||
SetWriteHandler(0x6000, 0x7FFF, Mapper268_WriteWRAM);
|
||||
} else
|
||||
SetWriteHandler(0x6000, 0x7FFF, Mapper268_WriteReg);
|
||||
}
|
||||
|
||||
static void Mapper268_close(void) {
|
||||
if (CHRRAM) FCEU_gfree(CHRRAM);
|
||||
CHRRAM =NULL;
|
||||
GenMMC3Close();
|
||||
}
|
||||
|
||||
void Mapper268_Init(CartInfo *info) {
|
||||
submapper = info->submapper;
|
||||
GenMMC3_Init(info, 512, 256, (info->PRGRamSize +info->PRGRamSaveSize) >>10, info->battery);
|
||||
cwrap = Mapper268_CHRWrap;
|
||||
pwrap = Mapper268_PRGWrap;
|
||||
info->Power = Mapper268_Power;
|
||||
info->Reset = Mapper268_Reset;
|
||||
info->Close = Mapper268_close;
|
||||
AddExState(EXPREGS, 8, 0, "EXPR");
|
||||
|
||||
if (info->CHRRomSize && info->CHRRamSize + info->CHRRamSaveSize) {
|
||||
CHRRAM =(uint8 *)FCEU_gmalloc(info->CHRRamSize + info->CHRRamSaveSize);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, info->CHRRamSize + info->CHRRamSaveSize, 1);
|
||||
AddExState(CHRRAM, info->CHRRamSize + info->CHRRamSaveSize, 0, "CRAM");
|
||||
}
|
||||
}
|
||||
|
||||
void COOLBOY_Init(CartInfo *info) {
|
||||
info->submapper =0;
|
||||
Mapper268_Init(info);
|
||||
}
|
||||
|
||||
void MINDKIDS_Init(CartInfo *info) {
|
||||
info->submapper =1;
|
||||
Mapper268_Init(info);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020 negativeExponent
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -80,7 +80,7 @@ static uint8 unscrambleCHR(uint8 data) {
|
||||
}
|
||||
|
||||
void Mapper269_Init(CartInfo *info) {
|
||||
int i;
|
||||
uint32 i;
|
||||
GenMMC3_Init(info, 512, 0, 8, 0);
|
||||
cwrap = M269CW;
|
||||
pwrap = M269PW;
|
||||
|
||||
179
src/boards/272.c
Normal file
179
src/boards/272.c
Normal file
@@ -0,0 +1,179 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* NES 2.0 Mapper 272 is used for a bootleg implementation of
|
||||
* 悪魔城 Special: ぼくDracula君 (Akumajō Special: Boku Dracula-kun).
|
||||
*
|
||||
* as implemented from
|
||||
* https://forums.nesdev.org/viewtopic.php?f=9&t=15302&start=60#p205862
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 prg[2];
|
||||
static uint8 chr[8];
|
||||
static uint8 mirr;
|
||||
static uint8 pal_mirr;
|
||||
static uint8 last_pa13;
|
||||
static uint8 IRQCount;
|
||||
static uint8 IRQa;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ prg, 2, "PRG" },
|
||||
{ chr, 8, "CHR" },
|
||||
{ &mirr, 1, "MIRR" },
|
||||
{ &last_pa13, 1, "PA13" },
|
||||
{ &IRQCount, 1, "CNTR" },
|
||||
{ &pal_mirr, 1, "PALM" },
|
||||
{ &IRQa, 1, "CCLK" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/* shifts bit from position `bit` into position `pos` of expression `exp` */
|
||||
#define shi(exp, bit, pos) \
|
||||
((((exp) & (1 << (bit))) >> (bit)) << (pos))
|
||||
|
||||
static uint32 vrc_addr_mix(uint32 A) {
|
||||
/* this game wires A0 to VRC_A0 and A1 to VRC_A1 */
|
||||
return (A & 0xf000) | shi(A, 0, 0) | shi(A, 1, 1);
|
||||
}
|
||||
|
||||
static void Sync(void) {
|
||||
uint8 i;
|
||||
setprg8(0x8000, prg[0]);
|
||||
setprg8(0xa000, prg[1]);
|
||||
setprg16(0xc000, -1);
|
||||
for (i = 0; i < 8; ++i)
|
||||
setchr1(0x400 * i, chr[i]);
|
||||
switch (pal_mirr) {
|
||||
case 2: setmirror(MI_0); break;
|
||||
case 3: setmirror(MI_1); break;
|
||||
default:
|
||||
switch (mirr) {
|
||||
case 0: setmirror(MI_V); break;
|
||||
case 1: setmirror(MI_H); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(M272Write) {
|
||||
/* writes to VRC chip */
|
||||
switch (vrc_addr_mix(A)) {
|
||||
case 0x8000:
|
||||
case 0x8001:
|
||||
case 0x8002:
|
||||
case 0x8003:
|
||||
prg[0] = V;
|
||||
break;
|
||||
case 0x9000:
|
||||
case 0x9001:
|
||||
case 0x9002:
|
||||
case 0x9003:
|
||||
mirr = V & 1;
|
||||
break;
|
||||
case 0xA000:
|
||||
case 0xA001:
|
||||
case 0xA002:
|
||||
case 0xA003:
|
||||
prg[1] = V;
|
||||
break;
|
||||
case 0xb000: chr[0] = (chr[0] & 0xF0) | (V & 0xF); break;
|
||||
case 0xb001: chr[0] = (chr[0] & 0xF) | ((V & 0xF) << 4); break;
|
||||
case 0xb002: chr[1] = (chr[1] & 0xF0) | (V & 0xF); break;
|
||||
case 0xb003: chr[1] = (chr[1] & 0xF) | ((V & 0xF) << 4); break;
|
||||
case 0xc000: chr[2] = (chr[2] & 0xF0) | (V & 0xF); break;
|
||||
case 0xc001: chr[2] = (chr[2] & 0xF) | ((V & 0xF) << 4); break;
|
||||
case 0xc002: chr[3] = (chr[3] & 0xF0) | (V & 0xF); break;
|
||||
case 0xc003: chr[3] = (chr[3] & 0xF) | ((V & 0xF) << 4); break;
|
||||
case 0xd000: chr[4] = (chr[4] & 0xF0) | (V & 0xF); break;
|
||||
case 0xd001: chr[4] = (chr[4] & 0xF) | ((V & 0xF) << 4); break;
|
||||
case 0xd002: chr[5] = (chr[5] & 0xF0) | (V & 0xF); break;
|
||||
case 0xd003: chr[5] = (chr[5] & 0xF) | ((V & 0xF) << 4); break;
|
||||
case 0xe000: chr[6] = (chr[6] & 0xF0) | (V & 0xF); break;
|
||||
case 0xe001: chr[6] = (chr[6] & 0xF) | ((V & 0xF) << 4); break;
|
||||
case 0xe002: chr[7] = (chr[7] & 0xF0) | (V & 0xF); break;
|
||||
case 0xe003: chr[7] = (chr[7] & 0xF) | ((V & 0xF) << 4); break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* writes to PAL chip */
|
||||
switch (A & 0xC00C) {
|
||||
case 0x8004: pal_mirr = V & 3; break;
|
||||
case 0x800c: X6502_IRQBegin(FCEU_IQEXT); break;
|
||||
case 0xc004: X6502_IRQEnd(FCEU_IQEXT); break;
|
||||
case 0xc008: IRQa = 1; break;
|
||||
case 0xc00c: IRQa = 0; IRQCount = 0; X6502_IRQEnd(FCEU_IQEXT); break;
|
||||
}
|
||||
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M272Power(void) {
|
||||
prg[0] = prg[1] = 0;
|
||||
chr[0] = chr[1] = chr[2] = chr[3] = 0;
|
||||
chr[4] = chr[5] = chr[6] = chr[7] = 0;
|
||||
mirr = pal_mirr = 0;
|
||||
last_pa13 = 0;
|
||||
IRQCount = 0;
|
||||
IRQa = 0;
|
||||
Sync();
|
||||
SetWriteHandler(0x8000, 0xFFFF, M272Write);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
}
|
||||
|
||||
static void M272Hook(uint32 A) {
|
||||
uint8 pa13 = (A >> 13) & 1;
|
||||
if ((last_pa13 == 1) && (pa13 == 0)) {
|
||||
if (IRQa) {
|
||||
IRQCount++;
|
||||
if (IRQCount == 84) {
|
||||
IRQCount = 0;
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
last_pa13 = pa13;
|
||||
}
|
||||
|
||||
static void M272Reset(void) {
|
||||
prg[0] = prg[1] = 0;
|
||||
chr[0] = chr[1] = chr[2] = chr[3] = 0;
|
||||
chr[4] = chr[5] = chr[6] = chr[7] = 0;
|
||||
mirr = pal_mirr = 0;
|
||||
last_pa13 = 0;
|
||||
IRQCount = 0;
|
||||
IRQa = 0;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper272_Init(CartInfo *info) {
|
||||
info->Power = M272Power;
|
||||
info->Reset = M272Reset;
|
||||
PPU_hook = M272Hook;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
@@ -29,25 +29,25 @@ static SFORMAT StateRegs[] =
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setprg8(0x6000, 31);
|
||||
setprg8(0x6000, (ROM_size == 17) ? 32 : 31); /* FIXME: Verify these */
|
||||
setprg32(0x8000, reg);
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
static DECLFW(BMCGS2013Write) {
|
||||
static DECLFW(M283Write) {
|
||||
reg = V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void BMCGS2013Power(void) {
|
||||
static void M283Power(void) {
|
||||
reg = 0;
|
||||
Sync();
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, BMCGS2013Write);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M283Write);
|
||||
}
|
||||
|
||||
static void BMCGS2013Reset(void) {
|
||||
static void M283Reset(void) {
|
||||
reg = 0;
|
||||
}
|
||||
|
||||
@@ -55,9 +55,9 @@ static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void BMCGS2013_Init(CartInfo *info) {
|
||||
info->Reset = BMCGS2013Reset;
|
||||
info->Power = BMCGS2013Power;
|
||||
void Mapper283_Init(CartInfo *info) {
|
||||
info->Reset = M283Reset;
|
||||
info->Power = M283Power;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
59
src/boards/291.c
Normal file
59
src/boards/291.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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"
|
||||
#include "mmc3.h"
|
||||
|
||||
static void M291CW(uint32 A, uint8 V) {
|
||||
setchr1(A, V | ((EXPREGS[0] << 2) & 0x100));
|
||||
}
|
||||
|
||||
static void M291PW(uint32 A, uint8 V) {
|
||||
if (EXPREGS[0] & 0x20)
|
||||
setprg32(0x8000, ((EXPREGS[0] >> 1) & 3) | ((EXPREGS[0] >> 4) & 4));
|
||||
else
|
||||
setprg8(A, (V & 0x0F) | ((EXPREGS[0] >> 2) & 0x10));
|
||||
}
|
||||
|
||||
static DECLFW(M291Write) {
|
||||
EXPREGS[0] = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void M291Reset(void) {
|
||||
EXPREGS[0] = 0;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void M291Power(void) {
|
||||
EXPREGS[0] = 0;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x6000, 0x7FFF, M291Write);
|
||||
}
|
||||
|
||||
void Mapper291_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 256, 512, 0, 0);
|
||||
cwrap = M291CW;
|
||||
pwrap = M291PW;
|
||||
info->Power = M291Power;
|
||||
info->Reset = M291Reset;
|
||||
AddExState(EXPREGS, 1, 0, "EXPR");
|
||||
}
|
||||
91
src/boards/293.c
Normal file
91
src/boards/293.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* NewStar 12-in-1 and 76-in-1
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 regs[2];
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ regs, 2, "REGS" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
uint8 mode = ((regs[0] >> 2) & 2) | ((regs[1] >> 6) & 1);
|
||||
uint8 bank = ((regs[1] << 5) & 0x20) | ((regs[1] >> 1) & 0x18);
|
||||
uint8 block = (regs[0] & 7);
|
||||
switch (mode) {
|
||||
case 0: /* UNROM */
|
||||
setprg16(0x8000, bank | block);
|
||||
setprg16(0xC000, bank | 7);
|
||||
break;
|
||||
case 1:
|
||||
setprg16(0x8000, bank | block & 0xFE);
|
||||
setprg16(0xC000, bank | 7);
|
||||
break;
|
||||
case 2: /* NROM-128 */
|
||||
setprg16(0x8000, bank | block);
|
||||
setprg16(0xC000, bank | block);
|
||||
break;
|
||||
case 3: /* NROM-256 */
|
||||
setprg32(0x8000, (bank | block) >> 1);
|
||||
break;
|
||||
}
|
||||
setchr8(0);
|
||||
setmirror(((regs[1] >> 7) & 1) ^ 1);
|
||||
}
|
||||
|
||||
static DECLFW(M293Write1) {
|
||||
regs[0] = V;
|
||||
regs[1] = V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFW(M293Write2) {
|
||||
regs[1] = V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFW(M293Write3) {
|
||||
regs[0] = V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M293Power(void) {
|
||||
regs[0] = regs[1] = 0;
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0x9FFF, M293Write1);
|
||||
SetWriteHandler(0xA000, 0xBFFF, M293Write2);
|
||||
SetWriteHandler(0xC000, 0xDFFF, M293Write3);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
/* BMC 12-in-1/76-in-1 (NewStar) (Unl) */
|
||||
void Mapper293_Init(CartInfo *info) {
|
||||
info->Power = M293Power;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
61
src/boards/294.c
Normal file
61
src/boards/294.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022 NewRisingSun
|
||||
*
|
||||
* 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 latch;
|
||||
|
||||
static void Mapper294_sync (void) {
|
||||
setprg16(0x8000, latch);
|
||||
setprg16(0xC000, latch |7);
|
||||
setchr8(0);
|
||||
setmirror(latch &0x80? MI_H: MI_V);
|
||||
}
|
||||
|
||||
static DECLFW(Mapper294_writeInnerBank) {
|
||||
latch =latch &~7 | V&7;
|
||||
Mapper294_sync();
|
||||
}
|
||||
|
||||
static DECLFW(Mapper294_writeOuterBank) {
|
||||
if (A &0x100) {
|
||||
latch =latch &7 | V <<3;
|
||||
Mapper294_sync();
|
||||
}
|
||||
}
|
||||
|
||||
static void Mapper294_reset(void) {
|
||||
latch =0;
|
||||
Mapper294_sync();
|
||||
}
|
||||
|
||||
static void Mapper294_power(void) {
|
||||
Mapper294_reset();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, Mapper294_writeInnerBank);
|
||||
SetWriteHandler(0x4020, 0x7FFF, Mapper294_writeOuterBank);
|
||||
}
|
||||
|
||||
void Mapper294_Init(CartInfo *info) {
|
||||
info->Power = Mapper294_power;
|
||||
info->Reset = Mapper294_reset;
|
||||
AddExState(&latch, 1, 0, "LATC");
|
||||
}
|
||||
88
src/boards/310.c
Normal file
88
src/boards/310.c
Normal file
@@ -0,0 +1,88 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022 NewRisingSun
|
||||
*
|
||||
* 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 regData[2];
|
||||
static uint8 regAddr;
|
||||
|
||||
static SFORMAT K1053_state[] =
|
||||
{
|
||||
{ regData, 2, "REGD" },
|
||||
{®Addr, 1, "REGA" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void K1053_sync (void) {
|
||||
int prg =regData[0] &0x3F | regAddr <<4 &~0x3F;
|
||||
int chrWritable;
|
||||
switch(regAddr &3) {
|
||||
case 0: setprg32(0x8000, prg >>1);
|
||||
chrWritable =0;
|
||||
break;
|
||||
case 1: setprg16(0x8000, prg);
|
||||
setprg16(0xC000, prg |7);
|
||||
chrWritable =1;
|
||||
break;
|
||||
case 2: prg =prg <<1 | regData[0] >>7;
|
||||
setprg8(0x8000, prg);
|
||||
setprg8(0xA000, prg);
|
||||
setprg8(0xC000, prg);
|
||||
setprg8(0xE000, prg);
|
||||
chrWritable =1;
|
||||
break;
|
||||
case 3: setprg16(0x8000, prg);
|
||||
setprg16(0xC000, prg);
|
||||
chrWritable =0;
|
||||
break;
|
||||
}
|
||||
SetupCartCHRMapping(0, CHRptr[0], 0x8000, chrWritable);
|
||||
setchr8(regData[1]);
|
||||
setmirror(regData[0] &0x40? MI_H: MI_V);
|
||||
}
|
||||
|
||||
static void K1053_restore(int version) {
|
||||
K1053_sync();
|
||||
}
|
||||
|
||||
static DECLFW(K1053_write) {
|
||||
regData[A >>14 &1] =V;
|
||||
if (A &0x4000) regAddr=A &0xFF;
|
||||
K1053_sync();
|
||||
}
|
||||
|
||||
static void K1053_reset(void) {
|
||||
regData[0] =regData[1] =regAddr =0;
|
||||
K1053_sync();
|
||||
}
|
||||
|
||||
static void K1053_power(void) {
|
||||
K1053_reset();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, K1053_write);
|
||||
}
|
||||
|
||||
void Mapper310_Init(CartInfo *info) {
|
||||
info->Power = K1053_power;
|
||||
info->Reset = K1053_reset;
|
||||
GameStateRestore = K1053_restore;
|
||||
AddExState(&K1053_state, ~0, 0, 0);
|
||||
}
|
||||
86
src/boards/319.c
Normal file
86
src/boards/319.c
Normal file
@@ -0,0 +1,86 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* 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 reg[2];
|
||||
static uint8 latch;
|
||||
static uint8 pad;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ reg, 2, "REG" },
|
||||
{ &latch, 1, "LATC" },
|
||||
{ &pad, 1, "PAD" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void M319Sync (void) {
|
||||
if (reg[1] &0x40)
|
||||
setprg32(0x8000, reg[1] >>3 &3);
|
||||
else
|
||||
{
|
||||
setprg16(0x8000, reg[1] >>2 &6 | reg[1] >>5 &1);
|
||||
setprg16(0xC000, reg[1] >>2 &6 | reg[1] >>5 &1);
|
||||
}
|
||||
setchr8(reg[0] >>4 &~(reg[0] <<2 &4) | latch <<2 &(reg[0] <<2 &4));
|
||||
setmirror(reg[1] >>7);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
M319Sync();
|
||||
}
|
||||
|
||||
static DECLFR(M319ReadPad) {
|
||||
return pad;
|
||||
}
|
||||
|
||||
static DECLFW(M319WriteReg) {
|
||||
reg[A >>2 &1] =V;
|
||||
M319Sync();
|
||||
}
|
||||
|
||||
static DECLFW(M319WriteLatch) {
|
||||
latch =V;
|
||||
M319Sync();
|
||||
}
|
||||
|
||||
static void M319Reset(void) {
|
||||
reg[0] =reg[1] =latch =0;
|
||||
pad ^=0x40;
|
||||
M319Sync();
|
||||
}
|
||||
|
||||
static void M319Power(void) {
|
||||
reg[0] =reg[1] =latch =pad =0;
|
||||
M319Sync();
|
||||
SetReadHandler(0x5000, 0x5FFF, M319ReadPad);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, M319WriteReg);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M319WriteLatch);
|
||||
}
|
||||
|
||||
void Mapper319_Init(CartInfo *info) {
|
||||
info->Power = M319Power;
|
||||
info->Reset = M319Reset;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
98
src/boards/326.c
Normal file
98
src/boards/326.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* NES 2.0 Mapper 326 is used for a bootleg version of Contra/Gryzor.
|
||||
* as implemented from
|
||||
* http://forums.nesdev.org/viewtopic.php?f=9&t=17352&p=218722#p218722
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 PRG[3], CHR[8], NTAPage[4];
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ PRG, 3, "PRG" },
|
||||
{ CHR, 8, "CHR" },
|
||||
{ NTAPage, 4, "NT" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void SyncPRG(void) {
|
||||
setprg8(0x8000, PRG[0]);
|
||||
setprg8(0xA000, PRG[1]);
|
||||
setprg8(0xC000, PRG[2]);
|
||||
setprg8(0xE000, ~0);
|
||||
}
|
||||
|
||||
static void DoCHR(int x, uint8 V) {
|
||||
CHR[x] = V;
|
||||
setchr1(x << 10, V);
|
||||
}
|
||||
|
||||
static void FixCHR(void) {
|
||||
int x;
|
||||
for (x = 0; x < 8; x++)
|
||||
DoCHR(x, CHR[x]);
|
||||
}
|
||||
|
||||
static void FASTAPASS(2) DoNTARAM(int w, uint8 V) {
|
||||
NTAPage[w] = V;
|
||||
setntamem(NTARAM + ((V & 1) << 10), 1, w);
|
||||
}
|
||||
|
||||
static void FixNTAR(void) {
|
||||
int x;
|
||||
for (x = 0; x < 4; x++)
|
||||
DoNTARAM(x, NTAPage[x]);
|
||||
}
|
||||
|
||||
static DECLFW(M326Write) {
|
||||
switch (A & 0xE010) {
|
||||
case 0x8000: PRG[0] = V; SyncPRG(); break;
|
||||
case 0xA000: PRG[1] = V; SyncPRG(); break;
|
||||
case 0xC000: PRG[2] = V; SyncPRG(); break;
|
||||
}
|
||||
|
||||
A &= 0x801F;
|
||||
if ((A >= 0x8010) && (A <= 0x8017))
|
||||
DoCHR(A - 0x8010, V);
|
||||
else if ((A >= 0x8018) && (A <= 0x801B))
|
||||
DoNTARAM(A - 0x8018, V);
|
||||
}
|
||||
|
||||
static void M326Power(void) {
|
||||
SyncPRG();
|
||||
FixCHR();
|
||||
FixNTAR();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M326Write);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
SyncPRG();
|
||||
FixCHR();
|
||||
FixNTAR();
|
||||
}
|
||||
|
||||
void Mapper326_Init(CartInfo *info) {
|
||||
info->Power = M326Power;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
137
src/boards/330.c
Normal file
137
src/boards/330.c
Normal file
@@ -0,0 +1,137 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* NES 2.0 Mapper 330 is used for a bootleg version of Contra/Gryzor.
|
||||
* as implemented from
|
||||
* http://forums.nesdev.org/viewtopic.php?f=9&t=17352&p=218722#p218722
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 *WRAM;
|
||||
|
||||
static uint8 PRG[3], CHR[8], NTAPage[4];
|
||||
static uint8 IRQa;
|
||||
static uint16 IRQCount;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ PRG, 3, "PRG" },
|
||||
{ CHR, 8, "CHR" },
|
||||
{ NTAPage, 4, "NT" },
|
||||
{ &IRQa, 1, "IRQA" },
|
||||
{ &IRQCount, 2, "IRQC" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void SyncPRG(void) {
|
||||
setprg8(0x8000, PRG[0]);
|
||||
setprg8(0xA000, PRG[1]);
|
||||
setprg8(0xC000, PRG[2]);
|
||||
setprg8(0xE000, ~0);
|
||||
}
|
||||
|
||||
static void DoCHR(int x, uint8 V) {
|
||||
CHR[x] = V;
|
||||
setchr1(x << 10, V);
|
||||
}
|
||||
|
||||
static void FixCHR(void) {
|
||||
int x;
|
||||
for (x = 0; x < 8; x++)
|
||||
DoCHR(x, CHR[x]);
|
||||
}
|
||||
|
||||
static void FASTAPASS(2) DoNTARAM(int w, uint8 V) {
|
||||
NTAPage[w] = V;
|
||||
setntamem(NTARAM + ((V & 1) << 10), 1, w);
|
||||
}
|
||||
|
||||
static void FixNTAR(void) {
|
||||
int x;
|
||||
for (x = 0; x < 4; x++)
|
||||
DoNTARAM(x, NTAPage[x]);
|
||||
}
|
||||
|
||||
static DECLFW(M330Write) {
|
||||
if (!(A & 0x400)) {
|
||||
if (A >= 0x8000 && A <= 0xB800)
|
||||
DoCHR((A - 0x8000) >> 11, V);
|
||||
else if (A >= 0xC000 && A <= 0xD800)
|
||||
DoNTARAM((A - 0xC000) >> 11, V);
|
||||
else if (A >= 0xE000 && A <= 0xF000) {
|
||||
PRG[(A - 0xE000) >> 11] = V;
|
||||
SyncPRG();
|
||||
}
|
||||
} else if ((A < 0xC000) && !(A & 0x4000)) {
|
||||
if (A & 0x2000) {
|
||||
IRQCount &= 0x00FF;
|
||||
IRQCount |= (V & 0x7F) << 8;
|
||||
IRQa = V & 0x80;
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
} else {
|
||||
IRQCount &= 0xFF00;
|
||||
IRQCount |= V;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void M330Power(void) {
|
||||
int i;
|
||||
for (i = 0; i < 4; i++)
|
||||
PRG[i] = i;
|
||||
for (i = 0; i < 8; i++)
|
||||
CHR[i] = i;
|
||||
for (i = 0; i < 4; i++)
|
||||
NTAPage[i] = ~0;
|
||||
IRQa = 0;
|
||||
IRQCount = 0;
|
||||
SyncPRG();
|
||||
FixCHR();
|
||||
FixNTAR();
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M330Write);
|
||||
}
|
||||
|
||||
static void FP_FASTAPASS(1) M330IRQHook(int a) {
|
||||
if (IRQa) {
|
||||
IRQCount += a;
|
||||
if (IRQCount > 0x7FFF) {
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
IRQa = 0;
|
||||
IRQCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
SyncPRG();
|
||||
FixCHR();
|
||||
FixNTAR();
|
||||
}
|
||||
|
||||
void Mapper330_Init(CartInfo *info) {
|
||||
info->Power = M330Power;
|
||||
MapIRQHook = M330IRQHook;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
WRAM = (uint8 *)FCEU_gmalloc(8192);
|
||||
SetupCartPRGMapping(0x10, WRAM, 8192, 1);
|
||||
AddExState(WRAM, 8192, 0, "WRAM");
|
||||
}
|
||||
65
src/boards/334.c
Normal file
65
src/boards/334.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* 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"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 dipswitch;
|
||||
|
||||
static void M334PW(uint32 A, uint8 V) {
|
||||
setprg32(0x8000, EXPREGS[0] >> 1);
|
||||
}
|
||||
|
||||
static DECLFW(M334Write) {
|
||||
if (!(A & 1)) {
|
||||
EXPREGS[0] = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(M334Read) {
|
||||
if (A & 2)
|
||||
return ((X.DB & 0xFE) | (dipswitch & 1));
|
||||
return X.DB;
|
||||
}
|
||||
|
||||
static void M334Reset(void) {
|
||||
dipswitch++;
|
||||
EXPREGS[0] = 0;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void M334Power(void) {
|
||||
dipswitch = 0;
|
||||
EXPREGS[0] = 0;
|
||||
GenMMC3Power();
|
||||
SetReadHandler(0x6000, 0x7FFF, M334Read);
|
||||
SetWriteHandler(0x6000, 0x7FFF, M334Write);
|
||||
}
|
||||
|
||||
void Mapper334_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 32, 32, 0, 0);
|
||||
pwrap = M334PW;
|
||||
info->Power = M334Power;
|
||||
info->Reset = M334Reset;
|
||||
AddExState(EXPREGS, 1, 0, "EXPR");
|
||||
}
|
||||
338
src/boards/351.c
Normal file
338
src/boards/351.c
Normal file
@@ -0,0 +1,338 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022 NewRisingSun
|
||||
*
|
||||
* 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 reg[4], dip;
|
||||
static uint8 MMC1_reg[4], MMC1_shift, MMC1_count, MMC1_filter;
|
||||
static uint8 MMC3_reg[8], MMC3_index, MMC3_mirroring, MMC3_wram, MMC3_reload, MMC3_count, MMC3_irq;
|
||||
static uint8 VRC4_prg[2];
|
||||
static uint8 VRC4_mirroring;
|
||||
static uint8 VRC4_misc;
|
||||
static uint16 VRC4_chr[8];
|
||||
static uint8 VRCIRQ_latch;
|
||||
static uint8 VRCIRQ_mode;
|
||||
static uint8 VRCIRQ_count;
|
||||
static signed short int VRCIRQ_cycles;
|
||||
static uint8 *CHRRAM =NULL;
|
||||
static uint8 *PRGCHR =NULL;
|
||||
|
||||
static SFORMAT stateRegs[] = {
|
||||
{ reg, 4, "REGS" },
|
||||
{ &dip, 1, "DIPS" },
|
||||
{ MMC1_reg, 4, "MMC1" },
|
||||
{ &MMC1_shift, 1, "M1SH" },
|
||||
{ &MMC1_count, 1, "M1CN" },
|
||||
{ &MMC1_filter, 1, "M1FI" },
|
||||
{ MMC3_reg, 1, "MMC3" },
|
||||
{ &MMC3_index, 1, "M3IX" },
|
||||
{ &MMC3_mirroring, 1, "M3MI" },
|
||||
{ &MMC3_wram, 1, "M3WR" },
|
||||
{ &MMC3_reload, 1, "M3RL" },
|
||||
{ &MMC3_count, 1, "M3CN" },
|
||||
{ &MMC3_irq, 1, "M3IQ" },
|
||||
{ VRC4_prg, 2, "V4PR" },
|
||||
{ &VRC4_mirroring, 1, "V4MI" },
|
||||
{ &VRC4_misc, 1, "V4MS" },
|
||||
{ VRC4_chr, 16, "V4CH" },
|
||||
{ &VRCIRQ_latch, 1, "VILA" },
|
||||
{ &VRCIRQ_mode, 1, "VIMO" },
|
||||
{ &VRCIRQ_count, 1, "VICO" },
|
||||
{ &VRCIRQ_cycles, 2, "VICY" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
||||
static void sync () {
|
||||
int chrAND;
|
||||
int chrOR;
|
||||
int prgAND =reg[2] &0x04? 0x0F: 0x1F;
|
||||
int prgOR =reg[1] >>1;
|
||||
int chip =reg[2] &0x01 && CHRRAM? 0x10: 0x00;
|
||||
|
||||
if (reg[2] &0x10) { /* NROM mode */
|
||||
if (reg[2] &0x08) { /* NROM-64 */
|
||||
setprg8r(chip, 0x8000, prgOR);
|
||||
setprg8r(chip, 0xA000, prgOR);
|
||||
setprg8r(chip, 0xC000, prgOR);
|
||||
setprg8r(chip, 0xE000, prgOR);
|
||||
} else
|
||||
if (reg[2] &0x04) { /* NROM-128 */
|
||||
setprg16r(chip, 0x8000, prgOR >>1);
|
||||
setprg16r(chip, 0xC000, prgOR >>1);
|
||||
} else /* NROM-256 */
|
||||
setprg32r(chip, 0x8000, prgOR >>2);
|
||||
} else
|
||||
if (~reg[0] &0x02) { /* MMC3 mode */
|
||||
setprg8r(chip, 0x8000 ^(MMC3_index <<8 &0x4000), MMC3_reg[6] &prgAND | prgOR &~prgAND);
|
||||
setprg8r(chip, 0xA000, MMC3_reg[7] &prgAND | prgOR &~prgAND);
|
||||
setprg8r(chip, 0xC000 ^(MMC3_index <<8 &0x4000), 0xFE &prgAND | prgOR &~prgAND);
|
||||
setprg8r(chip, 0xE000, 0xFF &prgAND | prgOR &~prgAND);
|
||||
} else
|
||||
if (reg[0] &0x01) { /* VRC4 mode */
|
||||
setprg8r(chip, 0x8000 ^(VRC4_misc <<13 &0x4000), VRC4_prg[0] &prgAND | prgOR &~prgAND);
|
||||
setprg8r(chip, 0xA000, VRC4_prg[1] &prgAND | prgOR &~prgAND);
|
||||
setprg8r(chip, 0xC000 ^(VRC4_misc <<13 &0x4000), 0xFE &prgAND | prgOR &~prgAND);
|
||||
setprg8r(chip, 0xE000, 0xFF &prgAND | prgOR &~prgAND);
|
||||
} else { /* MMC1 mode */
|
||||
prgAND >>=1;
|
||||
prgOR >>=1;
|
||||
if (MMC1_reg[0] &0x8) { /* 16 KiB mode */
|
||||
if (MMC1_reg[0] &0x04) { /* OR logic */
|
||||
setprg16r(chip, 0x8000, MMC1_reg[3] &prgAND | prgOR &~prgAND);
|
||||
setprg16r(chip, 0xC000, 0xFF &prgAND | prgOR &~prgAND);
|
||||
} else { /* AND logic */
|
||||
setprg16r(chip, 0x8000, 0x00 &prgAND | prgOR &~prgAND);
|
||||
setprg16r(chip, 0xC000, MMC1_reg[3] &prgAND | prgOR &~prgAND);
|
||||
}
|
||||
} else
|
||||
setprg32(0x8000, (MMC1_reg[3] &prgAND | prgOR &~prgAND) >>1);
|
||||
}
|
||||
|
||||
chrAND =reg[2] &0x10 && ~reg[2] &0x20? 0x1F: reg[2] &0x20? 0x7F: 0xFF;
|
||||
chrOR =reg[0] <<1;
|
||||
if (reg[2] &0x01) /* CHR RAM mode */
|
||||
setchr8r(0x10, 0);
|
||||
else
|
||||
if (reg[2] &0x40) /* CNROM mode */
|
||||
setchr8(chrOR >>3);
|
||||
else
|
||||
if (~reg[0] &0x02) { /* MMC3 mode */
|
||||
setchr1(0x0000 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] &0xFE)&chrAND | chrOR &~chrAND);
|
||||
setchr1(0x0400 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] |0x01)&chrAND | chrOR &~chrAND);
|
||||
setchr1(0x0800 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] &0xFE)&chrAND | chrOR &~chrAND);
|
||||
setchr1(0x0C00 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] |0x01)&chrAND | chrOR &~chrAND);
|
||||
setchr1(0x1000 ^(MMC3_index <<5 &0x1000), MMC3_reg[2] &chrAND | chrOR &~chrAND);
|
||||
setchr1(0x1400 ^(MMC3_index <<5 &0x1000), MMC3_reg[3] &chrAND | chrOR &~chrAND);
|
||||
setchr1(0x1800 ^(MMC3_index <<5 &0x1000), MMC3_reg[4] &chrAND | chrOR &~chrAND);
|
||||
setchr1(0x1C00 ^(MMC3_index <<5 &0x1000), MMC3_reg[5] &chrAND | chrOR &~chrAND);
|
||||
} else
|
||||
if (reg[0] &0x01) { /* VRC4 mode */
|
||||
setchr1(0x0000, VRC4_chr[0] &chrAND | chrOR &~chrAND);
|
||||
setchr1(0x0400, VRC4_chr[1] &chrAND | chrOR &~chrAND);
|
||||
setchr1(0x0800, VRC4_chr[2] &chrAND | chrOR &~chrAND);
|
||||
setchr1(0x0C00, VRC4_chr[3] &chrAND | chrOR &~chrAND);
|
||||
setchr1(0x1000, VRC4_chr[4] &chrAND | chrOR &~chrAND);
|
||||
setchr1(0x1400, VRC4_chr[5] &chrAND | chrOR &~chrAND);
|
||||
setchr1(0x1800, VRC4_chr[6] &chrAND | chrOR &~chrAND);
|
||||
setchr1(0x1C00, VRC4_chr[7] &chrAND | chrOR &~chrAND);
|
||||
} else { /* MMC1 mode */
|
||||
chrAND >>=2;
|
||||
chrOR >>=2;
|
||||
if (MMC1_reg[0] &0x10) { /* 4 KiB mode */
|
||||
setchr4(0x0000, MMC1_reg[1] &chrAND | chrOR &~chrAND);
|
||||
setchr4(0x1000, MMC1_reg[2] &chrAND | chrOR &~chrAND);
|
||||
} else /* 8 KiB mode */
|
||||
setchr8((MMC1_reg[1] &chrAND |chrOR &~chrAND) >>1);
|
||||
}
|
||||
|
||||
if (~reg[0] &0x02) /* MMC3 mode */
|
||||
setmirror(MMC3_mirroring &1 ^1);
|
||||
else
|
||||
if ( reg[0] &0x01) /* VRC4 mode */
|
||||
setmirror(VRC4_mirroring &3 ^(VRC4_mirroring &2? 0: 1));
|
||||
else /* MMC1 mode */
|
||||
setmirror(MMC1_reg[0] &3 ^3);
|
||||
}
|
||||
|
||||
static DECLFW(writeMMC3) {
|
||||
switch(A &0xE001) {
|
||||
case 0x8000: MMC3_index =V; sync(); break;
|
||||
case 0x8001: MMC3_reg[MMC3_index &7] =V; sync(); break;
|
||||
case 0xA000: MMC3_mirroring =V; sync(); break;
|
||||
case 0xA001: MMC3_wram =V; sync(); break;
|
||||
case 0xC000: MMC3_reload =V; break;
|
||||
case 0xC001: MMC3_count =0; break;
|
||||
case 0xE000: MMC3_irq =0; X6502_IRQEnd(FCEU_IQEXT); break;
|
||||
case 0xE001: MMC3_irq =1; break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(writeMMC1) {
|
||||
if (V &0x80) {
|
||||
MMC1_shift =MMC1_count =0;
|
||||
MMC1_reg[0] |=0x0C;
|
||||
sync();
|
||||
} else
|
||||
if (!MMC1_filter) {
|
||||
MMC1_shift |=(V &1) <<MMC1_count++;
|
||||
if (MMC1_count ==5) {
|
||||
MMC1_reg[A >>13 &3] =MMC1_shift;
|
||||
MMC1_count =0;
|
||||
MMC1_shift =0;
|
||||
sync();
|
||||
}
|
||||
}
|
||||
MMC1_filter =2;
|
||||
}
|
||||
|
||||
static DECLFW(writeVRC4) {
|
||||
uint8 index;
|
||||
A =A &0xF000 | (A &0x800? ((A &8? 1: 0) | (A &4? 2: 0)): ((A &4? 1: 0) | (A &8? 2: 0)));
|
||||
switch (A &0xF000) {
|
||||
case 0x8000: case 0xA000:
|
||||
VRC4_prg[A >>13 &1] =V;
|
||||
sync();
|
||||
break;
|
||||
case 0x9000:
|
||||
if (~A &2)
|
||||
VRC4_mirroring =V;
|
||||
else
|
||||
if (~A &1)
|
||||
VRC4_misc =V;
|
||||
sync();
|
||||
break;
|
||||
case 0xF000:
|
||||
switch (A &3) {
|
||||
case 0: VRCIRQ_latch =VRCIRQ_latch &0xF0 | V &0x0F; break;
|
||||
case 1: VRCIRQ_latch =VRCIRQ_latch &0x0F | V <<4; break;
|
||||
case 2: VRCIRQ_mode =V;
|
||||
if (VRCIRQ_mode &0x02) {
|
||||
VRCIRQ_count =VRCIRQ_latch;
|
||||
VRCIRQ_cycles =341;
|
||||
}
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
break;
|
||||
case 3: VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02;
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
index =(A -0xB000) >>11 | A >>1 &1;
|
||||
if (A &1)
|
||||
VRC4_chr[index] =VRC4_chr[index] & 0x0F | V <<4;
|
||||
else
|
||||
VRC4_chr[index] =VRC4_chr[index] &~0x0F | V &0x0F;
|
||||
sync();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void FP_FASTAPASS(1) cpuCycle(int a) {
|
||||
if ((reg[0] &3) ==3) while (a--) { /* VRC4 mode */
|
||||
if (VRCIRQ_mode &0x02 && (VRCIRQ_mode &0x04 || (VRCIRQ_cycles -=3) <=0)) {
|
||||
if (~VRCIRQ_mode &0x04) VRCIRQ_cycles +=341;
|
||||
if (!++VRCIRQ_count) {
|
||||
VRCIRQ_count =VRCIRQ_latch;
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (MMC1_filter) MMC1_filter--;
|
||||
}
|
||||
|
||||
static void horizontalBlanking(void) {
|
||||
if (~reg[0] &2) { /* MMC3 mode */
|
||||
MMC3_count =!MMC3_count? MMC3_reload: --MMC3_count;
|
||||
if (!MMC3_count && MMC3_irq) X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
|
||||
static void applyMode() {
|
||||
switch (reg[0] &3) {
|
||||
case 0:
|
||||
case 1: SetWriteHandler(0x8000, 0xFFFF, writeMMC3); break;
|
||||
case 2: SetWriteHandler(0x8000, 0xFFFF, writeMMC1); break;
|
||||
case 3: SetWriteHandler(0x8000, 0xFFFF, writeVRC4); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Mapper351_restore (int version) {
|
||||
applyMode();
|
||||
sync();
|
||||
}
|
||||
|
||||
static DECLFR(readDIP) {
|
||||
return dip;
|
||||
}
|
||||
|
||||
static DECLFW(writeReg) {
|
||||
uint8 previousMode =reg[0] &3;
|
||||
reg[A &3] =V;
|
||||
if ((reg[0] &3) !=previousMode) applyMode();
|
||||
sync();
|
||||
}
|
||||
|
||||
static DECLFW(writeFDSMirroring) {
|
||||
MMC3_mirroring =V >>3 &1;
|
||||
sync();
|
||||
}
|
||||
|
||||
static void Mapper351_power(void) {
|
||||
int i;
|
||||
for (i =0; i <4; i++) reg[i] =0;
|
||||
for (i =0; i <4; i++) MMC1_reg[i] =0;
|
||||
for (i =0; i <8; i++) MMC3_reg[i] =0;
|
||||
for (i =0; i <2; i++) VRC4_prg[i] =0;
|
||||
for (i =0; i <8; i++) VRC4_chr[i] =0;
|
||||
MMC1_shift =MMC1_count =MMC1_filter =0;
|
||||
MMC1_reg[0] =0x0C;
|
||||
MMC3_index =MMC3_mirroring =MMC3_wram =MMC3_reload =MMC3_count =MMC3_irq =0;
|
||||
VRC4_mirroring =VRC4_misc =VRCIRQ_latch =VRCIRQ_mode =VRCIRQ_count =VRCIRQ_cycles =0;
|
||||
dip =0;
|
||||
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetReadHandler(0x5000, 0x5FFF, readDIP);
|
||||
SetWriteHandler(0x5000, 0x5FFF, writeReg);
|
||||
SetWriteHandler(0x4025, 0x4025, writeFDSMirroring);
|
||||
applyMode();
|
||||
sync();
|
||||
}
|
||||
|
||||
static void Mapper351_reset (void) {
|
||||
int i;
|
||||
for (i =0; i <4; i++) reg[i] =0;
|
||||
dip++;
|
||||
applyMode();
|
||||
sync();
|
||||
}
|
||||
|
||||
static void Mapper351_close(void) {
|
||||
if (CHRRAM) FCEU_gfree(CHRRAM);
|
||||
if (PRGCHR) FCEU_gfree(PRGCHR);
|
||||
CHRRAM =NULL;
|
||||
PRGCHR =NULL;
|
||||
}
|
||||
|
||||
void Mapper351_Init (CartInfo *info) {
|
||||
int CHRRAMSIZE =info->CHRRamSize + info->CHRRamSaveSize;
|
||||
|
||||
info->Reset = Mapper351_reset;
|
||||
info->Power = Mapper351_power;
|
||||
info->Close = Mapper351_close;
|
||||
MapIRQHook = cpuCycle;
|
||||
GameHBIRQHook = horizontalBlanking;
|
||||
GameStateRestore = Mapper351_restore;
|
||||
AddExState(stateRegs, ~0, 0, 0);
|
||||
|
||||
if (CHRRAMSIZE) {
|
||||
CHRRAM =(uint8 *)FCEU_gmalloc(CHRRAMSIZE);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1);
|
||||
AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM");
|
||||
|
||||
/* This crazy thing can map CHR-ROM into CPU address space. Allocate a combined PRG+CHR address space and treat it a second "chip". */
|
||||
PRGCHR =(uint8 *)FCEU_gmalloc(PRGsize[0] +CHRsize[0]);
|
||||
memcpy(PRGCHR, PRGptr[0], PRGsize[0]);
|
||||
memcpy(PRGCHR +PRGsize[0], CHRptr[0], CHRsize[0]);
|
||||
SetupCartPRGMapping(0x10, PRGCHR, PRGsize[0] +CHRsize[0], 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020 negativeExponent
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
||||
92
src/boards/354.c
Normal file
92
src/boards/354.c
Normal file
@@ -0,0 +1,92 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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 uint16 latchAddr;
|
||||
static uint8 latchData;
|
||||
static uint8 submapper;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &latchAddr, 2, "ADDR" },
|
||||
{ &latchData, 1, "DATA" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Mapper354_Sync(void)
|
||||
{
|
||||
int prg =latchData &0x3F | latchAddr <<2 &0x40 | latchAddr >>5 &0x80;
|
||||
switch(latchAddr &7)
|
||||
{
|
||||
case 0: case 4:
|
||||
setprg32(0x8000, prg >>1);
|
||||
break;
|
||||
case 1:
|
||||
setprg16(0x8000, prg);
|
||||
setprg16(0xC000, prg |7);
|
||||
break;
|
||||
case 2: case 6:
|
||||
setprg8(0x8000, prg <<1 | latchData >>7);
|
||||
setprg8(0xA000, prg <<1 | latchData >>7);
|
||||
setprg8(0xC000, prg <<1 | latchData >>7);
|
||||
setprg8(0xE000, prg <<1 | latchData >>7);
|
||||
break;
|
||||
case 3: case 7:
|
||||
setprg16(0x8000, prg);
|
||||
setprg16(0xC000, prg);
|
||||
break;
|
||||
case 5:
|
||||
setprg8(0x6000, prg <<1 | latchData >>7);
|
||||
setprg32(0x8000, prg >>1 |3);
|
||||
break;
|
||||
}
|
||||
setchr8(0);
|
||||
setmirror(latchData &0x40? MI_H: MI_V);
|
||||
}
|
||||
|
||||
static DECLFW(Mapper354_WriteLatch)
|
||||
{
|
||||
latchData =V;
|
||||
latchAddr =A &0xFFFF;
|
||||
Mapper354_Sync();
|
||||
}
|
||||
|
||||
static void Mapper354_Reset(void)
|
||||
{
|
||||
latchAddr =latchData =0;
|
||||
Mapper354_Sync();
|
||||
}
|
||||
|
||||
static void Mapper354_Power(void)
|
||||
{
|
||||
latchAddr =latchData =0;
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(submapper ==1? 0xE000: 0xF000, 0xFFFF, Mapper354_WriteLatch);
|
||||
Mapper354_Sync();
|
||||
}
|
||||
|
||||
void Mapper354_Init(CartInfo *info)
|
||||
{
|
||||
submapper = info->submapper;
|
||||
info->Power =Mapper354_Power;
|
||||
info->Reset =Mapper354_Reset;
|
||||
AddExState(StateRegs, ~0, 0, 0);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020 negativeExponent
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020 negativeExponent
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -29,15 +29,16 @@
|
||||
|
||||
static uint8 preg[4];
|
||||
static uint8 dipswitch;
|
||||
static uint32 IRQCount, IRQa;
|
||||
static uint8 IRQa;
|
||||
static uint16 IRQCount;
|
||||
|
||||
static const uint8 banks[8] = { 4, 3, 5, 3, 6, 3, 7, 3 };
|
||||
static const uint8 outer_bank[4] = { 0x00, 0x08, 0x10, 0x18 };
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &IRQCount, 4 | FCEUSTATE_RLSB, "IRQC" },
|
||||
{ &IRQa, 4 | FCEUSTATE_RLSB, "IRQA" },
|
||||
{ &IRQCount, 2 | FCEUSTATE_RLSB, "IRQC" },
|
||||
{ &IRQa, 1 | FCEUSTATE_RLSB, "IRQA" },
|
||||
{ &dipswitch, 1, "DPSW" },
|
||||
{ &preg, 4, "REG" },
|
||||
{ 0 }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020 negativeExponent
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020 negativeExponent
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2019 Libretro Team
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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
|
||||
@@ -16,35 +16,38 @@
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
/* 2019-05-29 - Mapper 224, KT-008
|
||||
* iNES Mapper 224 is used for the 晶科泰 (Jncota) KT-008 PCB.
|
||||
* It's an MMC3 clone that supports 1024 KiB of PRG-ROM through an additional
|
||||
* outer bank register at $5000.
|
||||
* http://wiki.nesdev.com/w/index.php/INES_Mapper_224 */
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static void M224PW(uint32 A, uint8 V) {
|
||||
setprg8(A, (V & 0x3f) | ((EXPREGS[0] << 4) & 0x40));
|
||||
static void M364CW(uint32 A, uint8 V) {
|
||||
V &= (EXPREGS[0] & 0x20) ? 0x7F : 0xFF;
|
||||
setchr1(A, V | ((EXPREGS[0] << 4) & 0x100));
|
||||
}
|
||||
|
||||
static DECLFW(Mapper224Write) {
|
||||
static void M364PW(uint32 A, uint8 V) {
|
||||
V &= (EXPREGS[0] & 0x20) ? 0x0F : 0x1F;
|
||||
setprg8(A, V | ((EXPREGS[0] >> 1) & 0x20));
|
||||
}
|
||||
|
||||
static DECLFW(M364Write) {
|
||||
EXPREGS[0] = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void M224Power(void) {
|
||||
static void M364Power(void) {
|
||||
EXPREGS[0] = 0;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x5000, 0x5000, Mapper224Write);
|
||||
SetWriteHandler(0x7000, 0x7FFF, M364Write);
|
||||
}
|
||||
|
||||
void Mapper224_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 1024, 0, 8, 0);
|
||||
pwrap = M224PW;
|
||||
info->Power = M224Power;
|
||||
void Mapper364_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 512, 512, 8, 0);
|
||||
pwrap = M364PW;
|
||||
cwrap = M364CW;
|
||||
info->Power = M364Power;
|
||||
AddExState(EXPREGS, 1, 0, "EXPR");
|
||||
}
|
||||
112
src/boards/368.c
Normal file
112
src/boards/368.c
Normal file
@@ -0,0 +1,112 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* NES 2.0 Mapper 357 is used for a 4-in-1 multicart (cartridge ID 4602) from Bit Corp.
|
||||
* The first game is Bit Corp's hack of the YUNG-08 conversion of Super Mario Brothers 2 (J) named Mr. Mary 2,
|
||||
* the other three games are UNROM games.
|
||||
*
|
||||
* Implementation is modified so reset actually sets the correct dipswitch (or outer banks) for each of the 4 games
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 preg;
|
||||
static uint8 latch;
|
||||
static uint8 IRQa;
|
||||
static uint16 IRQCount;
|
||||
|
||||
static const uint8 banks[8] = { 4, 3, 5, 3, 6, 3, 7, 3 };
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &IRQCount, 2 | FCEUSTATE_RLSB, "IRQC" },
|
||||
{ &IRQa, 1, "IRQA" },
|
||||
{ &latch, 1, "LATC" },
|
||||
{ &preg, 1, "REG" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setprg8(0x6000, 2);
|
||||
setprg8(0x8000, 1);
|
||||
setprg8(0xa000, 0);
|
||||
setprg8(0xc000, banks[preg]);
|
||||
setprg8(0xe000, 8);
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
static DECLFW(M368WritePRG) {
|
||||
preg = V & 7;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFW(M368WriteIRQ) {
|
||||
latch = V & 0x53;
|
||||
IRQa = V & 1;
|
||||
if (!IRQa) {
|
||||
IRQCount = 0;
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(M368Read) {
|
||||
return (latch | 0xBA);
|
||||
}
|
||||
|
||||
static void M368Power(void) {
|
||||
preg = 0;
|
||||
latch = 0;
|
||||
IRQa = IRQCount = 0;
|
||||
Sync();
|
||||
SetReadHandler(0x4122, 0x4122, M368Read);
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x4022, 0x4022, M368WritePRG);
|
||||
SetWriteHandler(0x4120, 0x4120, M368WritePRG);
|
||||
SetWriteHandler(0x4122, 0x4122, M368WriteIRQ);
|
||||
}
|
||||
|
||||
static void M368Reset(void) {
|
||||
IRQa = IRQCount = 0;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void FP_FASTAPASS(1) M368IRQHook(int a) {
|
||||
if (IRQa) {
|
||||
if (IRQCount < 4096)
|
||||
IRQCount += a;
|
||||
else {
|
||||
IRQa = 0;
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper368_Init(CartInfo *info) {
|
||||
info->Reset = M368Reset;
|
||||
info->Power = M368Power;
|
||||
MapIRQHook = M368IRQHook;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020 negativeExponent
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* 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
|
||||
|
||||
96
src/boards/370.c
Normal file
96
src/boards/370.c
Normal file
@@ -0,0 +1,96 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* Mapper 370 - F600
|
||||
* Golden Mario Party II - Around the World (6-in-1 multicart)
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 PPUCHRBus;
|
||||
static uint8 mirr[8];
|
||||
|
||||
static void FP_FASTAPASS(1) M370PPU(uint32 A) {
|
||||
if ((EXPREGS[0] & 7) == 1) {
|
||||
A &= 0x1FFF;
|
||||
A >>= 10;
|
||||
PPUCHRBus = A;
|
||||
setmirror(MI_0 + mirr[A]);
|
||||
}
|
||||
}
|
||||
|
||||
static void M370CW(uint32 A, uint8 V) {
|
||||
uint8 mask = (EXPREGS[0] & 4) ? 0x7F : 0xFF;
|
||||
/* FIXME: Mario VII, mask is reversed? */
|
||||
if ((EXPREGS[0] & 7) == 6 && V & 0x80)
|
||||
mask = 0xFF;
|
||||
mirr[A >> 10] = V >> 7;
|
||||
setchr1(A, (V & mask) | ((EXPREGS[0] & 7) << 7));
|
||||
if (((EXPREGS[0] & 7) == 1) && (PPUCHRBus == (A >> 10)))
|
||||
setmirror(MI_0 + (V >> 7));
|
||||
}
|
||||
|
||||
static void M370PW(uint32 A, uint8 V) {
|
||||
uint8 mask = EXPREGS[0] & 0x20 ? 0x0F : 0x1F;
|
||||
setprg8(A, (V & mask) | ((EXPREGS[0] & 0x38) << 1));
|
||||
}
|
||||
|
||||
static void M370MW(uint8 V) {
|
||||
A000B = V;
|
||||
if ((EXPREGS[0] & 7) != 1)
|
||||
setmirror((V & 1) ^ 1);
|
||||
}
|
||||
|
||||
static DECLFR(M370Read) {;
|
||||
return (EXPREGS[1] << 7);
|
||||
}
|
||||
|
||||
static DECLFW(M370Write) {
|
||||
EXPREGS[0] = (A & 0xFF);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void M370Reset(void) {
|
||||
EXPREGS[0] = 0;
|
||||
EXPREGS[1] ^= 1;
|
||||
FCEU_printf("solderpad=%02x\n", EXPREGS[1]);
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void M370Power(void) {
|
||||
EXPREGS[0] = 0;
|
||||
EXPREGS[1] = 1; /* start off with the 6-in-1 menu */
|
||||
GenMMC3Power();
|
||||
SetReadHandler(0x5000, 0x5FFF, M370Read);
|
||||
SetWriteHandler(0x5000, 0x5FFF, M370Write);
|
||||
}
|
||||
|
||||
void Mapper370_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 256, 256, 8, 0);
|
||||
cwrap = M370CW;
|
||||
pwrap = M370PW;
|
||||
mwrap = M370MW;
|
||||
PPU_hook = M370PPU;
|
||||
info->Power = M370Power;
|
||||
info->Reset = M370Reset;
|
||||
AddExState(EXPREGS, 2, 0, "EXPR");
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020 negativeExponent
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -18,7 +18,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/* added 2020-1-28 - negativeExponent */
|
||||
/* added 2020-1-28 - */
|
||||
/* NES 2.0 Mapper 372 is used for a revision of the Rockman I-VI multicart (PCB ID SFC-12).
|
||||
* It is INES Mapper 045 but with one bit of outer bank register #2 working as a CHR-ROM/RAM switch.
|
||||
*/
|
||||
|
||||
121
src/boards/375.c
Normal file
121
src/boards/375.c
Normal file
@@ -0,0 +1,121 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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 *WRAM = NULL;
|
||||
static uint32 WRAMSIZE;
|
||||
|
||||
static uint16 addrlatch;
|
||||
static uint8 datalatch;
|
||||
|
||||
static void Sync(void) {
|
||||
uint32 S = addrlatch & 1;
|
||||
uint32 p = ((addrlatch >> 2) & 0x1F) + ((addrlatch & 0x100) >> 3) + ((addrlatch & 0x400) >> 4);
|
||||
uint32 L = (addrlatch >> 9) & 1;
|
||||
uint32 p_8000 = p;
|
||||
|
||||
if ((addrlatch >> 11) & 1)
|
||||
p_8000 = (p & 0x7E) | (datalatch & 7);
|
||||
|
||||
if ((addrlatch >> 7) & 1) {
|
||||
if (S) {
|
||||
setprg32(0x8000, p >> 1);
|
||||
} else {
|
||||
setprg16(0x8000, p_8000);
|
||||
setprg16(0xC000, p);
|
||||
}
|
||||
} else {
|
||||
if (S) {
|
||||
if (L) {
|
||||
setprg16(0x8000, p_8000 & 0x7E);
|
||||
setprg16(0xC000, p | 7);
|
||||
} else {
|
||||
setprg16(0x8000, p_8000 & 0x7E);
|
||||
setprg16(0xC000, p & 0x78);
|
||||
}
|
||||
} else {
|
||||
if (L) {
|
||||
setprg16(0x8000, p_8000);
|
||||
setprg16(0xC000, p | 7);
|
||||
} else {
|
||||
setprg16(0x8000, p_8000);
|
||||
setprg16(0xC000, p & 0x78);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((addrlatch & 0x80) == 0x80)
|
||||
/* CHR-RAM write protect hack, needed for some multicarts */
|
||||
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0);
|
||||
else
|
||||
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1);
|
||||
|
||||
setmirror(((addrlatch >> 1) & 1) ^ 1);
|
||||
setchr8(0);
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
}
|
||||
|
||||
static DECLFW(M375Write) {
|
||||
if (addrlatch & 0x800)
|
||||
datalatch = V;
|
||||
else {
|
||||
addrlatch = A;
|
||||
datalatch = V;
|
||||
}
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M375Reset(void) {
|
||||
addrlatch = 0;
|
||||
datalatch = 0;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M375Power(void) {
|
||||
addrlatch = 0;
|
||||
datalatch = 0;
|
||||
Sync();
|
||||
setchr8(0);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M375Write);
|
||||
if (WRAMSIZE) {
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper375_Init(CartInfo *info) {
|
||||
info->Power = M375Power;
|
||||
info->Reset = M375Reset;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&addrlatch, 2, 0, "ADDR");
|
||||
AddExState(&datalatch, 1, 0, "DATA");
|
||||
|
||||
WRAMSIZE = 8192;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
}
|
||||
65
src/boards/376.c
Normal file
65
src/boards/376.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2019 Libretro Team
|
||||
*
|
||||
* 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"
|
||||
#include "mmc3.h"
|
||||
|
||||
static void Mapper376CW(uint32 A, uint8 V) {
|
||||
uint32 base = (EXPREGS[0] &0x40? 0x080: 0x000) | (EXPREGS[1] &0x01? 0x100: 0x000);
|
||||
setchr1(A, base | (V & 0x7F));
|
||||
}
|
||||
|
||||
static void Mapper376PW(uint32 A, uint8 V) {
|
||||
uint32 base = (EXPREGS[0] &0x07) | (EXPREGS[0] &0x40? 0x08: 0x00) | (EXPREGS[1] &0x01? 0x10: 0x00);
|
||||
if (EXPREGS[0] & 0x80) {
|
||||
if (EXPREGS[0] &0x20) {
|
||||
if (A ==0x8000) setprg32(A, base >>1);
|
||||
} else {
|
||||
if (A ==0x8000 || A ==0xC000) setprg16(A, base);
|
||||
}
|
||||
} else
|
||||
setprg8(A, (base << 1) | (V & 0x0F));
|
||||
}
|
||||
|
||||
static DECLFW(Mapper376Write) {
|
||||
EXPREGS[A & 1] = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void Mapper376Reset(void) {
|
||||
EXPREGS[0] = 0;
|
||||
EXPREGS[1] = 0;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void Mapper376Power(void) {
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x6000, 0x7FFF, Mapper376Write);
|
||||
}
|
||||
|
||||
void Mapper376_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 128, 256, 1, 0);
|
||||
pwrap = Mapper376PW;
|
||||
cwrap = Mapper376CW;
|
||||
info->Power = Mapper376Power;
|
||||
info->Reset = Mapper376Reset;
|
||||
AddExState(EXPREGS, 2, 0, "EXPR");
|
||||
}
|
||||
64
src/boards/377.c
Normal file
64
src/boards/377.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* NES 2.0 Mapper 377 - NES 2.0 Mapper 377 is used for the
|
||||
* 1998 Super Game 8-in-1 (JY-111) pirate multicart. It works similarly to Mapper 267 except it has an outer 256KiB PRG-ROM bank.
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
#define OUTER_BANK (((EXPREGS[0] & 0x20) >> 2) | (EXPREGS[0] & 0x06))
|
||||
|
||||
static void M377CW(uint32 A, uint8 V) {
|
||||
setchr1(A, (V & 0x7F) | (OUTER_BANK << 6));
|
||||
}
|
||||
|
||||
static void M377PW(uint32 A, uint8 V) {
|
||||
setprg8(A, (V & 0x0F) | (OUTER_BANK << 3));
|
||||
}
|
||||
|
||||
static DECLFW(M377Write) {
|
||||
if (!(EXPREGS[0] & 0x80)) {
|
||||
EXPREGS[0] = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static void M377Reset(void) {
|
||||
EXPREGS[0] = 0;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void M377Power(void) {
|
||||
EXPREGS[0] = 0;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x6000, 0x7FFF, M377Write);
|
||||
}
|
||||
|
||||
void Mapper377_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 128, 128, 0, 0);
|
||||
cwrap = M377CW;
|
||||
pwrap = M377PW;
|
||||
info->Reset = M377Reset;
|
||||
info->Power = M377Power;
|
||||
AddExState(EXPREGS, 1, 0, "EXPR");
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020 negativeExponent
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
static uint16 latche;
|
||||
static uint8 dipswitch;
|
||||
static uint8 isKN35A;
|
||||
|
||||
static SFORMAT StateRegs[] = {
|
||||
{ &latche, 2 | FCEUSTATE_RLSB, "LATC" },
|
||||
@@ -47,14 +48,14 @@ static void Sync(void)
|
||||
else /* UxROM */
|
||||
{
|
||||
setprg16(0x8000, latche >> 2);
|
||||
setprg16(0xC000, (latche >> 2) | 7);
|
||||
setprg16(0xC000, (latche >> 2) | 7 | (isKN35A && latche &0x100? 8: 0));
|
||||
}
|
||||
setmirror(((latche >> 1) & 1) ^ 1);
|
||||
}
|
||||
|
||||
static DECLFR(M380Read)
|
||||
{
|
||||
if (latche & 0x100)
|
||||
if (latche & 0x100 && !isKN35A)
|
||||
return dipswitch;
|
||||
return CartBR(A);
|
||||
}
|
||||
@@ -89,6 +90,7 @@ static void StateRestore(int version)
|
||||
|
||||
void Mapper380_Init(CartInfo *info)
|
||||
{
|
||||
isKN35A = info->iNES2 && info->submapper == 1;
|
||||
info->Power = M380Power;
|
||||
info->Reset = M380Reset;
|
||||
GameStateRestore = StateRestore;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020 negativeExponent
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
||||
108
src/boards/383.c
Normal file
108
src/boards/383.c
Normal file
@@ -0,0 +1,108 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* 晶太 YY840708C PCB
|
||||
Solely used for the "1995 Soccer 6-in-1 足球小将專輯 (JY-014)" multicart.
|
||||
MMC3+PAL16L8 combination, resulting in a bizarre mapper that switches banks in part upon *reads*.
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
#define A15 EXPREGS[0]
|
||||
#define A16 EXPREGS[1]
|
||||
#define A17A18 EXPREGS[2]
|
||||
|
||||
static void M383PRGWrap (uint32 A, uint8 V)
|
||||
{
|
||||
switch(A17A18)
|
||||
{
|
||||
case 0x00:
|
||||
/* "Setting 0 provides a round-about means of dividing the first 128 KiB bank into two 32 KiB and one 64 KiB bank." */
|
||||
setprg8(A, V &(A16? 0x07: 0x03) | (A16? 0x00: A15) | A16 | A17A18);
|
||||
break;
|
||||
case 0x30:
|
||||
/* "Setting 3 provides 128 KiB MMC3 banking with the CPU A14 line fed to the MMC3 clone reversed.
|
||||
This is used for the game Tecmo Cup: Soccer Game (renamed "Tecmo Cup Soccer"),
|
||||
originally an MMC1 game with the fixed bank at $8000-$BFFF and the switchable bank at $C000-$FFFF,
|
||||
a configuration that could not be reproduced with an MMC3 alone." */
|
||||
setprg8(A ^0x4000, V &0x0F | A17A18);
|
||||
|
||||
/* "It is also used for the menu,
|
||||
which in part executes from PRG-ROM mapped to the CPU $6000-$7FFF address range on the MMC3 clone's fixed banks alone,
|
||||
as no MMC3 PRG bank register is written to before JMPing to this address range." */
|
||||
if (A ==0xE000) setprg8(A ^0x8000, V &0x0B | A17A18);
|
||||
break;
|
||||
default:
|
||||
/* "Settings 1 and 2 provide normal 128 KiB MMC3 banking." */
|
||||
setprg8(A, V &0x0F | A17A18);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void M383CHRWrap (uint32 A, uint8 V)
|
||||
{
|
||||
setchr1(A, V &0x7F | A17A18 <<3);
|
||||
}
|
||||
|
||||
static DECLFR(M383Read)
|
||||
{
|
||||
if (A17A18 ==0x00)
|
||||
{ /* "PAL PRG A16 is updated with the content of the corresponding MMC3 PRG bank bit by reading from the respective address range,
|
||||
which in turn will then be applied across the entire ROM address range." */
|
||||
A16 =DRegBuf[0x06 | A >>13 &0x01] &0x08;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
}
|
||||
return CartBR(A);
|
||||
}
|
||||
|
||||
static DECLFW(M383Write)
|
||||
{
|
||||
if (A &0x0100)
|
||||
{
|
||||
A15 =A >>11 &0x04;
|
||||
A17A18 =A &0x30;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
if (A &0x4000)
|
||||
MMC3_IRQWrite(A, V);
|
||||
else
|
||||
MMC3_CMDWrite(A, V);
|
||||
}
|
||||
|
||||
static void M383Reset (void) {
|
||||
EXPREGS[0] = 0;
|
||||
EXPREGS[1] = 0;
|
||||
EXPREGS[2] = 0;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void M383Power (void) {
|
||||
GenMMC3Power();
|
||||
SetReadHandler(0x8000, 0xBFFF, M383Read);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M383Write);
|
||||
}
|
||||
|
||||
void Mapper383_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 128, 128, 8, 0);
|
||||
pwrap = M383PRGWrap;
|
||||
cwrap = M383CHRWrap;
|
||||
info->Power = M383Power;
|
||||
info->Reset = M383Reset;
|
||||
AddExState(EXPREGS, 3, 0, "EXPR");
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020 negativeExponent
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020 negativeExponent
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
||||
71
src/boards/391.c
Normal file
71
src/boards/391.c
Normal file
@@ -0,0 +1,71 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* BS-110 PCB, previously called NC7000M due to a mix-up. */
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static void Mapper391_PRGWrap(uint32 A, uint8 V) {
|
||||
int prgAND =EXPREGS[0] &0x08? 0x0F: 0x1F;
|
||||
int prgOR =EXPREGS[0] <<4 &0x30;
|
||||
if (EXPREGS[0] &0x20) {
|
||||
if (~A &0x4000) {
|
||||
setprg8(A, (EXPREGS[0] &0x04? ~2: ~0) &V &prgAND | prgOR &~prgAND);
|
||||
setprg8(A |0x4000, (EXPREGS[0] &0x04? 2: 0) |V &prgAND | prgOR &~prgAND);
|
||||
}
|
||||
} else
|
||||
setprg8(A, V &prgAND | prgOR &~prgAND);
|
||||
}
|
||||
|
||||
static void Mapper391_CHRWrap(uint32 A, uint8 V) {
|
||||
int chrAND =EXPREGS[0] &0x40? 0x7F: 0xFF;
|
||||
int chrOR =EXPREGS[0] <<3 &0x80 | EXPREGS[1] <<8 &0x100;
|
||||
setchr1(A, V &chrAND | chrOR &~chrAND);
|
||||
}
|
||||
|
||||
static DECLFW(Mapper391_Write) {
|
||||
if (~EXPREGS[0] &0x80) {
|
||||
EXPREGS[0] =V;
|
||||
EXPREGS[1] =A >>8 &0xFF;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static void Mapper391_Reset(void) {
|
||||
EXPREGS[0] =EXPREGS[1] =0;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void Mapper391_Power(void) {
|
||||
EXPREGS[0] =EXPREGS[1] =0;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x6000, 0x7FFF, Mapper391_Write);
|
||||
}
|
||||
|
||||
void Mapper391_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 256, 256, 0, 0);
|
||||
cwrap = Mapper391_CHRWrap;
|
||||
pwrap = Mapper391_PRGWrap;
|
||||
info->Power = Mapper391_Power;
|
||||
info->Reset = Mapper391_Reset;
|
||||
AddExState(EXPREGS, 2, 0, "EXPR");
|
||||
}
|
||||
111
src/boards/393.c
Normal file
111
src/boards/393.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 *CHRRAM;
|
||||
static uint32 CHRRAMSIZE;
|
||||
|
||||
static int getPRGBank(int bank) {
|
||||
if ((~bank & 1) && (MMC3_cmd & 0x40)) bank ^= 2;
|
||||
return (bank & 2) ? 0xFE | (bank & 1) : DRegBuf[6 | (bank & 1)];
|
||||
}
|
||||
|
||||
static void M393CW(uint32 A, uint8 V) {
|
||||
if (EXPREGS[0] & 8)
|
||||
setchr8r(0x10, 0);
|
||||
else
|
||||
setchr1(A, V & 0xFF | EXPREGS[0] << 8);
|
||||
}
|
||||
|
||||
static void M393PW(uint32 A, uint8 V) {
|
||||
switch ((EXPREGS[0] >> 4) & 3) {
|
||||
case 0:
|
||||
case 1:
|
||||
setprg8(A, (V & 0x0F) | (EXPREGS[0] << 4));
|
||||
break;
|
||||
case 2:
|
||||
setprg32(0x8000, ((getPRGBank(0) >> 2) & 3) | (EXPREGS[0] << 2));
|
||||
break;
|
||||
case 3:
|
||||
setprg16(0x8000, (EXPREGS[0] << 3) | (EXPREGS[1] &7));
|
||||
setprg16(0xC000, (EXPREGS[0] << 3) | 7);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(M393Write8) {
|
||||
switch (A & 0xE000) {
|
||||
case 0x8000:
|
||||
case 0xA000:
|
||||
MMC3_CMDWrite(A, V);
|
||||
break;
|
||||
case 0xC000:
|
||||
case 0xE000:
|
||||
MMC3_IRQWrite(A, V);
|
||||
break;
|
||||
}
|
||||
|
||||
EXPREGS[1] = V;
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
}
|
||||
|
||||
static DECLFW(M393Write6) {
|
||||
EXPREGS[0] = A & 0xFF;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void M393Power(void) {
|
||||
EXPREGS[0] = EXPREGS[1] = 0;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x6000, 0x7FFF, M393Write6);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M393Write8);
|
||||
}
|
||||
|
||||
static void M393Reset(void) {
|
||||
EXPREGS[0] = EXPREGS[1] = 0;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void M393lose(void) {
|
||||
GenMMC3Close();
|
||||
if (CHRRAM)
|
||||
FCEU_free(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
}
|
||||
|
||||
void Mapper393_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 1024, 512, 8, 0);
|
||||
pwrap = M393PW;
|
||||
cwrap = M393CW;
|
||||
info->Power = M393Power;
|
||||
info->Reset = M393Reset;
|
||||
info->Close = M393lose;
|
||||
CHRRAMSIZE = 8192;
|
||||
CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1);
|
||||
AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR");
|
||||
AddExState(EXPREGS, 2, 0, "EXPR");
|
||||
}
|
||||
67
src/boards/395.c
Normal file
67
src/boards/395.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* Mapper 395 - Realtec 8210
|
||||
* Super Card 12-in-1 (SPC002)
|
||||
* Super Card 13-in-1 (SPC003)
|
||||
* Super Card 14-in-1 (King006)
|
||||
* Super Card 14-in-1 (King007)
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static void M395CW(uint32 A, uint8 V) {
|
||||
uint8 mask = EXPREGS[1] & 0x40 ? 0x7F : 0xFF;
|
||||
setchr1(A, (V & mask) | ((EXPREGS[1] & 0x10) << 3) | ((EXPREGS[0] & 0x30) << 4) | ((EXPREGS[1] & 0x20) << 5));
|
||||
}
|
||||
|
||||
static void M395PW(uint32 A, uint8 V) {
|
||||
uint8 mask = EXPREGS[1] & 8 ? 0x0F : 0x1F;
|
||||
setprg8(A, (V & mask) | ((EXPREGS[0] & 0x30) << 1) | ((EXPREGS[0] & 8) << 4) | ((EXPREGS[1] & 1) << 4));
|
||||
}
|
||||
|
||||
static DECLFW(M395Write) {
|
||||
if (!(EXPREGS[1] & 0x80)) {
|
||||
EXPREGS[(A >> 4) & 1] = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static void M395Reset(void) {
|
||||
EXPREGS[0] = EXPREGS[1] = 0;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void M395Power(void) {
|
||||
EXPREGS[0] = EXPREGS[1] = 0;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x6000, 0x7FFF, M395Write);
|
||||
}
|
||||
|
||||
void Mapper395_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 256, 256, 0, 0);
|
||||
cwrap = M395CW;
|
||||
pwrap = M395PW;
|
||||
info->Power = M395Power;
|
||||
info->Reset = M395Reset;
|
||||
AddExState(EXPREGS, 2, 0, "EXPR");
|
||||
}
|
||||
73
src/boards/396.c
Normal file
73
src/boards/396.c
Normal file
@@ -0,0 +1,73 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* NES 2.0 Mapper 396 - BMC-830752C
|
||||
* 1995 Super 8-in-1 (JY-050 rev0)
|
||||
* Super 8-in-1 Gold Card Series (JY-085)
|
||||
* Super 8-in-1 Gold Card Series (JY-086)
|
||||
* 2-in-1 (GN-51)
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 reg[2];
|
||||
|
||||
static void Sync (void) {
|
||||
setprg16(0x8000, reg[1] << 3 | reg[0] & 7);
|
||||
setprg16(0xC000, reg[1] << 3 | 7);
|
||||
setchr8(0);
|
||||
setmirror(reg[1] & 0x60 ? 0 : 1);
|
||||
}
|
||||
|
||||
static DECLFW(M396WriteInnerBank) {
|
||||
reg[0] = V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFW(M396WriteOuterBank) {
|
||||
reg[1] = V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M396Reset(void) {
|
||||
reg[0] = 0x00;
|
||||
reg[1] = 0x00;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M396Power(void) {
|
||||
reg[0] = 0x00;
|
||||
reg[1] = 0x00;
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0x9FFF, M396WriteInnerBank);
|
||||
SetWriteHandler(0xA000, 0xBFFF, M396WriteOuterBank);
|
||||
SetWriteHandler(0xC000, 0xFFFF, M396WriteInnerBank);
|
||||
}
|
||||
|
||||
void Mapper396_Init(CartInfo *info) {
|
||||
info->Power = M396Power;
|
||||
info->Reset = M396Reset;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(reg, 2, 0, "REGS");
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2012 CaH4e3
|
||||
* Copyright (C) 2022 NewRisingSun
|
||||
*
|
||||
* 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
|
||||
@@ -23,7 +24,8 @@
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 reg;
|
||||
static uint8 submapper;
|
||||
static uint8 reg, outer;
|
||||
static uint32 IRQCount, IRQa;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
@@ -31,34 +33,51 @@ static SFORMAT StateRegs[] =
|
||||
{ &IRQCount, 4, "IRQC" },
|
||||
{ &IRQa, 4, "IRQA" },
|
||||
{ ®, 1, "REG" },
|
||||
{ ®, 1, "OUTE" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setprg8(0x6000, ~1);
|
||||
setprg8(0x8000, ~3);
|
||||
setprg8(0xa000, ~2);
|
||||
setprg8(0xc000, reg);
|
||||
setprg8(0xe000, ~0);
|
||||
setchr8(0);
|
||||
if (outer &0x08) {
|
||||
if (outer &0x10)
|
||||
setprg32(0x8000, 2 | outer >>6);
|
||||
else {
|
||||
setprg16(0x8000, 4 | outer >>5);
|
||||
setprg16(0xC000, 4 | outer >>5);
|
||||
}
|
||||
} else {
|
||||
setprg8(0x6000, 6);
|
||||
setprg8(0x8000, 4);
|
||||
setprg8(0xa000, 5);
|
||||
setprg8(0xc000, reg &7);
|
||||
setprg8(0xe000, 7);
|
||||
}
|
||||
setchr8(outer >>1);
|
||||
setmirror(outer &1? MI_H: MI_V);
|
||||
}
|
||||
|
||||
static DECLFW(M40Write) {
|
||||
switch (A & 0xe000) {
|
||||
case 0x8000: IRQa = 0; IRQCount = 0; X6502_IRQEnd(FCEU_IQEXT); break;
|
||||
case 0xa000: IRQa = 1; break;
|
||||
case 0xc000: if (submapper ==1) { outer =A &0xFF; Sync(); } break;
|
||||
case 0xe000: reg = V & 7; Sync(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void M40Power(void) {
|
||||
reg = 0;
|
||||
outer = 0;
|
||||
IRQa = 0;
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
Sync();
|
||||
SetReadHandler(0x6000, 0xffff, CartBR);
|
||||
SetWriteHandler(0x8000, 0xffff, M40Write);
|
||||
}
|
||||
|
||||
static void M40Reset(void) {
|
||||
outer = 0;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void FP_FASTAPASS(1) M40IRQHook(int a) {
|
||||
@@ -77,6 +96,7 @@ static void StateRestore(int version) {
|
||||
}
|
||||
|
||||
void Mapper40_Init(CartInfo *info) {
|
||||
submapper =info->submapper;
|
||||
info->Reset = M40Reset;
|
||||
info->Power = M40Power;
|
||||
MapIRQHook = M40IRQHook;
|
||||
|
||||
96
src/boards/401.c
Normal file
96
src/boards/401.c
Normal file
@@ -0,0 +1,96 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* NES 2.0 - Mapper 401 (reference from NewRisingSun)
|
||||
* Super 19-in-1 (VIP19) (crc 0x2F497313)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 dipswitch = 0;
|
||||
|
||||
static void M401CW(uint32 A, uint8 V) {
|
||||
uint32 mask = (0xFF >> (~EXPREGS[2] & 0xF));
|
||||
uint32 bank = (EXPREGS[0] | ((EXPREGS[2] << 4) & 0xF00));
|
||||
setchr1(A, (V & mask) | bank);
|
||||
}
|
||||
|
||||
static void M401PW(uint32 A, uint8 V) {
|
||||
if ((dipswitch & 1) && (EXPREGS[1] & 0x80)) {
|
||||
/* openbus */
|
||||
} else {
|
||||
uint32 mask = (~EXPREGS[3] & 0x1F);
|
||||
uint32 bank = (EXPREGS[1] & 0x1F) | (EXPREGS[2] & 0x80) |
|
||||
((dipswitch & 2) ? (EXPREGS[2] & 0x20) : ((EXPREGS[1] >> 1) & 0x20)) |
|
||||
((dipswitch & 4) ? (EXPREGS[2] & 0x40) : ((EXPREGS[1] << 1) & 0x40));
|
||||
setprg8(A, (V & mask) | bank);
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(M401Read) {
|
||||
if ((dipswitch & 1) && (EXPREGS[1] & 0x80))
|
||||
return X.DB;
|
||||
return CartBR(A);
|
||||
}
|
||||
|
||||
static DECLFW(M401Write) {
|
||||
/* FCEU_printf("Wr A:%04x V:%02x index:%d\n", A, V, EXPREGS[4]); */
|
||||
if (!(EXPREGS[3] & 0x40)) {
|
||||
EXPREGS[EXPREGS[4]] = V;
|
||||
EXPREGS[4] = (EXPREGS[4] + 1) & 3;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
CartBW(A, V);
|
||||
}
|
||||
|
||||
static void M401Reset(void) {
|
||||
dipswitch = (dipswitch + 1) & 7;
|
||||
FCEU_printf("dipswitch = %d\n", dipswitch);
|
||||
EXPREGS[0] = 0x00;
|
||||
EXPREGS[1] = 0x00;
|
||||
EXPREGS[2] = 0x0F;
|
||||
EXPREGS[3] = 0x00;
|
||||
EXPREGS[4] = 0x00;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void M401Power(void) {
|
||||
dipswitch = 7;
|
||||
EXPREGS[0] = 0x00;
|
||||
EXPREGS[1] = 0x00;
|
||||
EXPREGS[2] = 0x0F;
|
||||
EXPREGS[3] = 0x00;
|
||||
EXPREGS[4] = 0x00;
|
||||
GenMMC3Power();
|
||||
SetReadHandler(0x8000, 0xFFFF, M401Read);
|
||||
SetWriteHandler(0x6000, 0x7FFF, M401Write);
|
||||
}
|
||||
|
||||
void Mapper401_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 256, 256, 8, 0);
|
||||
cwrap = M401CW;
|
||||
pwrap = M401PW;
|
||||
info->Power = M401Power;
|
||||
info->Reset = M401Reset;
|
||||
AddExState(EXPREGS, 5, 0, "EXPR");
|
||||
AddExState(&dipswitch, 1, 0, "DPSW");
|
||||
}
|
||||
82
src/boards/403.c
Normal file
82
src/boards/403.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* NES 2.0 Mapper 403 denotes the 89433 circuit board with up to 1 MiB PRG-ROM and 32 KiB of CHR-RAM, bankable with 8 KiB granularity.
|
||||
*
|
||||
* Tetris Family - 玩家 19-in-1 智瑟實典 (NO-1683)
|
||||
* Sachen Superpack (versions A-C)
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 reg[3];
|
||||
|
||||
static void Sync(void) {
|
||||
uint8 prg = reg[0];
|
||||
uint8 chr = reg[1];
|
||||
uint8 mode = reg[2];
|
||||
|
||||
/* NROM-128 */
|
||||
if (mode & 1) {
|
||||
setprg16(0x8000, prg >> 1);
|
||||
setprg16(0xC000, prg >> 1);
|
||||
/* NROM-256 */
|
||||
} else
|
||||
setprg32(0x8000, prg >> 2);
|
||||
setchr8(chr);
|
||||
setmirror(((mode >> 4) & 1) ^ 1);
|
||||
}
|
||||
|
||||
static DECLFW(M403Write4) {
|
||||
reg[A & 3] = V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFW(M403Write8) {
|
||||
if (reg[2] & 4) {
|
||||
reg[1] = V;
|
||||
Sync();
|
||||
}
|
||||
}
|
||||
|
||||
static void M403Reset(void) {
|
||||
reg[0] = reg[1] = reg[2] = 0;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M403Power(void) {
|
||||
reg[0] = reg[1] = reg[2] = 0;
|
||||
Sync();
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR); /* For TetrisA (Tetris Family 19-in-1 NO 1683) */
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x4100, 0x4103, M403Write4);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M403Write8);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper403_Init(CartInfo *info) {
|
||||
info->Reset = M403Reset;
|
||||
info->Power = M403Power;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(®, 3, 0, "REGS");
|
||||
}
|
||||
89
src/boards/410.c
Normal file
89
src/boards/410.c
Normal file
@@ -0,0 +1,89 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* NES 2.0 Mapper 410 is a variant of mapper 45 where the
|
||||
* ASIC's PRG A21/CHR A20 output (set by bit 6 of the third write to $6000)
|
||||
* selects between regularly-banked CHR-ROM (=0) and 8 KiB of unbanked CHR-RAM (=1).
|
||||
* It is used solely for the Super 8-in-1 - 98格鬥天王+熱血 (JY-302) multicart.
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 *CHRRAM;
|
||||
|
||||
static void M410CW(uint32 A, uint8 V) {
|
||||
if (!(EXPREGS[2] & 0x40)) {
|
||||
uint32 NV = V;
|
||||
NV &= (1 << ((EXPREGS[2] & 7) + 1)) - 1;
|
||||
NV |= EXPREGS[0] | ((EXPREGS[2] & 0xF0) << 4);
|
||||
setchr1(A, NV);
|
||||
} else
|
||||
setchr8r(0x10, 0);
|
||||
}
|
||||
|
||||
static void M410PW(uint32 A, uint8 V) {
|
||||
uint32 MV = V & ((EXPREGS[3] & 0x3F) ^ 0x3F);
|
||||
MV |= EXPREGS[1];
|
||||
MV |= ((EXPREGS[2] & 0x40) << 2);
|
||||
setprg8(A, MV);
|
||||
/* FCEU_printf("1:%02x 2:%02x 3:%02x A=%04x V=%03x\n",EXPREGS[1],EXPREGS[2],EXPREGS[3],A,MV); */
|
||||
}
|
||||
|
||||
static DECLFW(M410Write) {
|
||||
EXPREGS[EXPREGS[4]] = V;
|
||||
EXPREGS[4] = (EXPREGS[4] + 1) & 3;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void M410Close(void) {
|
||||
GenMMC3Close();
|
||||
if (CHRRAM)
|
||||
FCEU_free(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
}
|
||||
|
||||
static void M410Reset(void) {
|
||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[3] = EXPREGS[4] = 0;
|
||||
EXPREGS[2] = 0x0F;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void M410Power(void) {
|
||||
GenMMC3Power();
|
||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[3] = EXPREGS[4] = 0;
|
||||
EXPREGS[2] = 0x0F;
|
||||
SetWriteHandler(0x6000, 0x7FFF, M410Write);
|
||||
}
|
||||
|
||||
void Mapper410_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 512, 256, 8, info->battery);
|
||||
cwrap = M410CW;
|
||||
pwrap = M410PW;
|
||||
info->Reset = M410Reset;
|
||||
info->Power = M410Power;
|
||||
info->Close = M410Close;
|
||||
AddExState(EXPREGS, 5, 0, "EXPR");
|
||||
|
||||
CHRRAM = (uint8*)FCEU_gmalloc(8192);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, 8192, 1);
|
||||
AddExState(CHRRAM, 8192, 0, "CRAM");
|
||||
}
|
||||
85
src/boards/411.c
Normal file
85
src/boards/411.c
Normal file
@@ -0,0 +1,85 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
/* Mapper 411 - A88S-1
|
||||
* 1997 Super 7-in-1 (JY-201)
|
||||
* 1997 Super 6-in-1 (JY-202)
|
||||
* 1997 Super 7-in-1 (JY-203)
|
||||
* 1997 龍珠武鬥會 7-in-1 (JY-204)
|
||||
* 1997 Super 7-in-1 (JY-205)
|
||||
* 1997 Super 7-in-1 (JY-206)
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static void M411CW(uint32 A, uint8 V) {
|
||||
uint32 mask = (EXPREGS[1] & 2) ? 0xFF : 0x7F;
|
||||
V &= mask;
|
||||
setchr1(A, V | ((EXPREGS[1] << 5) & 0x80) | ((EXPREGS[0] << 4) & 0x100));
|
||||
}
|
||||
|
||||
static void M411PW(uint32 A, uint8 V) {
|
||||
/* NROM Mode */
|
||||
if (EXPREGS[0] & 0x40)
|
||||
{
|
||||
uint32 bank = (EXPREGS[0] & 1) | ((EXPREGS[0] >> 2) & 2) | (EXPREGS[0] & 4) | (EXPREGS[1] & 8) | ((EXPREGS[1] >> 2) & 0x10);
|
||||
|
||||
/* NROM-256 */
|
||||
if (EXPREGS[0] & 0x02) {
|
||||
setprg32(0x8000, bank >> 1);
|
||||
|
||||
/* NROM-128 */
|
||||
} else {
|
||||
setprg16(0x8000, bank);
|
||||
setprg16(0xC000, bank);
|
||||
}
|
||||
}
|
||||
|
||||
/* MMC3 Mode */
|
||||
else
|
||||
{
|
||||
uint32 mask = (EXPREGS[1] & 2) ? 0x1F : 0x0F;
|
||||
V &= mask;
|
||||
setprg8(A, V | ((EXPREGS[1] << 1) & 0x10) | ((EXPREGS[1] >> 1) & 0x20));
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(M411Write5000) {
|
||||
EXPREGS[A & 1] = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void M411Power(void) {
|
||||
EXPREGS[0] = 0x80;
|
||||
EXPREGS[1] = 0x82;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x5000, 0x5FFF, M411Write5000);
|
||||
}
|
||||
|
||||
void Mapper411_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 256, 256, 0, 0);
|
||||
pwrap = M411PW;
|
||||
cwrap = M411CW;
|
||||
info->Power = M411Power;
|
||||
AddExState(EXPREGS, 2, 0, "EXPR");
|
||||
}
|
||||
64
src/boards/414.c
Normal file
64
src/boards/414.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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 latch_data;
|
||||
static uint32 latch_addr;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &latch_addr, 4, "ADDR" },
|
||||
{ &latch_data, 1, "DATA" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
if (latch_addr & 0x2000) { /* NROM-256 */
|
||||
setprg32(0x8000, latch_addr >> 2);
|
||||
} else { /* NROM-128 */
|
||||
setprg16(0x8000, latch_addr >> 1);
|
||||
setprg16(0xC000, latch_addr >> 1);
|
||||
}
|
||||
setchr8(latch_data);
|
||||
setmirror((latch_addr & 1) ^ 1);
|
||||
}
|
||||
|
||||
static DECLFW(M414Write) {
|
||||
latch_addr = A;
|
||||
latch_data = V & CartBR(A);
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M414Power(void) {
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M414Write);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper414_Init(CartInfo *info) {
|
||||
info->Power = M414Power;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
111
src/boards/416.c
Normal file
111
src/boards/416.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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 reg;
|
||||
static uint8 smb2j_reg;
|
||||
static uint8 IRQa;
|
||||
static uint16 IRQCount;
|
||||
|
||||
static void Sync(void) {
|
||||
if (reg & 8) {
|
||||
uint8 prg = ((reg >> 5) & 1) | ((reg >> 6) & 2) | ((reg >> 1) & 4);
|
||||
switch ((reg >> 6) & 3) {
|
||||
case 0:
|
||||
setprg8(0x8000, prg << 1);
|
||||
setprg8(0xA000, prg << 1);
|
||||
setprg8(0xC000, prg << 1);
|
||||
setprg8(0xE000, prg << 1);
|
||||
break;
|
||||
case 1:
|
||||
setprg16(0x8000, prg);
|
||||
setprg16(0xC000, prg);
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
setprg32(0x8000, prg >> 1);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
setprg8(0x8000, 0x0);
|
||||
setprg8(0xA000, 0x1);
|
||||
setprg8(0xC000, smb2j_reg);
|
||||
setprg8(0xE000, 0x3);
|
||||
}
|
||||
setprg8(0x6000, 0x7);
|
||||
setchr8((reg >> 1) & 3);
|
||||
setmirror(((reg >> 2) & 1) ^ 1);
|
||||
}
|
||||
|
||||
static DECLFW(M416Write4) {
|
||||
switch (A & 0xD160) {
|
||||
case 0x4120:
|
||||
IRQa = V & 1;
|
||||
if (!IRQa)
|
||||
IRQCount = 0;
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
break;
|
||||
case 0x4020:
|
||||
smb2j_reg = ((V & 1) << 2) | ((V & 6) >> 1);
|
||||
Sync();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(M416Write8) {
|
||||
reg = V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M416Power(void) {
|
||||
reg = smb2j_reg = IRQa = IRQCount = 0;
|
||||
Sync();
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x4020, 0x5FFF, M416Write4);
|
||||
SetWriteHandler(0x8000, 0x8000, M416Write8);
|
||||
}
|
||||
|
||||
static void FP_FASTAPASS(1) M416IRQHook(int a) {
|
||||
if (IRQa) {
|
||||
if (IRQCount < 4096)
|
||||
IRQCount += a;
|
||||
else {
|
||||
IRQa = 0;
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper416_Init(CartInfo *info) {
|
||||
info->Power = M416Power;
|
||||
MapIRQHook = M416IRQHook;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(®, 1, 0, "REGS");
|
||||
AddExState(&smb2j_reg, 1, 0, "SMBJ");
|
||||
AddExState(&IRQa, 1, 0, "IRQa");
|
||||
AddExState(&IRQCount, 2, 0, "IRQC");
|
||||
}
|
||||
80
src/boards/417.c
Normal file
80
src/boards/417.c
Normal file
@@ -0,0 +1,80 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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 preg[4];
|
||||
static uint8 creg[8];
|
||||
static uint8 nt[4];
|
||||
static uint8 IRQa;
|
||||
static uint16 IRQCount;
|
||||
|
||||
static SFORMAT StateRegs[] = {
|
||||
{ preg, 4, "PREG" },
|
||||
{ creg, 8, "CREG" },
|
||||
{ nt, 4, "NREG" },
|
||||
{ &IRQa, 1, "IRQA" },
|
||||
{ &IRQCount, 2, "IRQC" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
int i;
|
||||
setprg8(0x8000, preg[0]);
|
||||
setprg8(0xA000, preg[1]);
|
||||
setprg8(0xC000, preg[2]);
|
||||
setprg8(0xE000, ~0);
|
||||
for (i = 0; i < 8; i++) setchr1(i << 10, creg[i]);
|
||||
setmirrorw(nt[0] & 1, nt[1] & 1, nt[2] & 1, nt[3] & 1);
|
||||
}
|
||||
|
||||
static DECLFW(M417Write) {
|
||||
switch ((A >> 4) & 7) {
|
||||
case 0: preg[A & 3] = V; Sync(); break;
|
||||
case 1: creg[0 | (A & 3)] = V; Sync(); break;
|
||||
case 2: creg[4 | (A & 3)] = V; Sync(); break;break;
|
||||
case 3: IRQCount = 0; IRQa = 1; break;
|
||||
case 4: IRQa = 0; X6502_IRQEnd(FCEU_IQEXT); break;
|
||||
case 5: nt[A & 3] = V; Sync(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void M417Power(void) {
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M417Write);
|
||||
}
|
||||
|
||||
static void M417IRQHook(int a) {
|
||||
IRQCount += a;
|
||||
if (IRQa && IRQCount > 1024)
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper417_Init(CartInfo *info) {
|
||||
info->Power = M417Power;
|
||||
MapIRQHook = M417IRQHook;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
static uint8 regs[4];
|
||||
static uint8 hrd_flag;
|
||||
static void(*Sync)(void);
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
@@ -34,7 +33,8 @@ static SFORMAT StateRegs[] =
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void SyncAbG1l(void) {
|
||||
static void Sync(void) {
|
||||
int mask = regs[2] >> 6; /* There is an CNROM mode that takes either two or four inner CHR banks from a CNROM-like latch register at $8000-$FFFF. */
|
||||
|
||||
if (regs[1] & 0x10)
|
||||
setprg32(0x8000,(regs[1] & 0xC0) >> 6);
|
||||
@@ -44,37 +44,36 @@ static void SyncAbG1l(void) {
|
||||
setprg16(0xC000, (regs[1] & 0xE0) >> 5);
|
||||
}
|
||||
|
||||
setchr8(regs[1]);
|
||||
setchr8(((regs[1] & 0x07) & ~mask) | regs[0] & mask);
|
||||
|
||||
setmirror((regs[1] & 0x8) ? 0 : 1);
|
||||
|
||||
}
|
||||
|
||||
static DECLFW(AbG1lWriteHi) {
|
||||
static DECLFW(WriteHi) {
|
||||
regs[0] = V;
|
||||
setchr8(((regs[2] & 0xC0) >> 7) << 2 | (regs[0] & 0x03));
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFW(AbG1lWriteLo) {
|
||||
static DECLFW(WriteLo) {
|
||||
regs[A & 0x03] = V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFR(AbG1lReadLo) {
|
||||
static DECLFR(ReadLo) {
|
||||
return hrd_flag;
|
||||
}
|
||||
|
||||
static void AbG1lPower(void) {
|
||||
hrd_flag = 0;
|
||||
static void Power(void) {
|
||||
hrd_flag = 0; /* Solder pad, selecting different menus */
|
||||
|
||||
regs[0] = 0;
|
||||
regs[1] = 0;
|
||||
regs[2] = 0;
|
||||
|
||||
Sync();
|
||||
SetWriteHandler(0x8000, 0xFFFF, AbG1lWriteHi);
|
||||
SetWriteHandler(0x6001, 0x6002, AbG1lWriteLo);
|
||||
SetReadHandler(0x6000, 0x7FFF, AbG1lReadLo);
|
||||
SetWriteHandler(0x8000, 0xFFFF, WriteHi);
|
||||
SetWriteHandler(0x6001, 0x6002, WriteLo);
|
||||
SetReadHandler(0x6000, 0x7FFF, ReadLo);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
}
|
||||
|
||||
@@ -82,7 +81,7 @@ static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void AbG1lReset(void) {
|
||||
static void Reset(void) {
|
||||
hrd_flag++;
|
||||
hrd_flag &= 3;
|
||||
|
||||
@@ -93,64 +92,14 @@ static void AbG1lReset(void) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void AbG1l_Init(CartInfo *info) {
|
||||
|
||||
Sync = SyncAbG1l;
|
||||
|
||||
void Mapper428_Init(CartInfo *info) {
|
||||
hrd_flag = 0;
|
||||
|
||||
Sync();
|
||||
|
||||
info->Power = AbG1lPower;
|
||||
info->Reset = AbG1lReset;
|
||||
info->Power = Power;
|
||||
info->Reset = Reset;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
GameStateRestore = StateRestore;
|
||||
}
|
||||
|
||||
|
||||
static void SyncWellNoDG450(void) {
|
||||
|
||||
if (regs[1] & 0x10)
|
||||
setprg32(0x8000, (regs[1]) >> 6);
|
||||
else
|
||||
{
|
||||
setprg16(0x8000, (regs[1]) >> 5);
|
||||
setprg16(0xC000, (regs[1]) >> 5);
|
||||
}
|
||||
|
||||
setchr8(regs[1] & 0x0F);
|
||||
setmirror((regs[1] & 0x8) ? 0 : 1);
|
||||
}
|
||||
|
||||
static void WellNoDG450Power(void) {
|
||||
hrd_flag = 0;
|
||||
|
||||
regs[0] = 0;
|
||||
regs[1] = 0;
|
||||
regs[2] = 0;
|
||||
|
||||
Sync();
|
||||
|
||||
SetWriteHandler(0x6001, 0x6002, AbG1lWriteLo);
|
||||
SetReadHandler(0x6000, 0x7FFF, AbG1lReadLo);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
}
|
||||
|
||||
static void WellNoDG450Reset(void) {
|
||||
hrd_flag++;
|
||||
hrd_flag &= 3;
|
||||
|
||||
regs[0] = 0;
|
||||
regs[1] = 0;
|
||||
regs[2] = 0;
|
||||
|
||||
Sync();
|
||||
}
|
||||
|
||||
void WellNoDG450_Init(CartInfo *info) {
|
||||
Sync = SyncWellNoDG450;
|
||||
info->Power = WellNoDG450Power;
|
||||
info->Reset = WellNoDG450Reset;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
GameStateRestore = StateRestore;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2007 CaH4e3
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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
|
||||
@@ -20,44 +20,43 @@
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 reg, mirr;
|
||||
static uint8 inner_bank;
|
||||
static uint8 outer_bank;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ ®, 1, "REGS" },
|
||||
{ &mirr, 1, "MIRR" },
|
||||
{ &outer_bank, 1, "OUTB" },
|
||||
{ &inner_bank, 1, "INNB" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setprg8(0x6000, 32);
|
||||
setprg32(0x8000, reg);
|
||||
setprg16(0x8000, ((outer_bank >> 2) & ~7) | (inner_bank & 7));
|
||||
setprg16(0xC000, ((outer_bank >> 2) & ~7) | 7);
|
||||
setchr8(0);
|
||||
setmirror((outer_bank & 1) ^ 1);
|
||||
}
|
||||
|
||||
static DECLFW(BMCGS2004Write) {
|
||||
reg = V;
|
||||
static DECLFW(M431Write) {
|
||||
if (A < 0xC000) outer_bank = V;
|
||||
else inner_bank = V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void BMCGS2004Power(void) {
|
||||
reg = 0x07;
|
||||
static void M431Power(void) {
|
||||
inner_bank = 0;
|
||||
outer_bank = 0;
|
||||
Sync();
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, BMCGS2004Write);
|
||||
}
|
||||
|
||||
static void BMCGS2004Reset(void) {
|
||||
reg = 0x07;
|
||||
SetWriteHandler(0x8000, 0xFFFF, M431Write);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void BMCGS2004_Init(CartInfo *info) {
|
||||
info->Reset = BMCGS2004Reset;
|
||||
info->Power = BMCGS2004Power;
|
||||
void Mapper431_Init(CartInfo *info) {
|
||||
info->Power = M431Power;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
75
src/boards/432.c
Normal file
75
src/boards/432.c
Normal file
@@ -0,0 +1,75 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* 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"
|
||||
#include "mmc3.h"
|
||||
|
||||
static void M432CW(uint32 A, uint8 V) {
|
||||
int chrAND = (EXPREGS[1] & 0x04) ? 0x7F : 0xFF;
|
||||
int chrOR = (EXPREGS[1] << 7) & 0x080 | (EXPREGS[1] << 5) & 0x100 | (EXPREGS[1] << 4) & 0x200;
|
||||
setchr1(A, (V & chrAND) | (chrOR & ~chrAND));
|
||||
}
|
||||
|
||||
static void M432PW(uint32 A, uint8 V) {
|
||||
int prgAND = (EXPREGS[1] & 0x02) ? 0x0F : 0x1F;
|
||||
int prgOR = ((EXPREGS[1] << 4) & 0x10) | (EXPREGS[1] << 1) & 0x60;
|
||||
if ((A < 0xC000) || (~EXPREGS[1] & 0x40)) setprg8(A, (V & prgAND) | (prgOR & ~prgAND) & (EXPREGS[1] & 0x80?~2:~0));
|
||||
if ((A < 0xC000) && (EXPREGS[1] & 0x40)) setprg8(A | 0x4000, (V & prgAND) | (prgOR & ~prgAND) | (EXPREGS[1] & 0x80? 2: 0));
|
||||
}
|
||||
|
||||
static DECLFR(M432Read) {
|
||||
if (EXPREGS[0] & 1 || EXPREGS[1] & 0x20 && ROM_size <64)
|
||||
return EXPREGS[2];
|
||||
return CartBR(A);
|
||||
}
|
||||
|
||||
static DECLFW(M432Write) {
|
||||
EXPREGS[A & 1] = V;
|
||||
if (~A &1 && ~V &1 && ROM_size <64) EXPREGS[1] &=~0x20; /* Writing 0 to register 0 clears register 1's DIP bit */
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void M432Reset(void) {
|
||||
EXPREGS[0] = 0;
|
||||
EXPREGS[1] = 0;
|
||||
EXPREGS[2]++;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void M432Power(void) {
|
||||
EXPREGS[0] = 0;
|
||||
EXPREGS[1] = 0;
|
||||
EXPREGS[2] = 0;
|
||||
GenMMC3Power();
|
||||
SetReadHandler(0x8000, 0xFFFF, M432Read);
|
||||
SetWriteHandler(0x6000, 0x7FFF, M432Write);
|
||||
}
|
||||
|
||||
void Mapper432_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 256, 256, 0, 0);
|
||||
cwrap = M432CW;
|
||||
pwrap = M432PW;
|
||||
info->Power = M432Power;
|
||||
info->Reset = M432Reset;
|
||||
AddExState(EXPREGS, 3, 0, "EXPR");
|
||||
}
|
||||
72
src/boards/433.c
Normal file
72
src/boards/433.c
Normal file
@@ -0,0 +1,72 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
/* NES 2.0 Mapper 433 denotes the NC-20MB PCB, used for the 20-in-1 (CA-006) multicart. It is almost identical to INES Mapper 433, except that mirroring is selected just by single bit 6 (1=Horizontal).
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 latche;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &latche, 1, "LATC" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
if (!(latche & 0x20))
|
||||
setprg32(0x8000, (latche & 0x1f) >> 1);
|
||||
else {
|
||||
setprg16(0x8000, (latche & 0x1f));
|
||||
setprg16(0xC000, (latche & 0x1f));
|
||||
}
|
||||
setmirror(((latche >> 6) & 1) ^ 1);
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
static DECLFW(M433Write) {
|
||||
latche = V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M433Power(void) {
|
||||
latche = 0;
|
||||
Sync();
|
||||
SetWriteHandler(0x8000, 0xFFFF, M433Write);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M433Reset(void) {
|
||||
latche = 0;
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper433_Init(CartInfo *info) {
|
||||
info->Power = M433Power;
|
||||
info->Reset = M433Reset;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
GameStateRestore = StateRestore;
|
||||
}
|
||||
67
src/boards/434.c
Normal file
67
src/boards/434.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2012 CaH4e3
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* S-009. UNROM plus outer bank register at $6000-$7FFF. */
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint16 latch;
|
||||
|
||||
static void Mapper434_Sync(void) {
|
||||
setprg16(0x8000, latch);
|
||||
setprg16(0xC000, latch |7);
|
||||
setchr8(0);
|
||||
setmirror(latch >>8 &1);
|
||||
}
|
||||
|
||||
static DECLFW(Mapper434_WriteOuterBank) {
|
||||
latch =latch &7 | V <<3;
|
||||
Mapper434_Sync();
|
||||
}
|
||||
|
||||
static DECLFW(Mapper434_WriteInnerBank) {
|
||||
latch =latch &~7 | V &CartBR(A) &7;
|
||||
Mapper434_Sync();
|
||||
}
|
||||
|
||||
static void Mapper434_Reset(void) {
|
||||
latch =0;
|
||||
Mapper434_Sync();
|
||||
}
|
||||
|
||||
static void Mapper434_Power(void) {
|
||||
latch =0;
|
||||
Mapper434_Sync();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, Mapper434_WriteOuterBank);
|
||||
SetWriteHandler(0x8000, 0xFFFF, Mapper434_WriteInnerBank);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Mapper434_Sync();
|
||||
}
|
||||
|
||||
void Mapper434_Init(CartInfo *info) {
|
||||
info->Reset = Mapper434_Reset;
|
||||
info->Power = Mapper434_Power;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&latch, 2, 0, "LATC");
|
||||
}
|
||||
63
src/boards/436.c
Normal file
63
src/boards/436.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2008 CaH4e3
|
||||
* Copyright (C) 2019 Libretro Team
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* NES 2.0 Mapper 436: 820401/T-217 */
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static void Mapper436_PWrap(uint32 A, uint8 V) {
|
||||
if (EXPREGS[0] &0x01)
|
||||
setprg8(A, V &0x0F | EXPREGS[0] >>2 &0x30);
|
||||
else
|
||||
if (A == 0x8000)
|
||||
setprg32(A, (EXPREGS[0] >>4));
|
||||
}
|
||||
|
||||
static void Mapper436_CWrap(uint32 A, uint8 V) {
|
||||
setchr1(A, V &0x7F | EXPREGS[0] <<1 &~0x7F);
|
||||
}
|
||||
|
||||
static DECLFW(Mapper436_Write) {
|
||||
EXPREGS[0] = A &0xFF;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void Mapper436_Reset(void) {
|
||||
EXPREGS[0] = 0;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void Mapper436_Power(void) {
|
||||
EXPREGS[0] = 0;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x6000, 0x7FFF, Mapper436_Write);
|
||||
}
|
||||
|
||||
void Mapper436_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 128, 128, 8, 0);
|
||||
pwrap = Mapper436_PWrap;
|
||||
cwrap = Mapper436_CWrap;
|
||||
info->Power = Mapper436_Power;
|
||||
info->Reset = Mapper436_Reset;
|
||||
AddExState(EXPREGS, 1, 0, "EXPR");
|
||||
}
|
||||
67
src/boards/437.c
Normal file
67
src/boards/437.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2012 CaH4e3
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* NTDEC TH2348 circuit board. UNROM plus outer bank register at $5FFx. */
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 latch;
|
||||
|
||||
static void Mapper437_Sync(void) {
|
||||
setprg16(0x8000, latch);
|
||||
setprg16(0xC000, latch |7);
|
||||
setchr8(0);
|
||||
setmirror(latch >>6 &1 ^1);
|
||||
}
|
||||
|
||||
static DECLFW(Mapper437_WriteOuterBank) {
|
||||
latch =latch &7 | A <<3;
|
||||
Mapper437_Sync();
|
||||
}
|
||||
|
||||
static DECLFW(Mapper437_WriteInnerBank) {
|
||||
latch =latch &~7 | V &CartBR(A) &7;
|
||||
Mapper437_Sync();
|
||||
}
|
||||
|
||||
static void Mapper437_Reset(void) {
|
||||
latch =0;
|
||||
Mapper437_Sync();
|
||||
}
|
||||
|
||||
static void Mapper437_Power(void) {
|
||||
latch =0;
|
||||
Mapper437_Sync();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x5000, 0x5FFF, Mapper437_WriteOuterBank);
|
||||
SetWriteHandler(0x8000, 0xFFFF, Mapper437_WriteInnerBank);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Mapper437_Sync();
|
||||
}
|
||||
|
||||
void Mapper437_Init(CartInfo *info) {
|
||||
info->Reset = Mapper437_Reset;
|
||||
info->Power = Mapper437_Power;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&latch, 1, 0, "LATC");
|
||||
}
|
||||
67
src/boards/438.c
Normal file
67
src/boards/438.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2012 CaH4e3
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* K-3071 */
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 latch[2];
|
||||
|
||||
static void Mapper438_Sync(void) {
|
||||
if (latch[0] &1)
|
||||
setprg32(0x8000, latch[0] >>2);
|
||||
else {
|
||||
setprg16(0x8000, latch[0] >>1);
|
||||
setprg16(0xC000, latch[0] >>1);
|
||||
}
|
||||
setchr8(latch[1] >>1);
|
||||
setmirror(latch[1] &1 ^1);
|
||||
|
||||
}
|
||||
|
||||
static DECLFW(Mapper438_WriteLatch) {
|
||||
latch[0] =A &0xFF;
|
||||
latch[1] =V;
|
||||
Mapper438_Sync();
|
||||
}
|
||||
|
||||
static void Mapper438_Reset(void) {
|
||||
latch[0] =latch[1] =0;
|
||||
Mapper438_Sync();
|
||||
}
|
||||
|
||||
static void Mapper438_Power(void) {
|
||||
latch[0] =latch[1] =0;
|
||||
Mapper438_Sync();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, Mapper438_WriteLatch);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Mapper438_Sync();
|
||||
}
|
||||
|
||||
void Mapper438_Init(CartInfo *info) {
|
||||
info->Reset = Mapper438_Reset;
|
||||
info->Power = Mapper438_Power;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&latch, 2, 0, "LATC");
|
||||
}
|
||||
68
src/boards/441.c
Normal file
68
src/boards/441.c
Normal file
@@ -0,0 +1,68 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* 850335C PCB */
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static void Mapper441_PRGWrap(uint32 A, uint8 V) {
|
||||
int prgAND =EXPREGS[0] &0x08? 0x0F: 0x1F;
|
||||
int prgOR =EXPREGS[0] <<4 &0x30;
|
||||
if (EXPREGS[0] &0x04) {
|
||||
if (~A &0x4000) {
|
||||
setprg8(A, ~2 &V &prgAND | prgOR &~prgAND);
|
||||
setprg8(A |0x4000, 2 |V &prgAND | prgOR &~prgAND);
|
||||
}
|
||||
} else
|
||||
setprg8(A, V &prgAND | prgOR &~prgAND);
|
||||
}
|
||||
|
||||
static void Mapper441_CHRWrap(uint32 A, uint8 V) {
|
||||
int chrAND =EXPREGS[0] &0x40? 0x7F: 0xFF;
|
||||
int chrOR =EXPREGS[0] <<3 &0x180;
|
||||
setchr1(A, V &chrAND | chrOR &~chrAND);
|
||||
}
|
||||
|
||||
static DECLFW(Mapper441_Write) {
|
||||
if (~EXPREGS[0] &0x80) EXPREGS[0] =V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void Mapper441_Reset(void) {
|
||||
EXPREGS[0] =0;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void Mapper441_Power(void) {
|
||||
EXPREGS[0] =0;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x6000, 0x7FFF, Mapper441_Write);
|
||||
}
|
||||
|
||||
void Mapper441_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 256, 256, 0, 0);
|
||||
cwrap = Mapper441_CHRWrap;
|
||||
pwrap = Mapper441_PRGWrap;
|
||||
info->Power = Mapper441_Power;
|
||||
info->Reset = Mapper441_Reset;
|
||||
AddExState(EXPREGS, 1, 0, "EXPR");
|
||||
}
|
||||
79
src/boards/443.c
Normal file
79
src/boards/443.c
Normal file
@@ -0,0 +1,79 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* NC3000M PCB */
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 dip;
|
||||
|
||||
static void Mapper443_PRGWrap(uint32 A, uint8 V) {
|
||||
int prgAND =0x0F;
|
||||
int prgOR =EXPREGS[0] <<4 &0x20 | EXPREGS[0] &0x10;
|
||||
if (EXPREGS[0] &0x04) {
|
||||
if (~A &0x4000) {
|
||||
setprg8(A, (~EXPREGS[0] &0x08? ~2: ~0) &V &prgAND | prgOR &~prgAND);
|
||||
setprg8(A |0x4000, (~EXPREGS[0] &0x08? 2: 0) |V &prgAND | prgOR &~prgAND);
|
||||
}
|
||||
} else
|
||||
setprg8(A, V &prgAND | prgOR &~prgAND);
|
||||
}
|
||||
|
||||
static void Mapper443_CHRWrap(uint32 A, uint8 V) {
|
||||
int chrAND =0xFF;
|
||||
int chrOR =EXPREGS[0] <<8;
|
||||
setchr1(A, V &chrAND | chrOR &~chrAND);
|
||||
}
|
||||
|
||||
static DECLFR(Mapper443_Read) {
|
||||
return (EXPREGS[0] &0x0C) ==0x08? dip: CartBR(A);
|
||||
}
|
||||
|
||||
static DECLFW(Mapper443_Write) {
|
||||
EXPREGS[0] =A &0xFF;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void Mapper443_Reset(void) {
|
||||
dip++;
|
||||
dip &= 15;
|
||||
EXPREGS[0] =0;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void Mapper443_Power(void) {
|
||||
dip =0;
|
||||
EXPREGS[0] =0;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x6000, 0x7FFF, Mapper443_Write);
|
||||
SetReadHandler(0x8000, 0xFFFF, Mapper443_Read);
|
||||
}
|
||||
|
||||
void Mapper443_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 256, 256, 0, 0);
|
||||
cwrap = Mapper443_CHRWrap;
|
||||
pwrap = Mapper443_PRGWrap;
|
||||
info->Power = Mapper443_Power;
|
||||
info->Reset = Mapper443_Reset;
|
||||
AddExState(EXPREGS, 1, 0, "EXPR");
|
||||
AddExState(&dip, 1, 0, "DIPS");
|
||||
}
|
||||
82
src/boards/444.c
Normal file
82
src/boards/444.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* NC7000M PCB, with incorrect UNIF MAPR BS-110 due to a mix-up. Submapper bits 0 and 1. denote the setting of two solder pads that configure CHR banking. */
|
||||
/* NC8000M PCB, indicated by submapper bit 2. */
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 pads;
|
||||
static uint8 dip;
|
||||
|
||||
static void Mapper444_PRGWrap(uint32 A, uint8 V) {
|
||||
int prgAND =pads &4 && EXPREGS[0] &0x02? 0x1F: 0x0F;
|
||||
int prgOR =EXPREGS[0] <<4;
|
||||
if (EXPREGS[0] &0x04) {
|
||||
if (~A &0x4000) {
|
||||
setprg8(A, (~EXPREGS[0] &0x08? ~2: ~0) &V &prgAND | prgOR &~prgAND);
|
||||
setprg8(A |0x4000, (~EXPREGS[0] &0x08? 2: 0) |V &prgAND | prgOR &~prgAND);
|
||||
}
|
||||
} else
|
||||
setprg8(A, V &prgAND | prgOR &~prgAND);
|
||||
}
|
||||
|
||||
static void Mapper444_CHRWrap(uint32 A, uint8 V) {
|
||||
int chrAND =pads &1? 0xFF: 0x7F;
|
||||
int chrOR =EXPREGS[0] <<7 &(pads &1? 0x00: 0x80) | EXPREGS[0] <<(pads &2? 4: 7) &0x100;
|
||||
setchr1(A, V &chrAND | chrOR &~chrAND);
|
||||
}
|
||||
|
||||
static DECLFR(Mapper444_Read) {
|
||||
return (EXPREGS[0] &0x0C) ==0x08? dip: CartBR(A);
|
||||
}
|
||||
|
||||
static DECLFW(Mapper444_Write) {
|
||||
EXPREGS[0] =A &0xFF;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void Mapper444_Reset(void) {
|
||||
dip++;
|
||||
dip &= 3;
|
||||
EXPREGS[0] =0;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void Mapper444_Power(void) {
|
||||
dip =0;
|
||||
EXPREGS[0] =0;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x6000, 0x7FFF, Mapper444_Write);
|
||||
SetReadHandler(0x8000, 0xFFFF, Mapper444_Read);
|
||||
}
|
||||
|
||||
void Mapper444_Init(CartInfo *info) {
|
||||
pads = info->submapper; /* UNIF represents submapper 0 */
|
||||
GenMMC3_Init(info, 256, 256, 0, 0);
|
||||
cwrap = Mapper444_CHRWrap;
|
||||
pwrap = Mapper444_PRGWrap;
|
||||
info->Power = Mapper444_Power;
|
||||
info->Reset = Mapper444_Reset;
|
||||
AddExState(EXPREGS, 1, 0, "EXPR");
|
||||
AddExState(&dip, 1, 0, "DIPS");
|
||||
}
|
||||
95
src/boards/449.c
Normal file
95
src/boards/449.c
Normal file
@@ -0,0 +1,95 @@
|
||||
/* FCEUmm - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2022
|
||||
*
|
||||
* 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 uint16 latchAddr;
|
||||
static uint8 latchData;
|
||||
static uint8 dipswitch;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &latchAddr, 2, "ADDR" },
|
||||
{ &latchData, 1, "DATA" },
|
||||
{ &latchData, 1, "DIPS" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Mapper449_Sync(void)
|
||||
{
|
||||
int prg =latchAddr >>2 &0x1F | latchAddr >>3 &0x20;
|
||||
if (~latchAddr &0x080)
|
||||
{
|
||||
setprg16(0x8000, prg);
|
||||
setprg16(0xC000, prg |7);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (latchAddr &0x001)
|
||||
{
|
||||
setprg32(0x8000, prg >>1);
|
||||
}
|
||||
else
|
||||
{
|
||||
setprg16(0x8000, prg);
|
||||
setprg16(0xC000, prg);
|
||||
}
|
||||
}
|
||||
setchr8(latchData);
|
||||
setmirror(latchAddr &0x002? MI_H: MI_V);
|
||||
}
|
||||
|
||||
static DECLFR(Mapper449_Read)
|
||||
{
|
||||
if (latchAddr &0x200)
|
||||
return CartBR(A | dipswitch);
|
||||
else
|
||||
return CartBR(A);
|
||||
}
|
||||
|
||||
static DECLFW(Mapper449_WriteLatch)
|
||||
{
|
||||
latchData =V;
|
||||
latchAddr =A &0xFFFF;
|
||||
Mapper449_Sync();
|
||||
}
|
||||
|
||||
static void Mapper449_Reset(void)
|
||||
{
|
||||
dipswitch =(dipswitch +1) &0xF;
|
||||
latchAddr =latchData =0;
|
||||
Mapper449_Sync();
|
||||
}
|
||||
|
||||
static void Mapper449_Power(void)
|
||||
{
|
||||
dipswitch =latchAddr =latchData =0;
|
||||
Mapper449_Sync();
|
||||
SetWriteHandler(0x8000, 0xFFFF, Mapper449_WriteLatch);
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetReadHandler(0x8000, 0xFFFF, Mapper449_Read);
|
||||
}
|
||||
|
||||
void Mapper449_Init(CartInfo *info)
|
||||
{
|
||||
info->Power = Mapper449_Power;
|
||||
info->Reset = Mapper449_Reset;
|
||||
AddExState(StateRegs, ~0, 0, 0);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user