├── .gitignore ├── jni ├── Application.mk └── Android.mk ├── link.T ├── intl ├── .gitignore ├── crowdin.yaml ├── upload_workflow.py ├── download_workflow.py ├── crowdin_prep.py ├── remove_initial_cycle.py ├── crowdin_translate.py ├── activate.py ├── crowdin_source_upload.py └── crowdin_translation_download.py ├── nes_emu ├── mappers │ ├── mapper026.hpp │ ├── mapper086.hpp │ ├── mapper152.hpp │ ├── mapper113.hpp │ ├── mapper154.hpp │ ├── mapper190.hpp │ ├── mapper000.hpp │ ├── mapper023.hpp │ ├── mapper025.hpp │ ├── mapper022.hpp │ ├── mapper156.hpp │ ├── mapper034.hpp │ ├── mapper003.hpp │ ├── mapper010.hpp │ ├── mapper002.hpp │ ├── mapper241.hpp │ ├── mapper180.hpp │ ├── mapper094.hpp │ ├── mapper009.hpp │ ├── mapper007.hpp │ ├── mapper011.hpp │ ├── mapper066.hpp │ ├── mapper087.hpp │ ├── mapper030.hpp │ ├── mapper093.hpp │ ├── mapper060.hpp │ ├── mapper071.hpp │ ├── mapper232.hpp │ ├── mapper089.hpp │ ├── mapper097.hpp │ ├── mapper078.hpp │ ├── mapper140.hpp │ ├── mapper240.hpp │ ├── mapper184.hpp │ ├── mapper244.hpp │ ├── mapper246.hpp │ ├── mapper193.hpp │ ├── mapper070.hpp │ ├── mapper079.hpp │ ├── mapper015.hpp │ ├── mapper206.hpp │ ├── mapper033.hpp │ ├── mapper207.hpp │ ├── mapper075.hpp │ ├── mapper001.hpp │ ├── mapper088.hpp │ ├── mapper032.hpp │ ├── mapper073.hpp │ └── mapper005.hpp ├── blargg_config.h ├── emu2413_state.h ├── nes_ntsc_config.h ├── Nes_Effects_Buffer.h ├── blargg_source.h ├── apu_state.h ├── Nes_Vrc7.h ├── Nes_Ppu_Rendering.h ├── Nes_Buffer.h ├── nes_data.cpp ├── nes_util.h ├── Nes_Ppu_Bg.h ├── Nes_Cart.h ├── blargg_common.h ├── Nes_Vrc6_Apu.h ├── Nes_Namco_Apu.h ├── Effects_Buffer.h ├── Nes_Effects_Buffer.cpp ├── Data_Reader.cpp ├── emu2413_state.cpp ├── abstract_file.cpp ├── abstract_file.h ├── Nes_Fme7_Apu.h ├── Nes_Cart.cpp ├── Nes_Fme7_Apu.cpp ├── Nes_File.h ├── Nes_Oscs.h ├── Nes_Core.h ├── nes_cpu_io.h ├── Nes_State.h ├── Nes_Cpu.h ├── Data_Reader.h ├── Nes_Ppu.h ├── Nes_Ppu_Sprites.h ├── blargg_endian.h └── nes_util.cpp ├── .travis.yml ├── .github └── workflows │ ├── crowdin_prep.yml │ ├── compilation.yml │ └── crowdin_translate.yml ├── Makefile.common └── libretro └── libretro-common └── include ├── retro_inline.h └── libretro_gskit_ps2.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.so 2 | *.dll 3 | *.dylib 4 | *.o 5 | -------------------------------------------------------------------------------- /jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_STL := c++_static 2 | APP_ABI := all 3 | -------------------------------------------------------------------------------- /link.T: -------------------------------------------------------------------------------- 1 | { 2 | global: retro_*; 3 | local: *; 4 | }; 5 | 6 | -------------------------------------------------------------------------------- /intl/.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | crowdin-cli.jar 3 | *.h 4 | *.json 5 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper026.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Konami VRC6 mapper 4 | 5 | // Nes_Emu 0.7.0. http://www.slack.net/~ant/ 6 | 7 | #include "Nes_Mapper.h" 8 | 9 | typedef Mapper_Vrc6<3> Mapper026; -------------------------------------------------------------------------------- /nes_emu/blargg_config.h: -------------------------------------------------------------------------------- 1 | // Library configuration. Modify this file as necessary. 2 | 3 | // File_Extractor 1.0.0 4 | #ifndef BLARGG_CONFIG_H 5 | #define BLARGG_CONFIG_H 6 | 7 | #define HAVE_STDINT_H 8 | 9 | // Use standard config.h if present 10 | #ifdef HAVE_CONFIG_H 11 | #include "config.h" 12 | #endif 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /intl/crowdin.yaml: -------------------------------------------------------------------------------- 1 | "project_id": "380544" 2 | "api_token": "_secret_" 3 | "base_url": "https://api.crowdin.com" 4 | "preserve_hierarchy": true 5 | 6 | "files": 7 | [ 8 | { 9 | "source": "/_core_name_/_us.json", 10 | "dest": "/_core_name_/_core_name_.json", 11 | "translation": "/_core_name_/_%two_letters_code%.json", 12 | }, 13 | ] 14 | -------------------------------------------------------------------------------- /intl/upload_workflow.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import subprocess 5 | 6 | try: 7 | api_key = sys.argv[1] 8 | core_name = sys.argv[2] 9 | dir_path = sys.argv[3] 10 | except IndexError as e: 11 | print('Please provide path to libretro_core_options.h, Crowdin API Token and core name!') 12 | raise e 13 | 14 | subprocess.run(['python3', 'intl/crowdin_prep.py', dir_path, core_name]) 15 | subprocess.run(['python3', 'intl/crowdin_source_upload.py', api_key, core_name]) 16 | -------------------------------------------------------------------------------- /intl/download_workflow.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import subprocess 5 | 6 | try: 7 | api_key = sys.argv[1] 8 | core_name = sys.argv[2] 9 | dir_path = sys.argv[3] 10 | except IndexError as e: 11 | print('Please provide path to libretro_core_options.h, Crowdin API Token and core name!') 12 | raise e 13 | 14 | subprocess.run(['python3', 'intl/crowdin_prep.py', dir_path, core_name]) 15 | subprocess.run(['python3', 'intl/crowdin_translation_download.py', api_key, core_name]) 16 | subprocess.run(['python3', 'intl/crowdin_translate.py', dir_path, core_name]) 17 | -------------------------------------------------------------------------------- /jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | CORE_DIR := $(LOCAL_PATH)/.. 4 | 5 | include $(CORE_DIR)/Makefile.common 6 | 7 | COREFLAGS := -DANDROID -D__LIBRETRO__ -Wall -Wno-multichar -Wno-unused-variable -Wno-sign-compare $(INCFLAGS) -DNO_UNALIGNED_ACCESS 8 | 9 | GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)" 10 | ifneq ($(GIT_VERSION)," unknown") 11 | COREFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" 12 | endif 13 | 14 | include $(CLEAR_VARS) 15 | LOCAL_MODULE := retro 16 | LOCAL_SRC_FILES := $(SOURCES_CXX) 17 | LOCAL_CXXFLAGS := $(COREFLAGS) 18 | LOCAL_LDFLAGS := -Wl,-version-script=$(CORE_DIR)/link.T 19 | include $(BUILD_SHARED_LIBRARY) 20 | -------------------------------------------------------------------------------- /nes_emu/emu2413_state.h: -------------------------------------------------------------------------------- 1 | #ifndef EMU2413_STATE_H 2 | #define EMU2413_STATE_H 3 | 4 | #include "emu2413.h" 5 | 6 | typedef struct { 7 | e_int32 feedback; 8 | e_int32 output[2]; 9 | e_uint32 phase; 10 | e_uint32 pgout; 11 | e_int32 eg_mode; 12 | e_uint32 eg_phase; 13 | e_uint32 eg_dphase; 14 | e_uint32 egout; 15 | } OPLL_SLOT_STATE; 16 | 17 | typedef struct { 18 | e_uint32 pm_phase; 19 | e_int32 am_phase; 20 | OPLL_SLOT_STATE slot[6 * 2]; 21 | } OPLL_STATE; 22 | 23 | #ifdef __cplusplus 24 | extern "C" 25 | { 26 | #endif 27 | 28 | int OPLL_serialize_size(); 29 | void OPLL_serialize(const OPLL * opll, OPLL_STATE* state); 30 | void OPLL_deserialize(OPLL * opll, const OPLL_STATE* state); 31 | void OPLL_state_byteswap(OPLL_STATE *state); 32 | 33 | #ifdef __cplusplus 34 | } 35 | #endif 36 | 37 | #endif -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: generic 2 | os: linux 3 | dist: trusty 4 | sudo: required 5 | addons: 6 | apt: 7 | packages: 8 | - g++-7 9 | sources: 10 | - ubuntu-toolchain-r-test 11 | env: 12 | global: 13 | - CORE=quicknes 14 | - COMPILER_NAME=gcc CXX=g++-7 CC=gcc-7 15 | matrix: 16 | - PLATFORM=3ds 17 | - PLATFORM=linux_x64 18 | - PLATFORM=ngc 19 | - PLATFORM=wii 20 | - PLATFORM=wiiu 21 | before_script: 22 | - pwd 23 | - mkdir -p ~/bin 24 | - ln -s /usr/bin/gcc-7 ~/bin/gcc 25 | - ln -s /usr/bin/g++-7 ~/bin/g++ 26 | - ln -s /usr/bin/cpp-7 ~/bin/cpp 27 | - export PATH=~/bin:$PATH 28 | - ls -l ~/bin 29 | - echo $PATH 30 | - g++-7 --version 31 | - g++ --version 32 | script: 33 | - cd ~/ 34 | - git clone --depth=50 https://github.com/libretro/libretro-super 35 | - cd libretro-super/travis 36 | - ./build.sh 37 | -------------------------------------------------------------------------------- /.github/workflows/crowdin_prep.yml: -------------------------------------------------------------------------------- 1 | # Prepare source texts & upload them to Crowdin 2 | 3 | name: Crowdin Source Texts Upload 4 | 5 | # on change to the English texts 6 | on: 7 | push: 8 | branches: 9 | - master 10 | paths: 11 | - 'libretro/libretro_core_options.h' 12 | 13 | jobs: 14 | upload_source_file: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Setup Java JDK 18 | uses: actions/setup-java@v1 19 | with: 20 | java-version: 1.8 21 | 22 | - name: Setup Python 23 | uses: actions/setup-python@v2 24 | 25 | - name: Checkout 26 | uses: actions/checkout@v2 27 | 28 | - name: Upload Source 29 | shell: bash 30 | env: 31 | CROWDIN_API_KEY: ${{ secrets.CROWDIN_API_KEY }} 32 | run: | 33 | python3 intl/upload_workflow.py $CROWDIN_API_KEY "QuickNES_Core" "libretro/libretro_core_options.h" 34 | -------------------------------------------------------------------------------- /nes_emu/nes_ntsc_config.h: -------------------------------------------------------------------------------- 1 | /* Configure library by modifying this file */ 2 | 3 | #ifndef NES_NTSC_CONFIG_H 4 | #define NES_NTSC_CONFIG_H 5 | 6 | /* Uncomment to enable emphasis support and use a 512 color palette instead 7 | of the base 64 color palette. */ 8 | #define NES_NTSC_EMPHASIS 1 9 | 10 | /* The following affect the built-in blitter only; a custom blitter can 11 | handle things however it wants. */ 12 | 13 | /* Bits per pixel of output. Can be 15, 16, 32, or 24 (same as 32). */ 14 | #define NES_NTSC_OUT_DEPTH 16 15 | 16 | /* Type of input pixel values. You'll probably use unsigned short 17 | if you enable emphasis above. */ 18 | #define NES_NTSC_IN_T unsigned short 19 | 20 | /* Each raw pixel input value is passed through this. You might want to mask 21 | the pixel index if you use the high bits as flags, etc. */ 22 | #define NES_NTSC_ADJ_IN( in ) in 23 | 24 | /* For each pixel, this is the basic operation: 25 | output_color = color_palette [NES_NTSC_ADJ_IN( NES_NTSC_IN_T )] */ 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper086.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | typedef Mapper_74x161x162x32<86> Mapper086; -------------------------------------------------------------------------------- /nes_emu/mappers/mapper152.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | typedef Mapper_74x161x162x32<152> Mapper152; -------------------------------------------------------------------------------- /nes_emu/mappers/mapper113.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | * 19 | * This mapper was added by retrowertz for Libretro port of QuickNES. 20 | * 21 | * Mapper 079 22 | * Mapper 113 23 | * Nina-03 / Nina-06 24 | */ 25 | 26 | #pragma once 27 | 28 | typedef Mapper_AveNina Mapper113; -------------------------------------------------------------------------------- /nes_emu/mappers/mapper154.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 3/24/18 20 | * 21 | * Mapper 88 22 | * Mapper 154 23 | * Mapper 206 24 | */ 25 | 26 | #pragma once 27 | 28 | typedef Mapper_Namco_34x3 Mapper154; -------------------------------------------------------------------------------- /nes_emu/mappers/mapper190.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nes_Mapper.h" 4 | 5 | // Magic Kid Googoo 6 | 7 | class Mapper190: public Nes_Mapper { 8 | public: 9 | Mapper190() 10 | { 11 | } 12 | 13 | virtual void reset_state() 14 | { 15 | } 16 | 17 | virtual void apply_mapping() 18 | { 19 | mirror_vert(); 20 | enable_sram(); 21 | set_prg_bank( 0xc000, bank_16k, 0); 22 | } 23 | 24 | virtual void write(nes_time_t, nes_addr_t addr, int data) 25 | { 26 | switch ( addr >> 12 ) 27 | { 28 | case 0x8: 29 | case 0x9: 30 | case 0xc: 31 | case 0xd: 32 | set_prg_bank( 0x8000, bank_16k, ( ( ( addr >> 11 ) & 8 ) | ( data & 7 ) ) ); 33 | break; 34 | case 0xa: 35 | case 0xb: 36 | switch ( addr & 3 ) 37 | { 38 | case 0: 39 | set_chr_bank( 0x0000, bank_2k, data ); 40 | break; 41 | case 1: 42 | set_chr_bank( 0x0800, bank_2k, data ); 43 | break; 44 | case 2: 45 | set_chr_bank( 0x1000, bank_2k, data ); 46 | break; 47 | case 3: 48 | set_chr_bank( 0x1800, bank_2k, data ); 49 | break; 50 | } 51 | break; 52 | } 53 | } 54 | }; 55 | 56 | -------------------------------------------------------------------------------- /.github/workflows/compilation.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | pull_request: 6 | repository_dispatch: 7 | types: [run_build] 8 | 9 | jobs: 10 | build-ps2: 11 | runs-on: ubuntu-latest 12 | container: ps2dev/ps2dev:latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | 16 | - name: Install dependencies 17 | run: | 18 | apk add build-base 19 | 20 | - name: Get Information Variables 21 | id: core 22 | run: | 23 | echo "::set-output name=info::$(echo quicknes)" 24 | echo "::set-output name=platform::$(echo ps2)" 25 | echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)" 26 | 27 | - name: Compile project 28 | run: | 29 | make -f Makefile platform=${{ steps.core.outputs.platform }} clean all 30 | 31 | - name: Upload artifacts 32 | if: ${{ success() }} 33 | uses: actions/upload-artifact@v4 34 | with: 35 | name: ${{ steps.core.outputs.info }}_libretro_${{ steps.core.outputs.platform }}-${{ steps.core.outputs.sha8 }} 36 | path: ${{ steps.core.outputs.info }}_libretro_${{ steps.core.outputs.platform }}.a 37 | -------------------------------------------------------------------------------- /intl/crowdin_prep.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import core_option_translation as t 4 | 5 | if __name__ == '__main__': 6 | try: 7 | if t.os.path.isfile(t.sys.argv[1]) or t.sys.argv[1].endswith('.h'): 8 | _temp = t.os.path.dirname(t.sys.argv[1]) 9 | else: 10 | _temp = t.sys.argv[1] 11 | while _temp.endswith('/') or _temp.endswith('\\'): 12 | _temp = _temp[:-1] 13 | TARGET_DIR_PATH = _temp 14 | except IndexError: 15 | TARGET_DIR_PATH = t.os.path.dirname(t.os.path.dirname(t.os.path.realpath(__file__))) 16 | print("No path provided, assuming parent directory:\n" + TARGET_DIR_PATH) 17 | 18 | CORE_NAME = t.clean_file_name(t.sys.argv[2]) 19 | DIR_PATH = t.os.path.dirname(t.os.path.realpath(__file__)) 20 | H_FILE_PATH = t.os.path.join(TARGET_DIR_PATH, 'libretro_core_options.h') 21 | 22 | print('Getting texts from libretro_core_options.h') 23 | with open(H_FILE_PATH, 'r+', encoding='utf-8') as _h_file: 24 | _main_text = _h_file.read() 25 | _hash_n_str = t.get_texts(_main_text) 26 | _files = t.create_msg_hash(DIR_PATH, CORE_NAME, _hash_n_str) 27 | 28 | _source_jsons = t.h2json(_files) 29 | 30 | print('\nAll done!') 31 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper000.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Common simple mappers 4 | 5 | // Nes_Emu 0.7.0. http://www.slack.net/~ant/ 6 | 7 | #include "Nes_Mapper.h" 8 | 9 | /* Copyright (C) 2004-2006 Shay Green. This module is free software; you 10 | can redistribute it and/or modify it under the terms of the GNU Lesser 11 | General Public License as published by the Free Software Foundation; either 12 | version 2.1 of the License, or (at your option) any later version. This 13 | module is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 16 | more details. You should have received a copy of the GNU Lesser General 17 | Public License along with this module; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 19 | 20 | #include "blargg_source.h" 21 | 22 | // NROM 23 | 24 | class Mapper000 : public Nes_Mapper { 25 | public: 26 | Mapper000() { } 27 | 28 | virtual void apply_mapping() { } 29 | 30 | virtual void write( nes_time_t, nes_addr_t, int ) 31 | { 32 | // empty 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /nes_emu/Nes_Effects_Buffer.h: -------------------------------------------------------------------------------- 1 | 2 | // Effects_Buffer with non-linear sound 3 | 4 | // Nes_Emu 0.7.0 5 | 6 | #ifndef NES_EFFECTS_BUFFER_H 7 | #define NES_EFFECTS_BUFFER_H 8 | 9 | #include "Nes_Buffer.h" 10 | #include "Effects_Buffer.h" 11 | 12 | // Effects_Buffer uses several buffers and outputs stereo sample pairs. 13 | class Nes_Effects_Buffer : public Effects_Buffer { 14 | public: 15 | Nes_Effects_Buffer(); 16 | ~Nes_Effects_Buffer(); 17 | 18 | // Setup APU for use with buffer, including setting its output to this buffer. 19 | // If you're using Nes_Emu, this is automatically called for you. 20 | void set_apu( Nes_Apu* apu ) { nonlin.set_apu( apu ); } 21 | 22 | // Enable/disable non-linear output 23 | void enable_nonlinearity( bool = true ); 24 | 25 | // See Effects_Buffer.h for reference 26 | const char *set_sample_rate( long rate, int msec = blip_default_length ); 27 | void config( const config_t& ); 28 | void clear(); 29 | channel_t channel( int ); 30 | long read_samples( blip_sample_t*, long ); 31 | 32 | void SaveAudioBufferState(); 33 | void RestoreAudioBufferState(); 34 | 35 | private: 36 | Nes_Nonlinearizer nonlin; 37 | friend Multi_Buffer* set_apu( Nes_Effects_Buffer*, Nes_Apu* ); 38 | }; 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper023.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2004-2006 Shay Green 3 | * Copyright (C) 2007 CaH4e3 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | * General code is from FCEUX https://sourceforge.net/p/fceultra/code/HEAD/tree/fceu/trunk/src/boards/vrc2and4.cpp 20 | * IRQ portion is from existing VRC6/VRC7 by Shay Green 21 | * This mapper was ported by retrowertz for Libretro port of QuickNES. 22 | * 3-19-2018 23 | * 24 | * VRC-2/VRC-4 Konami 25 | */ 26 | 27 | #pragma once 28 | #include "Nes_Mapper.h" 29 | 30 | typedef Mapper_VRC2_4 Mapper023; -------------------------------------------------------------------------------- /nes_emu/mappers/mapper025.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2004-2006 Shay Green 3 | * Copyright (C) 2007 CaH4e3 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | * General code is from FCEUX https://sourceforge.net/p/fceultra/code/HEAD/tree/fceu/trunk/src/boards/vrc2and4.cpp 20 | * IRQ portion is from existing VRC6/VRC7 by Shay Green 21 | * This mapper was ported by retrowertz for Libretro port of QuickNES. 22 | * 3-19-2018 23 | * 24 | * VRC-2/VRC-4 Konami 25 | */ 26 | 27 | #pragma once 28 | #include "Nes_Mapper.h" 29 | 30 | typedef Mapper_VRC2_4 Mapper025; -------------------------------------------------------------------------------- /nes_emu/mappers/mapper022.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2004-2006 Shay Green 3 | * Copyright (C) 2007 CaH4e3 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | * General code is from FCEUX https://sourceforge.net/p/fceultra/code/HEAD/tree/fceu/trunk/src/boards/vrc2and4.cpp 20 | * IRQ portion is from existing VRC6/VRC7 by Shay Green 21 | * This mapper was ported by retrowertz for Libretro port of QuickNES. 22 | * 3-19-2018 23 | * 24 | * VRC-2/VRC-4 Konami 25 | */ 26 | 27 | #pragma once 28 | #include "Nes_Mapper.h" 29 | #include "mappers/mapper021.hpp" 30 | 31 | typedef Mapper_VRC2_4 Mapper022; -------------------------------------------------------------------------------- /intl/remove_initial_cycle.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | with open('intl/upload_workflow.py', 'r') as workflow: 4 | workflow_config = workflow.read() 5 | 6 | workflow_config = workflow_config.replace( 7 | "subprocess.run(['python3', 'intl/core_option_translation.py', dir_path, core_name])", 8 | "subprocess.run(['python3', 'intl/crowdin_prep.py', dir_path, core_name])" 9 | ) 10 | workflow_config = workflow_config.replace( 11 | "subprocess.run(['python3', 'intl/initial_sync.py', api_key, core_name])", 12 | "subprocess.run(['python3', 'intl/crowdin_source_upload.py', api_key, core_name])" 13 | ) 14 | with open('intl/upload_workflow.py', 'w') as workflow: 15 | workflow.write(workflow_config) 16 | 17 | 18 | with open('intl/download_workflow.py', 'r') as workflow: 19 | workflow_config = workflow.read() 20 | 21 | workflow_config = workflow_config.replace( 22 | "subprocess.run(['python3', 'intl/core_option_translation.py', dir_path, core_name])", 23 | "subprocess.run(['python3', 'intl/crowdin_prep.py', dir_path, core_name])" 24 | ) 25 | workflow_config = workflow_config.replace( 26 | "subprocess.run(['python3', 'intl/initial_sync.py', api_key, core_name])", 27 | "subprocess.run(['python3', 'intl/crowdin_translation_download.py', api_key, core_name])" 28 | ) 29 | with open('intl/download_workflow.py', 'w') as workflow: 30 | workflow.write(workflow_config) 31 | -------------------------------------------------------------------------------- /nes_emu/blargg_source.h: -------------------------------------------------------------------------------- 1 | /* Included at the beginning of library source files, AFTER all other #include 2 | lines. Sets up helpful macros and services used in my source code. Since this 3 | is only "active" in my source code, I don't have to worry about polluting the 4 | global namespace with unprefixed names. */ 5 | 6 | // File_Extractor 1.0.0 7 | #ifndef BLARGG_SOURCE_H 8 | #define BLARGG_SOURCE_H 9 | 10 | #ifndef BLARGG_COMMON_H // optimization only 11 | #include "blargg_common.h" 12 | #endif 13 | 14 | #include /* memcpy(), memset(), memmove() */ 15 | #include /* offsetof() */ 16 | 17 | /* If expr yields non-NULL error string, returns it from current function, 18 | otherwise continues normally. */ 19 | #undef RETURN_ERR 20 | #define RETURN_ERR( expr ) \ 21 | do {\ 22 | const char *blargg_return_err_ = (expr);\ 23 | if ( blargg_return_err_ )\ 24 | return blargg_return_err_;\ 25 | } while ( 0 ) 26 | 27 | /* If ptr is NULL, returns out-of-memory error, otherwise continues normally. */ 28 | #undef CHECK_ALLOC 29 | #define CHECK_ALLOC( ptr ) \ 30 | do {\ 31 | if ( !(ptr) )\ 32 | return "Out of memory";\ 33 | } while ( 0 ) 34 | 35 | /* The usual min/max functions for built-in types. */ 36 | 37 | template T min( T x, T y ) { return x < y ? x : y; } 38 | template T max( T x, T y ) { return x > y ? x : y; } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper156.hpp: -------------------------------------------------------------------------------- 1 | #include "Nes_Mapper.h" 2 | 3 | #pragma once 4 | 5 | // DIS23C01 DAOU ROM CONTROLLER 6 | 7 | struct m156_state_t 8 | { 9 | uint8_t prg_bank; 10 | uint8_t chr_banks [8]; 11 | }; 12 | BOOST_STATIC_ASSERT( sizeof (m156_state_t) == 9 ); 13 | 14 | class Mapper156 : public Nes_Mapper, m156_state_t { 15 | public: 16 | Mapper156() 17 | { 18 | m156_state_t * state = this; 19 | register_state( state, sizeof * state ); 20 | } 21 | 22 | void reset_state() 23 | { 24 | prg_bank = 0; 25 | for ( unsigned i = 0; i < 8; i++ ) chr_banks [i] = i; 26 | enable_sram(); 27 | apply_mapping(); 28 | } 29 | 30 | void apply_mapping() 31 | { 32 | mirror_single( 0 ); 33 | set_prg_bank( 0x8000, bank_16k, prg_bank ); 34 | 35 | for ( int i = 0; i < (int) sizeof chr_banks; i++ ) 36 | set_chr_bank( i * 0x400, bank_1k, chr_banks [i] ); 37 | } 38 | 39 | void write( nes_time_t, nes_addr_t addr, int data ) 40 | { 41 | unsigned int reg = addr - 0xC000; 42 | if ( addr == 0xC010 ) 43 | { 44 | prg_bank = data; 45 | set_prg_bank( 0x8000, bank_16k, data ); 46 | } 47 | else if ( reg < 4 ) 48 | { 49 | chr_banks [reg] = data; 50 | set_chr_bank( reg * 0x400, bank_1k, data ); 51 | } 52 | else if ( ( reg - 8 ) < 4 ) 53 | { 54 | reg -= 4; 55 | chr_banks [reg] = data; 56 | set_chr_bank( reg * 0x400, bank_1k, data ); 57 | } 58 | } 59 | }; 60 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper034.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Optional less-common simple mappers 4 | 5 | // Nes_Emu 0.7.0. http://www.slack.net/~ant/ 6 | 7 | #include "Nes_Mapper.h" 8 | 9 | /* Copyright (C) 2004-2006 Shay Green. This module is free software; you 10 | can redistribute it and/or modify it under the terms of the GNU Lesser 11 | General Public License as published by the Free Software Foundation; either 12 | version 2.1 of the License, or (at your option) any later version. This 13 | module is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 16 | more details. You should have received a copy of the GNU Lesser General 17 | Public License along with this module; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 19 | 20 | #include "blargg_source.h" 21 | 22 | // Nina-1 (Deadly Towers only) 23 | 24 | class Mapper034 : public Nes_Mapper { 25 | uint8_t bank; 26 | public: 27 | Mapper034() 28 | { 29 | register_state( &bank, 1 ); 30 | } 31 | 32 | virtual void apply_mapping() 33 | { 34 | write( 0, 0, bank ); 35 | } 36 | 37 | virtual void write( nes_time_t, nes_addr_t, int data ) 38 | { 39 | bank = data; 40 | set_prg_bank( 0x8000, bank_32k, bank ); 41 | } 42 | }; 43 | 44 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper003.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Common simple mappers 4 | 5 | // Nes_Emu 0.7.0. http://www.slack.net/~ant/ 6 | 7 | #include "Nes_Mapper.h" 8 | 9 | /* Copyright (C) 2004-2006 Shay Green. This module is free software; you 10 | can redistribute it and/or modify it under the terms of the GNU Lesser 11 | General Public License as published by the Free Software Foundation; either 12 | version 2.1 of the License, or (at your option) any later version. This 13 | module is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 16 | more details. You should have received a copy of the GNU Lesser General 17 | Public License along with this module; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 19 | 20 | #include "blargg_source.h" 21 | 22 | // CNROM 23 | 24 | class Mapper003 : public Nes_Mapper { 25 | uint8_t bank; 26 | public: 27 | Mapper003() 28 | { 29 | register_state( &bank, 1 ); 30 | } 31 | 32 | virtual void apply_mapping() 33 | { 34 | set_chr_bank( 0, bank_8k, bank & 7 ); 35 | } 36 | 37 | virtual void write( nes_time_t, nes_addr_t addr, int data ) 38 | { 39 | bank = handle_bus_conflict( addr, data ); 40 | set_chr_bank( 0, bank_8k, bank & 7 ); 41 | } 42 | }; 43 | 44 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper010.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "Nes_Mapper.h" 5 | #include "blargg_source.h" 6 | 7 | // MMC4 8 | 9 | class Mapper010: public Nes_Mapper 10 | { 11 | uint8_t regs[6]; // A,B,C,D,E,F 12 | 13 | void mirror(uint8_t val) 14 | { 15 | if (val & 1) 16 | mirror_horiz(); 17 | else 18 | mirror_vert(); 19 | } 20 | 21 | public: 22 | Mapper010() 23 | { 24 | register_state(regs, sizeof(regs)); 25 | } 26 | 27 | virtual void reset_state() 28 | { 29 | std::memset(regs, 0, sizeof(regs)); 30 | } 31 | 32 | virtual void apply_mapping() 33 | { 34 | enable_sram(); 35 | 36 | mirror(regs[5]); 37 | set_prg_bank(0x8000, bank_16k, regs[0]); 38 | 39 | set_chr_bank(0x0000, bank_4k, regs[1]); 40 | set_chr_bank(0x1000, bank_4k, regs[3]); 41 | 42 | set_chr_bank_ex(0x0000, bank_4k, regs[2]); 43 | set_chr_bank_ex(0x1000, bank_4k, regs[4]); 44 | } 45 | 46 | virtual void write(nes_time_t, nes_addr_t addr, int data) 47 | { 48 | switch (addr >> 12) 49 | { 50 | case 0xa: regs[0] = data; set_prg_bank(0x8000, bank_16k, data); break; 51 | case 0xb: regs[1] = data; set_chr_bank(0x0000, bank_4k, data); break; 52 | case 0xc: regs[2] = data; set_chr_bank_ex(0x0000, bank_4k, data); break; 53 | case 0xd: regs[3] = data; set_chr_bank(0x1000, bank_4k, data); break; 54 | case 0xe: regs[4] = data; set_chr_bank_ex(0x1000, bank_4k, data); break; 55 | case 0xf: regs[5] = data; mirror(data); break; 56 | } 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper002.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Common simple mappers 4 | 5 | // Nes_Emu 0.7.0. http://www.slack.net/~ant/ 6 | 7 | #include "Nes_Mapper.h" 8 | 9 | /* Copyright (C) 2004-2006 Shay Green. This module is free software; you 10 | can redistribute it and/or modify it under the terms of the GNU Lesser 11 | General Public License as published by the Free Software Foundation; either 12 | version 2.1 of the License, or (at your option) any later version. This 13 | module is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 16 | more details. You should have received a copy of the GNU Lesser General 17 | Public License along with this module; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 19 | 20 | #include "blargg_source.h" 21 | 22 | // UNROM 23 | 24 | class Mapper002 : public Nes_Mapper { 25 | uint8_t bank; 26 | public: 27 | Mapper002() 28 | { 29 | register_state( &bank, 1 ); 30 | } 31 | 32 | virtual void apply_mapping() 33 | { 34 | enable_sram(); // at least one UNROM game needs sram (Bomberman 2) 35 | set_prg_bank( 0x8000, bank_16k, bank ); 36 | } 37 | 38 | virtual void write( nes_time_t, nes_addr_t addr, int data ) 39 | { 40 | bank = handle_bus_conflict( addr, data ); 41 | set_prg_bank( 0x8000, bank_16k, bank ); 42 | } 43 | }; 44 | 45 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper241.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #include "Nes_Mapper.h" 25 | 26 | // https://www.nesdev.org/wiki/INES_Mapper241 27 | 28 | class Mapper241 : public Nes_Mapper { 29 | public: 30 | Mapper241() 31 | { 32 | register_state( &bank, 1 ); 33 | } 34 | 35 | virtual void reset_state() 36 | { } 37 | 38 | virtual void apply_mapping() 39 | { 40 | enable_sram(); 41 | write( 0, 0, bank ); 42 | } 43 | 44 | virtual void write( nes_time_t, nes_addr_t, int data ) 45 | { 46 | bank = data; 47 | set_prg_bank( 0x8000, bank_32k, bank ); 48 | } 49 | 50 | uint8_t bank; 51 | }; 52 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper180.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 20 | * Mapper 180 Crazy Climber 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include "Nes_Mapper.h" 27 | 28 | // UxROM (inverted) 29 | 30 | class Mapper180 : public Nes_Mapper { 31 | public: 32 | Mapper180() 33 | { 34 | register_state( &bank, 1 ); 35 | } 36 | 37 | virtual void reset_state() 38 | { } 39 | 40 | virtual void apply_mapping() 41 | { 42 | set_prg_bank( 0x8000, bank_16k, 0 ); 43 | write( 0, 0, bank ); 44 | } 45 | 46 | virtual void write( nes_time_t, nes_addr_t, int data ) 47 | { 48 | bank = data; 49 | set_prg_bank( 0xC000, bank_16k, data ); 50 | } 51 | 52 | uint8_t bank; 53 | }; 54 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper094.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 20 | * Mapper 94 - HVC-UN1ROM 21 | * Senjou no Ookami (Japanese version of Commando) 22 | * 23 | */ 24 | 25 | #pragma once 26 | 27 | #include "Nes_Mapper.h" 28 | 29 | // Un1rom 30 | 31 | class Mapper094 : public Nes_Mapper { 32 | public: 33 | Mapper094() 34 | { 35 | register_state( &bank, 1 ); 36 | } 37 | 38 | virtual void reset_state() 39 | { } 40 | 41 | virtual void apply_mapping() 42 | { 43 | write( 0, 0, bank ); 44 | } 45 | 46 | virtual void write( nes_time_t, nes_addr_t, int data ) 47 | { 48 | bank = data; 49 | set_prg_bank( 0x8000, bank_16k, bank >> 2 ); 50 | } 51 | 52 | uint8_t bank; 53 | }; 54 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper009.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Nes_Mapper.h" 6 | #include "blargg_source.h" 7 | 8 | // MMC2 9 | 10 | class Mapper009: public Nes_Mapper 11 | { 12 | uint8_t regs[6]; // A,B,C,D,E,F 13 | 14 | void mirror(uint8_t val) 15 | { 16 | if (val & 1) 17 | mirror_horiz(); 18 | else 19 | mirror_vert(); 20 | } 21 | 22 | public: 23 | Mapper009() 24 | { 25 | register_state(regs, sizeof(regs)); 26 | } 27 | 28 | virtual void reset_state() 29 | { 30 | std::memset(regs, 0, sizeof(regs)); 31 | } 32 | 33 | virtual void apply_mapping() 34 | { 35 | mirror(regs[5]); 36 | set_prg_bank(0x8000, bank_8k, regs[0]); 37 | set_prg_bank(0xa000, bank_8k, 13); 38 | set_prg_bank(0xc000, bank_8k, 14); 39 | set_prg_bank(0xe000, bank_8k, 15); 40 | 41 | set_chr_bank(0x0000, bank_4k, regs[1]); 42 | set_chr_bank(0x1000, bank_4k, regs[3]); 43 | 44 | set_chr_bank_ex(0x0000, bank_4k, regs[2]); 45 | set_chr_bank_ex(0x1000, bank_4k, regs[4]); 46 | } 47 | 48 | virtual void write(nes_time_t, nes_addr_t addr, int data) 49 | { 50 | switch (addr >> 12) 51 | { 52 | case 0xa: regs[0] = data; set_prg_bank(0x8000, bank_8k, data); break; 53 | case 0xb: regs[1] = data; set_chr_bank(0x0000, bank_4k, data); break; 54 | case 0xc: regs[2] = data; set_chr_bank_ex(0x0000, bank_4k, data); break; 55 | case 0xd: regs[3] = data; set_chr_bank(0x1000, bank_4k, data); break; 56 | case 0xe: regs[4] = data; set_chr_bank_ex(0x1000, bank_4k, data); break; 57 | case 0xf: regs[5] = data; mirror(data); break; 58 | } 59 | } 60 | }; 61 | 62 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper007.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Common simple mappers 4 | 5 | // Nes_Emu 0.7.0. http://www.slack.net/~ant/ 6 | 7 | #include "Nes_Mapper.h" 8 | 9 | /* Copyright (C) 2004-2006 Shay Green. This module is free software; you 10 | can redistribute it and/or modify it under the terms of the GNU Lesser 11 | General Public License as published by the Free Software Foundation; either 12 | version 2.1 of the License, or (at your option) any later version. This 13 | module is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 16 | more details. You should have received a copy of the GNU Lesser General 17 | Public License along with this module; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 19 | 20 | #include "blargg_source.h" 21 | 22 | // AOROM 23 | 24 | class Mapper007 : public Nes_Mapper { 25 | uint8_t bank; 26 | public: 27 | Mapper007() 28 | { 29 | register_state( &bank, 1 ); 30 | } 31 | 32 | virtual void apply_mapping() 33 | { 34 | int b = bank; 35 | bank = ~b; // force update 36 | write( 0, 0, b ); 37 | } 38 | 39 | virtual void write( nes_time_t, nes_addr_t, int data ) 40 | { 41 | int changed = bank ^ data; 42 | bank = data; 43 | 44 | if ( changed & 0x10 ) 45 | mirror_single( bank >> 4 & 1 ); 46 | 47 | if ( changed & 0x0f ) 48 | set_prg_bank( 0x8000, bank_32k, bank & 7 ); 49 | } 50 | }; 51 | 52 | 53 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper011.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Optional less-common simple mappers 4 | 5 | // Nes_Emu 0.7.0. http://www.slack.net/~ant/ 6 | 7 | #include "Nes_Mapper.h" 8 | 9 | /* Copyright (C) 2004-2006 Shay Green. This module is free software; you 10 | can redistribute it and/or modify it under the terms of the GNU Lesser 11 | General Public License as published by the Free Software Foundation; either 12 | version 2.1 of the License, or (at your option) any later version. This 13 | module is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 16 | more details. You should have received a copy of the GNU Lesser General 17 | Public License along with this module; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 19 | 20 | #include "blargg_source.h" 21 | 22 | // Color Dreams 23 | 24 | class Mapper011 : public Nes_Mapper { 25 | uint8_t bank; 26 | public: 27 | Mapper011() 28 | { 29 | register_state( &bank, 1 ); 30 | } 31 | 32 | virtual void apply_mapping() 33 | { 34 | int b = bank; 35 | bank = ~b; 36 | write( 0, 0, b ); 37 | } 38 | 39 | virtual void write( nes_time_t, nes_addr_t, int data ) 40 | { 41 | int changed = bank ^ data; 42 | bank = data; 43 | 44 | if ( changed & 0x0f ) 45 | set_prg_bank( 0x8000, bank_32k, bank & 0x0f ); 46 | 47 | if ( changed & 0xf0 ) 48 | set_chr_bank( 0, bank_8k, bank >> 4 ); 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper066.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Optional less-common simple mappers 4 | 5 | // Nes_Emu 0.7.0. http://www.slack.net/~ant/ 6 | 7 | #include "Nes_Mapper.h" 8 | 9 | /* Copyright (C) 2004-2006 Shay Green. This module is free software; you 10 | can redistribute it and/or modify it under the terms of the GNU Lesser 11 | General Public License as published by the Free Software Foundation; either 12 | version 2.1 of the License, or (at your option) any later version. This 13 | module is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 16 | more details. You should have received a copy of the GNU Lesser General 17 | Public License along with this module; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 19 | 20 | #include "blargg_source.h" 21 | 22 | // GNROM 23 | 24 | class Mapper066 : public Nes_Mapper { 25 | uint8_t bank; 26 | public: 27 | Mapper066() 28 | { 29 | register_state( &bank, 1 ); 30 | } 31 | 32 | virtual void apply_mapping() 33 | { 34 | int b = bank; 35 | bank = ~b; 36 | write( 0, 0, b ); 37 | } 38 | 39 | virtual void write( nes_time_t, nes_addr_t, int data ) 40 | { 41 | int changed = bank ^ data; 42 | bank = data; 43 | 44 | if ( changed & 0x30 ) 45 | set_prg_bank( 0x8000, bank_32k, bank >> 4 & 3 ); 46 | 47 | if ( changed & 0x03 ) 48 | set_chr_bank( 0, bank_8k, bank & 3 ); 49 | } 50 | }; 51 | 52 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper087.hpp: -------------------------------------------------------------------------------- 1 | 2 | // Optional less-common simple mappers 3 | 4 | // Nes_Emu 0.7.0. http://www.slack.net/~ant/ 5 | 6 | #pragma once 7 | 8 | #include "Nes_Mapper.h" 9 | 10 | /* Copyright (C) 2004-2006 Shay Green. This module is free software; you 11 | can redistribute it and/or modify it under the terms of the GNU Lesser 12 | General Public License as published by the Free Software Foundation; either 13 | version 2.1 of the License, or (at your option) any later version. This 14 | module is distributed in the hope that it will be useful, but WITHOUT ANY 15 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 17 | more details. You should have received a copy of the GNU Lesser General 18 | Public License along with this module; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 20 | 21 | #include "blargg_source.h" 22 | 23 | // Jaleco/Konami/Taito 24 | 25 | class Mapper087 : public Nes_Mapper { 26 | uint8_t bank; 27 | public: 28 | Mapper087() 29 | { 30 | register_state( &bank, 1 ); 31 | } 32 | 33 | void apply_mapping() 34 | { 35 | intercept_writes( 0x6000, 1 ); 36 | write( 0, 0x6000, bank ); 37 | } 38 | 39 | bool write_intercepted( nes_time_t, nes_addr_t addr, int data ) 40 | { 41 | if ( addr != 0x6000 ) 42 | return false; 43 | 44 | bank = data; 45 | set_chr_bank( 0, bank_8k, data >> 1 ); 46 | return true; 47 | } 48 | 49 | void write( nes_time_t, nes_addr_t, int ) { } 50 | }; 51 | 52 | -------------------------------------------------------------------------------- /nes_emu/apu_state.h: -------------------------------------------------------------------------------- 1 | 2 | // NES APU state snapshot support 3 | 4 | // Nes_Snd_Emu 0.1.7 5 | 6 | #ifndef APU_STATE_H 7 | #define APU_STATE_H 8 | 9 | #include 10 | #include "blargg_common.h" 11 | 12 | struct apu_state_t 13 | { 14 | typedef uint8_t env_t [3]; 15 | /*struct env_t { 16 | uint8_t delay; 17 | uint8_t env; 18 | uint8_t written; 19 | };*/ 20 | 21 | struct apu_t { 22 | uint8_t w40xx [0x14]; // $4000-$4013 23 | uint8_t w4015; // enables 24 | uint8_t w4017; // mode 25 | uint16_t frame_delay; 26 | uint8_t frame_step; 27 | uint8_t irq_flag; 28 | } apu; 29 | 30 | struct square_t { 31 | uint16_t delay; 32 | env_t env; 33 | uint8_t length_counter; 34 | uint8_t phase; 35 | uint8_t swp_delay; 36 | uint8_t swp_reset; 37 | uint8_t unused2 [1]; 38 | }; 39 | 40 | square_t square1; 41 | square_t square2; 42 | 43 | struct triangle_t { 44 | uint16_t delay; 45 | uint8_t length_counter; 46 | uint8_t phase; 47 | uint8_t linear_counter; 48 | uint8_t linear_mode; 49 | } triangle; 50 | 51 | struct noise_t { 52 | uint16_t delay; 53 | env_t env; 54 | uint8_t length_counter; 55 | uint16_t shift_reg; 56 | } noise; 57 | 58 | struct dmc_t { 59 | uint16_t delay; 60 | uint16_t remain; 61 | uint16_t addr; 62 | uint8_t buf; 63 | uint8_t bits_remain; 64 | uint8_t bits; 65 | uint8_t buf_full; 66 | uint8_t silence; 67 | uint8_t irq_flag; 68 | } dmc; 69 | 70 | //uint8_t length_counters [4]; 71 | 72 | enum { tag = 0x41505552 }; // 'APUR' 73 | void swap(); 74 | }; 75 | BOOST_STATIC_ASSERT( sizeof (apu_state_t) == 72 ); 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper030.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 3/24/18 20 | * 21 | * Unrom-512 22 | * 23 | * NOTE: 24 | * No flash and one screen mirroring support. 25 | * Tested only on Troll Burner and Mystic Origins demo. 26 | */ 27 | 28 | #pragma once 29 | 30 | #include "Nes_Mapper.h" 31 | 32 | // Unrom512 33 | 34 | class Mapper030 : public Nes_Mapper { 35 | public: 36 | Mapper030() { } 37 | 38 | void reset_state() { } 39 | 40 | void apply_mapping() { } 41 | 42 | void write( nes_time_t, nes_addr_t addr, int data ) 43 | { 44 | if ( ( addr & 0xF000 ) >= 0x8000 ) 45 | { 46 | set_prg_bank(0x8000, bank_16k, data & 0x1F); 47 | set_chr_bank(0x0000, bank_8k, (data >> 5) & 0x3); 48 | } 49 | } 50 | }; 51 | 52 | -------------------------------------------------------------------------------- /Makefile.common: -------------------------------------------------------------------------------- 1 | LIBRETRO_COMM_DIR := $(CORE_DIR)/libretro/libretro-common 2 | INCFLAGS := -I$(CORE_DIR) \ 3 | -I$(CORE_DIR)/nes_emu \ 4 | -I$(CORE_DIR)/libretro \ 5 | -I$(LIBRETRO_COMM_DIR)/include 6 | 7 | ifneq (,$(findstring msvc200,$(platform))) 8 | INCFLAGS += -I$(LIBRETRO_COMM_DIR)/include/compat/msvc 9 | endif 10 | 11 | SOURCES_CXX := \ 12 | $(CORE_DIR)/libretro/libretro.cpp \ 13 | $(CORE_DIR)/nes_emu/abstract_file.cpp \ 14 | $(CORE_DIR)/nes_emu/apu_state.cpp \ 15 | $(CORE_DIR)/nes_emu/Blip_Buffer.cpp \ 16 | $(CORE_DIR)/nes_emu/Effects_Buffer.cpp \ 17 | $(CORE_DIR)/nes_emu/Multi_Buffer.cpp \ 18 | $(CORE_DIR)/nes_emu/Nes_Apu.cpp \ 19 | $(CORE_DIR)/nes_emu/Nes_Buffer.cpp \ 20 | $(CORE_DIR)/nes_emu/Nes_Cart.cpp \ 21 | $(CORE_DIR)/nes_emu/Nes_Core.cpp \ 22 | $(CORE_DIR)/nes_emu/Nes_Cpu.cpp \ 23 | $(CORE_DIR)/nes_emu/nes_data.cpp \ 24 | $(CORE_DIR)/nes_emu/Nes_Effects_Buffer.cpp \ 25 | $(CORE_DIR)/nes_emu/Nes_Emu.cpp \ 26 | $(CORE_DIR)/nes_emu/Nes_File.cpp \ 27 | $(CORE_DIR)/nes_emu/Nes_Fme7_Apu.cpp \ 28 | $(CORE_DIR)/nes_emu/Nes_Mapper.cpp \ 29 | $(CORE_DIR)/nes_emu/Nes_Vrc7.cpp \ 30 | $(CORE_DIR)/nes_emu/emu2413.cpp \ 31 | $(CORE_DIR)/nes_emu/emu2413_state.cpp \ 32 | $(CORE_DIR)/nes_emu/Nes_Namco_Apu.cpp \ 33 | $(CORE_DIR)/nes_emu/Nes_Oscs.cpp \ 34 | $(CORE_DIR)/nes_emu/Nes_Ppu.cpp \ 35 | $(CORE_DIR)/nes_emu/Nes_Ppu_Impl.cpp \ 36 | $(CORE_DIR)/nes_emu/Nes_Ppu_Rendering.cpp \ 37 | $(CORE_DIR)/nes_emu/Nes_State.cpp \ 38 | $(CORE_DIR)/nes_emu/nes_util.cpp \ 39 | $(CORE_DIR)/nes_emu/Nes_Vrc6_Apu.cpp \ 40 | $(CORE_DIR)/nes_emu/Data_Reader.cpp \ 41 | $(CORE_DIR)/nes_emu/nes_ntsc.cpp 42 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper093.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 20 | * Mapper 93 - Sunsoft-2 21 | */ 22 | 23 | #pragma once 24 | 25 | #include "Nes_Mapper.h" 26 | 27 | // Sunsoft2a 28 | 29 | class Mapper093 : public Nes_Mapper { 30 | public: 31 | Mapper093() 32 | { 33 | register_state( ®s, 1 ); 34 | } 35 | 36 | virtual void reset_state() 37 | {} 38 | 39 | virtual void apply_mapping() 40 | { 41 | set_prg_bank( 0xC000, bank_16k, last_bank ); 42 | write( 0, 0x8000, regs ); 43 | } 44 | 45 | virtual void write( nes_time_t, nes_addr_t addr, int data ) 46 | { 47 | regs = handle_bus_conflict( addr, data ); 48 | 49 | set_chr_bank( 0x0000, bank_8k, data & 0x0F ); 50 | set_prg_bank( 0x8000, bank_16k, ( data >> 4 ) & 0x07 ); 51 | } 52 | 53 | uint8_t regs; 54 | }; 55 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper060.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2018. 2 | * This module is free software; you 3 | * can redistribute it and/or modify it under the terms of the GNU Lesser 4 | * General Public License as published by the Free Software Foundation; either 5 | * version 2.1 of the License, or (at your option) any later version. This 6 | * module is distributed in the hope that it will be useful, but WITHOUT ANY 7 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 8 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 9 | * more details. You should have received a copy of the GNU Lesser General 10 | * Public License along with this module; if not, write to the Free Software 11 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 12 | * 13 | * This mapper was added by retrowertz for Libretro port of QuickNES. 14 | * 15 | * 4-in-1 Multicart ( Reset-based ) 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "Nes_Mapper.h" 21 | 22 | // NROM-128 4-in-1 multicart 23 | 24 | class Mapper060 : public Nes_Mapper { 25 | public: 26 | Mapper060() 27 | { 28 | last_game = 2; 29 | register_state( &game_sel, 1 ); 30 | } 31 | 32 | virtual void reset_state() 33 | { 34 | game_sel = last_game; 35 | game_sel++; 36 | game_sel &= 3; 37 | } 38 | 39 | virtual void apply_mapping() 40 | { 41 | set_prg_bank ( 0x8000, bank_16k, game_sel ); 42 | set_prg_bank ( 0xC000, bank_16k, game_sel ); 43 | set_chr_bank ( 0, bank_8k, game_sel ); 44 | last_game = game_sel; 45 | } 46 | 47 | virtual void write( nes_time_t, nes_addr_t addr, int data ) { } 48 | 49 | uint8_t game_sel, last_game; 50 | }; 51 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper071.hpp: -------------------------------------------------------------------------------- 1 | // Optional less-common simple mappers 2 | 3 | // Nes_Emu 0.7.0. http://www.slack.net/~ant/ 4 | 5 | #pragma once 6 | 7 | #include "Nes_Mapper.h" 8 | 9 | /* Copyright (C) 2004-2006 Shay Green. This module is free software; you 10 | can redistribute it and/or modify it under the terms of the GNU Lesser 11 | General Public License as published by the Free Software Foundation; either 12 | version 2.1 of the License, or (at your option) any later version. This 13 | module is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 16 | more details. You should have received a copy of the GNU Lesser General 17 | Public License along with this module; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 19 | 20 | #include "blargg_source.h" 21 | 22 | // Camerica 23 | 24 | class Mapper071 : public Nes_Mapper { 25 | uint8_t regs [3]; 26 | public: 27 | Mapper071() 28 | { 29 | register_state( regs, sizeof regs ); 30 | } 31 | 32 | virtual void apply_mapping() 33 | { 34 | write( 0, 0xc000, regs [0] ); 35 | if ( regs [1] & 0x80 ) 36 | write( 0, 0x9000, regs [1] ); 37 | } 38 | 39 | virtual void write( nes_time_t, nes_addr_t addr, int data ) 40 | { 41 | if ( addr >= 0xc000 ) 42 | { 43 | regs [0] = data; 44 | set_prg_bank( 0x8000, bank_16k, data ); 45 | } 46 | else if ( (addr & 0xf000) == 0x9000 ) 47 | { 48 | regs [1] = 0x80 | data; 49 | mirror_single( (data >> 4) & 1 ); 50 | } 51 | } 52 | }; 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper232.hpp: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | // Optional less-common simple mappers 5 | 6 | // Nes_Emu 0.7.0. http://www.slack.net/~ant/ 7 | 8 | #include "Nes_Mapper.h" 9 | 10 | /* Copyright (C) 2004-2006 Shay Green. This module is free software; you 11 | can redistribute it and/or modify it under the terms of the GNU Lesser 12 | General Public License as published by the Free Software Foundation; either 13 | version 2.1 of the License, or (at your option) any later version. This 14 | module is distributed in the hope that it will be useful, but WITHOUT ANY 15 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 17 | more details. You should have received a copy of the GNU Lesser General 18 | Public License along with this module; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 20 | 21 | #include "blargg_source.h" 22 | 23 | // Quattro 24 | 25 | class Mapper232 : public Nes_Mapper { 26 | uint8_t regs [2]; 27 | public: 28 | Mapper232() 29 | { 30 | register_state( regs, sizeof regs ); 31 | } 32 | 33 | virtual void reset_state() 34 | { 35 | regs [0] = 0; 36 | regs [1] = 3; 37 | } 38 | 39 | virtual void apply_mapping() 40 | { 41 | int bank = regs [0] >> 1 & 0x0c; 42 | set_prg_bank( 0x8000, bank_16k, bank + (regs [1] & 3) ); 43 | set_prg_bank( 0xC000, bank_16k, bank + 3 ); 44 | } 45 | 46 | virtual void write( nes_time_t, nes_addr_t addr, int data ) 47 | { 48 | if ( addr < 0xc000 ) 49 | regs [0] = data; 50 | else 51 | regs [1] = data; 52 | Mapper232::apply_mapping(); 53 | } 54 | }; 55 | 56 | -------------------------------------------------------------------------------- /nes_emu/Nes_Vrc7.h: -------------------------------------------------------------------------------- 1 | 2 | // Konami VRC7 sound chip emulator 3 | 4 | // Nes_Snd_Emu 0.1.7. Copyright (C) 2003-2005 Shay Green. GNU LGPL license. 5 | 6 | #ifndef NES_VRC7_H 7 | #define NES_VRC7_H 8 | 9 | #include "emu2413_state.h" 10 | 11 | struct vrc7_snapshot_t; 12 | 13 | class Nes_Vrc7 { 14 | public: 15 | Nes_Vrc7(); 16 | ~Nes_Vrc7(); 17 | 18 | // See Nes_Apu.h for reference 19 | void reset(); 20 | void volume( double ); 21 | void treble_eq( blip_eq_t const& ); 22 | void output( Blip_Buffer* ); 23 | enum { osc_count = 6 }; 24 | void osc_output( int index, Blip_Buffer* ); 25 | void end_frame( nes_time_t ); 26 | void save_snapshot(vrc7_snapshot_t*); 27 | void load_snapshot(vrc7_snapshot_t &, int dataSize); 28 | void update_last_amp(); 29 | 30 | void write_reg( int reg ); 31 | void write_data( nes_time_t, int data ); 32 | 33 | private: 34 | // noncopyable 35 | Nes_Vrc7( const Nes_Vrc7& ); 36 | Nes_Vrc7& operator = ( const Nes_Vrc7& ); 37 | 38 | struct Vrc7_Osc 39 | { 40 | uint8_t regs [3]; 41 | Blip_Buffer* output; 42 | int last_amp; 43 | }; 44 | 45 | void * opll; 46 | nes_time_t last_time; 47 | 48 | Blip_Synth synth; // DB2LIN_AMP_BITS == 11, * 2 49 | int count; 50 | Vrc7_Osc oscs [osc_count]; 51 | 52 | void run_until( nes_time_t ); 53 | }; 54 | 55 | struct vrc7_snapshot_t 56 | { 57 | uint8_t latch; 58 | uint8_t inst [8]; 59 | uint8_t regs [6] [3]; 60 | uint8_t count; 61 | int internal_opl_state_size; 62 | OPLL_STATE internal_opl_state; 63 | }; 64 | BOOST_STATIC_ASSERT( sizeof (vrc7_snapshot_t) == 28 + 440 + 4 ); 65 | 66 | inline void Nes_Vrc7::osc_output( int i, Blip_Buffer* buf ) 67 | { 68 | oscs [i].output = buf; 69 | } 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /nes_emu/Nes_Ppu_Rendering.h: -------------------------------------------------------------------------------- 1 | 2 | // NES PPU emulator graphics rendering 3 | 4 | // Nes_Emu 0.7.0 5 | 6 | #ifndef NES_PPU_RENDERING_H 7 | #define NES_PPU_RENDERING_H 8 | 9 | #include "Nes_Ppu_Impl.h" 10 | 11 | class Nes_Ppu_Rendering : public Nes_Ppu_Impl { 12 | typedef Nes_Ppu_Impl base; 13 | public: 14 | Nes_Ppu_Rendering(); 15 | 16 | int sprite_limit; 17 | 18 | uint8_t* host_pixels; 19 | long host_row_bytes; 20 | 21 | protected: 22 | 23 | long sprite_hit_found; // -1: sprite 0 didn't hit, 0: no hit so far, > 0: y * 341 + x 24 | void draw_background( int start, int count ); 25 | void draw_sprites( int start, int count ); 26 | 27 | private: 28 | 29 | void draw_scanlines( int start, int count, uint8_t* pixels, long pitch, int mode ); 30 | void draw_background_( int count ); 31 | 32 | // destination for draw functions; avoids extra parameters 33 | uint8_t* scanline_pixels; 34 | long scanline_row_bytes; 35 | 36 | // fill/copy 37 | void fill_background( int count ); 38 | void clip_left( int count ); 39 | void save_left( int count ); 40 | void restore_left( int count ); 41 | 42 | // sprites 43 | enum { max_sprites = 64 }; 44 | uint8_t sprite_scanlines [image_height]; // number of sprites on each scanline 45 | void draw_sprites_( int start, int count ); 46 | bool sprite_hit_possible( int scanline ) const; 47 | void check_sprite_hit( int begin, int end ); 48 | }; 49 | 50 | inline Nes_Ppu_Rendering::Nes_Ppu_Rendering() 51 | { 52 | sprite_limit = 8; 53 | host_pixels = NULL; 54 | } 55 | 56 | inline void Nes_Ppu_Rendering::draw_sprites( int start, int count ) 57 | { 58 | draw_scanlines( start, count, host_pixels + host_row_bytes * start, host_row_bytes, 2 ); 59 | } 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper089.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 20 | * Mapper 93 - Sunsoft-2 21 | */ 22 | 23 | #pragma once 24 | 25 | #include "Nes_Mapper.h" 26 | 27 | // Sunsoft2b 28 | 29 | class Mapper089 : public Nes_Mapper { 30 | public: 31 | Mapper089() 32 | { 33 | register_state( ®s, 1 ); 34 | } 35 | 36 | virtual void reset_state() 37 | {} 38 | 39 | virtual void apply_mapping() 40 | { 41 | set_prg_bank( 0xC000, bank_16k, last_bank ); 42 | write( 0, 0x8000, regs ); 43 | } 44 | 45 | virtual void write( nes_time_t, nes_addr_t addr, int data ) 46 | { 47 | regs = handle_bus_conflict( addr, data ); 48 | 49 | set_chr_bank( 0x0000, bank_8k, ( ( data >> 4 ) & 0x08 ) | ( data & 0x07 ) ); 50 | set_prg_bank( 0x8000, bank_16k, ( data >> 4 ) & 0x07 ); 51 | mirror_single( ( data >> 3 ) & 1 ); 52 | } 53 | 54 | uint8_t regs; 55 | }; 56 | -------------------------------------------------------------------------------- /intl/crowdin_translate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import core_option_translation as t 4 | 5 | if __name__ == '__main__': 6 | try: 7 | if t.os.path.isfile(t.sys.argv[1]) or t.sys.argv[1].endswith('.h'): 8 | _temp = t.os.path.dirname(t.sys.argv[1]) 9 | else: 10 | _temp = t.sys.argv[1] 11 | while _temp.endswith('/') or _temp.endswith('\\'): 12 | _temp = _temp[:-1] 13 | TARGET_DIR_PATH = _temp 14 | except IndexError: 15 | TARGET_DIR_PATH = t.os.path.dirname(t.os.path.dirname(t.os.path.realpath(__file__))) 16 | print("No path provided, assuming parent directory:\n" + TARGET_DIR_PATH) 17 | 18 | CORE_NAME = t.clean_file_name(t.sys.argv[2]) 19 | DIR_PATH = t.os.path.dirname(t.os.path.realpath(__file__)) 20 | LOCALISATIONS_PATH = t.os.path.join(DIR_PATH, CORE_NAME) 21 | US_FILE_PATH = t.os.path.join(LOCALISATIONS_PATH, '_us.h') 22 | H_FILE_PATH = t.os.path.join(TARGET_DIR_PATH, 'libretro_core_options.h') 23 | INTL_FILE_PATH = t.os.path.join(TARGET_DIR_PATH, 'libretro_core_options_intl.h') 24 | 25 | print('Getting texts from libretro_core_options.h') 26 | with open(H_FILE_PATH, 'r+', encoding='utf-8') as _h_file: 27 | _main_text = _h_file.read() 28 | _hash_n_str = t.get_texts(_main_text) 29 | _files = t.create_msg_hash(DIR_PATH, CORE_NAME, _hash_n_str) 30 | _source_jsons = t.h2json(_files) 31 | 32 | print('Converting translations *.json to *.h:') 33 | localisation_files = t.os.scandir(LOCALISATIONS_PATH) 34 | t.json2h(LOCALISATIONS_PATH, localisation_files) 35 | 36 | print('Constructing libretro_core_options_intl.h') 37 | t.create_intl_file(INTL_FILE_PATH, LOCALISATIONS_PATH, _main_text, _files["_us"]) 38 | 39 | print('\nAll done!') 40 | -------------------------------------------------------------------------------- /.github/workflows/crowdin_translate.yml: -------------------------------------------------------------------------------- 1 | # Download translations form Crowdin & Recreate libretro_core_options_intl.h 2 | 3 | name: Crowdin Translation Integration 4 | 5 | on: 6 | schedule: 7 | # please choose a random time & weekday to avoid all repos synching at the same time 8 | - cron: '25 21 * * 5' # Fridays at 9:25 PM, UTC 9 | 10 | jobs: 11 | create_intl_file: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Setup Java JDK 15 | uses: actions/setup-java@v1 16 | with: 17 | java-version: 1.8 18 | 19 | - name: Setup Python 20 | uses: actions/setup-python@v2 21 | 22 | - name: Checkout 23 | uses: actions/checkout@v2 24 | with: 25 | persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token. 26 | fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository. 27 | 28 | - name: Create intl file 29 | shell: bash 30 | env: 31 | CROWDIN_API_KEY: ${{ secrets.CROWDIN_API_KEY }} 32 | run: | 33 | python3 intl/download_workflow.py $CROWDIN_API_KEY "QuickNES_Core" "libretro/libretro_core_options_intl.h" 34 | 35 | - name: Commit files 36 | run: | 37 | git config --local user.email "github-actions@github.com" 38 | git config --local user.name "github-actions[bot]" 39 | git add intl/*_workflow.py "libretro/libretro_core_options_intl.h" 40 | git commit -m "Fetch translations & Recreate libretro_core_options_intl.h" 41 | 42 | - name: GitHub Push 43 | uses: ad-m/github-push-action@v0.6.0 44 | with: 45 | github_token: ${{ secrets.GITHUB_TOKEN }} 46 | branch: ${{ github.ref }} 47 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper097.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 20 | * Mapper 97 - Kaiketsu Yanchamaru 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include "Nes_Mapper.h" 27 | 28 | // Irem_Tam_S1 29 | 30 | class Mapper097 : public Nes_Mapper { 31 | public: 32 | Mapper097() 33 | { 34 | register_state( &bank, 1 ); 35 | } 36 | 37 | virtual void reset_state() 38 | { 39 | bank = ~0; 40 | } 41 | 42 | virtual void apply_mapping() 43 | { 44 | write( 0, 0, bank ); 45 | } 46 | 47 | virtual void write( nes_time_t, nes_addr_t, int data ) 48 | { 49 | bank = data; 50 | set_prg_bank( 0x8000, bank_16k, ~0 ); 51 | set_prg_bank( 0xC000, bank_16k, bank & 0x0F ); 52 | 53 | switch ( ( bank >> 6 ) & 0x03 ) 54 | { 55 | case 1: mirror_horiz(); break; 56 | case 2: mirror_vert(); break; 57 | case 0: 58 | case 3: mirror_single( bank & 0x01 ); break; 59 | } 60 | } 61 | 62 | uint8_t bank; 63 | }; 64 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper078.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nes_Mapper.h" 4 | 5 | // Holy Diver and Uchuusen - Cosmo Carrier. 6 | 7 | class Mapper078 : public Nes_Mapper { 8 | // lower 8 bits are the reg at 8000:ffff 9 | // next two bits are autodetecting type 10 | // 0 = unknown 1 = cosmo carrier 2 = holy diver 11 | int reg; 12 | void writeinternal(int data, int changed) 13 | { 14 | reg &= 0x300; 15 | reg |= data; 16 | 17 | if (changed & 0x07) 18 | set_prg_bank(0x8000, bank_16k, reg & 0x07); 19 | if (changed & 0xf0) 20 | set_chr_bank(0x0000, bank_8k, (reg >> 4) & 0x0f); 21 | if (changed & 0x08) 22 | { 23 | // set mirroring based on memorized board type 24 | if (reg & 0x100) 25 | { 26 | mirror_single((reg >> 3) & 1); 27 | } 28 | else if (reg & 0x200) 29 | { 30 | if (reg & 0x08) 31 | mirror_vert(); 32 | else 33 | mirror_horiz(); 34 | } 35 | else 36 | { 37 | // if you don't set something here, holy diver dumps with 4sc set will 38 | // savestate as 4k NTRAM. then when you later set H\V mapping, state size mismatch. 39 | mirror_single(1); 40 | } 41 | } 42 | } 43 | 44 | public: 45 | Mapper078() 46 | { 47 | register_state(®, 4); 48 | } 49 | 50 | virtual void reset_state() 51 | { 52 | reg = 0; 53 | } 54 | 55 | virtual void apply_mapping() 56 | { 57 | writeinternal(reg, 0xff); 58 | } 59 | 60 | virtual void write( nes_time_t, nes_addr_t addr, int data) 61 | { 62 | // heuristic: if the first write ever to the register is 0, 63 | // we're on holy diver, otherwise, carrier. it works for these two games... 64 | if (!(reg & 0x300)) 65 | { 66 | reg |= data ? 0x100 : 0x200; 67 | writeinternal(data, 0xff); 68 | } 69 | else 70 | { 71 | writeinternal(data, reg ^ data); 72 | } 73 | } 74 | }; 75 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper140.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | * 19 | * This mapper was added by retrowertz for Libretro port of QuickNES. 20 | * 21 | * Mapper 140 - Jaleco's JF-11 and JF-14 22 | * 23 | */ 24 | 25 | #pragma once 26 | 27 | #include "Nes_Mapper.h" 28 | 29 | // Jaleco_JF11 30 | 31 | class Mapper140 : public Nes_Mapper { 32 | public: 33 | Mapper140() 34 | { 35 | register_state( ®s, 1 ); 36 | } 37 | 38 | virtual void reset_state() 39 | { 40 | intercept_writes( 0x6000, 1 ); 41 | } 42 | 43 | virtual void apply_mapping() 44 | { 45 | write_intercepted(0, 0x6000, regs ); 46 | } 47 | 48 | bool write_intercepted( nes_time_t time, nes_addr_t addr, int data ) 49 | { 50 | if ( addr < 0x6000 || addr > 0x7FFF ) 51 | return false; 52 | 53 | regs = data; 54 | set_prg_bank( 0x8000, bank_32k, data >> 4); 55 | set_chr_bank( 0, bank_8k, data ); 56 | 57 | return true; 58 | } 59 | 60 | virtual void write( nes_time_t, nes_addr_t addr, int data ) { } 61 | 62 | uint8_t regs; 63 | }; 64 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper240.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #include "Nes_Mapper.h" 25 | 26 | // https://www.nesdev.org/wiki/INES_Mapper240 27 | 28 | class Mapper240 : public Nes_Mapper { 29 | public: 30 | Mapper240() 31 | { 32 | register_state( ®s, 1 ); 33 | } 34 | 35 | virtual void reset_state() 36 | { 37 | } 38 | 39 | virtual void apply_mapping() 40 | { 41 | enable_sram(); 42 | intercept_writes( 0x4020, 1 ); 43 | write_intercepted( 0, 0x4120, regs ); 44 | } 45 | 46 | virtual void write( nes_time_t, nes_addr_t, int data ) 47 | { } 48 | 49 | virtual bool write_intercepted( nes_time_t, nes_addr_t addr, int data ) 50 | { 51 | if ( addr < 0x4020 || addr > 0x5FFF ) 52 | return false; 53 | 54 | regs = data; 55 | set_chr_bank( 0x0000, bank_8k, data & 0x0F ); 56 | set_prg_bank( 0x8000, bank_32k, data >> 4 ); 57 | 58 | return true; 59 | } 60 | 61 | uint8_t regs; 62 | }; 63 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper184.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 20 | * Mapper 184 - Sunsoft-1 21 | */ 22 | 23 | #pragma once 24 | 25 | #include "Nes_Mapper.h" 26 | 27 | // Sunsoft1 28 | 29 | class Mapper184 : public Nes_Mapper { 30 | public: 31 | Mapper184() 32 | { 33 | register_state( ®s, 1 ); 34 | } 35 | 36 | virtual void reset_state() 37 | {} 38 | 39 | virtual void apply_mapping() 40 | { 41 | set_prg_bank( 0x8000, bank_32k, 0 ); 42 | intercept_writes( 0x6000, 1 ); 43 | write_intercepted( 0, 0x6000, regs ); 44 | } 45 | 46 | virtual bool write_intercepted( nes_time_t, nes_addr_t addr, int data ) 47 | { 48 | if ( addr != 0x6000 ) 49 | return false; 50 | 51 | regs = data; 52 | set_chr_bank( 0x0000, bank_4k, data & 0x07 ); 53 | set_chr_bank( 0x1000, bank_4k, ( data >> 4 ) & 0x07 ); 54 | 55 | return true; 56 | } 57 | 58 | virtual void write( nes_time_t, nes_addr_t addr, int data ) 59 | {} 60 | 61 | uint8_t regs; 62 | }; 63 | 64 | -------------------------------------------------------------------------------- /libretro/libretro-common/include/retro_inline.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2010-2020 The RetroArch team 2 | * 3 | * --------------------------------------------------------------------------------------- 4 | * The following license statement only applies to this file (retro_inline.h). 5 | * --------------------------------------------------------------------------------------- 6 | * 7 | * Permission is hereby granted, free of charge, 8 | * to any person obtaining a copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 11 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 16 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef __LIBRETRO_SDK_INLINE_H 24 | #define __LIBRETRO_SDK_INLINE_H 25 | 26 | #ifndef INLINE 27 | 28 | #if defined(_WIN32) || defined(__INTEL_COMPILER) 29 | #define INLINE __inline 30 | #elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L 31 | #define INLINE inline 32 | #elif defined(__GNUC__) 33 | #define INLINE __inline__ 34 | #else 35 | #define INLINE 36 | #endif 37 | 38 | #endif 39 | #endif 40 | -------------------------------------------------------------------------------- /nes_emu/Nes_Buffer.h: -------------------------------------------------------------------------------- 1 | 2 | // NES non-linear audio buffer 3 | 4 | // Nes_Emu 0.7.0 5 | 6 | #ifndef NES_BUFFER_H 7 | #define NES_BUFFER_H 8 | 9 | #include "Multi_Buffer.h" 10 | class Nes_Apu; 11 | 12 | class Nes_Nonlinearizer { 13 | private: 14 | enum { table_bits = 11 }; 15 | enum { table_size = 1 << table_bits }; 16 | int16_t table [table_size]; 17 | Nes_Apu* apu; 18 | long accum; 19 | long prev; 20 | 21 | long extra_accum; 22 | long extra_prev; 23 | public: 24 | Nes_Nonlinearizer(); 25 | bool enabled; 26 | void clear(); 27 | void set_apu( Nes_Apu* a ) { apu = a; } 28 | Nes_Apu* enable( bool, Blip_Buffer* tnd ); 29 | long make_nonlinear( Blip_Buffer& buf, long count ); 30 | void SaveAudioBufferState(); 31 | void RestoreAudioBufferState(); 32 | }; 33 | 34 | class Nes_Buffer : public Multi_Buffer { 35 | public: 36 | Nes_Buffer(); 37 | ~Nes_Buffer(); 38 | 39 | // Setup APU for use with buffer, including setting its output to this buffer. 40 | // If you're using Nes_Emu, this is automatically called for you. 41 | void set_apu( Nes_Apu* apu ) { nonlin.set_apu( apu ); } 42 | 43 | // Enable/disable non-linear output 44 | void enable_nonlinearity( bool = true ); 45 | 46 | // Blip_Buffer to output other sound chips to 47 | Blip_Buffer* buffer() { return &buf; } 48 | 49 | // See Multi_Buffer.h 50 | const char *set_sample_rate( long rate, int msec = blip_default_length ); 51 | 52 | void clock_rate( long ); 53 | void bass_freq( int ); 54 | void clear(); 55 | channel_t channel( int ); 56 | void end_frame( blip_time_t, bool unused = true ); 57 | long samples_avail() const; 58 | long read_samples( blip_sample_t*, long ); 59 | 60 | private: 61 | Blip_Buffer buf; 62 | Blip_Buffer tnd; 63 | Nes_Nonlinearizer nonlin; 64 | friend Multi_Buffer* set_apu( Nes_Buffer*, Nes_Apu* ); 65 | public: 66 | virtual void SaveAudioBufferState(); 67 | virtual void RestoreAudioBufferState(); 68 | }; 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /nes_emu/nes_data.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Nes_Emu 0.7.0. http://www.slack.net/~ant/ 3 | 4 | #include "nes_data.h" 5 | 6 | #include "blargg_endian.h" 7 | 8 | /* Copyright (C) 2004-2006 Shay Green. This module is free software; you 9 | can redistribute it and/or modify it under the terms of the GNU Lesser 10 | General Public License as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. This 12 | module is distributed in the hope that it will be useful, but WITHOUT ANY 13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 15 | more details. You should have received a copy of the GNU Lesser General 16 | Public License along with this module; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 18 | 19 | #include "blargg_source.h" 20 | 21 | #define SWAP_BE( n ) (void) (set_be( &(n), (n) )) 22 | #define SWAP_LE( n ) (void) (set_le( &(n), (n) )) 23 | 24 | void nes_block_t::swap() 25 | { 26 | SWAP_BE( tag ); 27 | SWAP_LE( size ); 28 | } 29 | 30 | void nes_state_t::swap() 31 | { 32 | SWAP_LE( timestamp ); 33 | SWAP_LE( frame_count ); 34 | } 35 | 36 | void cpu_state_t::swap() 37 | { 38 | SWAP_LE( pc ); 39 | } 40 | 41 | void ppu_state_t::swap() 42 | { 43 | SWAP_LE( vram_addr ); 44 | SWAP_LE( vram_temp ); 45 | SWAP_LE( decay_low ); 46 | SWAP_LE( decay_high ); 47 | } 48 | 49 | void apu_state_t::swap() 50 | { 51 | SWAP_LE( apu.frame_delay ); 52 | SWAP_LE( square1.delay ); 53 | SWAP_LE( square2.delay ); 54 | SWAP_LE( triangle.delay ); 55 | SWAP_LE( noise.delay ); 56 | SWAP_LE( noise.shift_reg ); 57 | SWAP_LE( dmc.delay ); 58 | SWAP_LE( dmc.remain ); 59 | SWAP_LE( dmc.addr ); 60 | } 61 | 62 | void joypad_state_t::swap() 63 | { 64 | SWAP_LE( joypad_latches [0] ); 65 | SWAP_LE( joypad_latches [1] ); 66 | } 67 | -------------------------------------------------------------------------------- /nes_emu/nes_util.h: -------------------------------------------------------------------------------- 1 | 2 | // Experimental utilities for NES emulator 3 | 4 | // Nes_Emu 0.7.0 5 | 6 | #ifndef NES_UTIL_H 7 | #define NES_UTIL_H 8 | 9 | #include 10 | #include "blargg_common.h" 11 | 12 | class Nes_Emu; 13 | class Nes_Cart; 14 | 15 | struct game_genie_patch_t 16 | { 17 | unsigned addr; // always 0x8000 or greater 18 | int change_to; 19 | int compare_with; // if -1, always change byte 20 | 21 | // Decode Game Genie code 22 | const char *decode( const char* in ); 23 | 24 | // Apply patch to cartridge data. Might not work for some codes, since this really 25 | // requires emulator support. Returns number of bytes changed, where 0 26 | // means patch wasn't for that cartridge. 27 | int apply( Nes_Cart& ) const; 28 | }; 29 | 30 | class Cheat_Value_Finder { 31 | public: 32 | Cheat_Value_Finder(); 33 | 34 | // Start scanning emulator's memory for values that are constantly changing. 35 | void start( Nes_Emu* ); 36 | 37 | // Rescan memory and eliminate any changed bytes from later matching. 38 | // Should be called many times after begin_scan() and before begin_matching(). 39 | void rescan(); 40 | 41 | // Start search for any bytes which changed by difference between original and 42 | // changed values. 43 | void search( int original, int changed ); 44 | 45 | // Get next match and return its delta from changed value (closer to 0 46 | // is more likely to be a match), or no_match if there are no more matches. 47 | // Optionally returns address of matched byte. 48 | enum { no_match = 0x100 }; 49 | int next_match( int* addr = NULL ); 50 | 51 | // Change current match to new value. Returns previous value. 52 | int change_value( int new_value ); 53 | 54 | private: 55 | Nes_Emu* emu; 56 | int original_value; 57 | int changed_value; 58 | int pos; 59 | enum { low_mem_size = 0x800 }; 60 | uint8_t original [low_mem_size]; 61 | uint8_t changed [low_mem_size]; 62 | }; 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper244.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 20 | * Mapper 244 - Decathlon 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include "Nes_Mapper.h" 27 | 28 | // https://www.nesdev.org/wiki/INES_Mapper244 29 | 30 | struct mapper244_state_t 31 | { 32 | uint8_t preg; 33 | uint8_t creg; 34 | }; 35 | 36 | BOOST_STATIC_ASSERT( sizeof (mapper244_state_t) == 2 ); 37 | 38 | class Mapper244 : public Nes_Mapper, mapper244_state_t { 39 | public: 40 | Mapper244() 41 | { 42 | mapper244_state_t *state = this; 43 | register_state( state, sizeof *state ); 44 | } 45 | 46 | virtual void reset_state() 47 | { } 48 | 49 | virtual void apply_mapping() 50 | { 51 | set_prg_bank( 0x8000, bank_32k, preg ); 52 | set_chr_bank( 0x0000, bank_8k, creg ); 53 | } 54 | 55 | virtual void write( nes_time_t, nes_addr_t addr, int data ) 56 | { 57 | if ( addr >= 0x8065 && addr <= 0x80A4 ) 58 | { 59 | preg = ( addr - 0x8065 ) & 0x03; 60 | set_prg_bank( 0x8000, bank_32k, preg ); 61 | } 62 | 63 | if ( addr >= 0x80A5 && addr <= 0x80E4 ) 64 | { 65 | creg = (addr - 0x80A5 ) & 0x07; 66 | set_chr_bank( 0x0000, bank_8k, creg ); 67 | } 68 | } 69 | }; 70 | -------------------------------------------------------------------------------- /nes_emu/Nes_Ppu_Bg.h: -------------------------------------------------------------------------------- 1 | while ( true ) 2 | { 3 | while ( count-- ) 4 | { 5 | int attrib = attr_table [addr >> 2 & 0x07]; 6 | attrib >>= (addr >> 4 & 4) | (addr & 2); 7 | unsigned long offset = (attrib & 3) * attrib_factor + this->palette_offset; 8 | 9 | // draw one tile 10 | cache_t const* lines = this->get_bg_tile( nametable [addr] + bg_bank ); 11 | uint8_t* p = pixels; 12 | addr++; 13 | pixels += 8; // next tile 14 | 15 | if ( !clipped ) 16 | { 17 | // optimal case: no clipping 18 | for ( int n = 4; n--; ) 19 | { 20 | unsigned long line = *lines++; 21 | ((unaligned_uint32_t*) p) [0].val = (line >> 4 & mask) + offset; 22 | ((unaligned_uint32_t*) p) [1].val = (line & mask) + offset; 23 | p += row_bytes; 24 | ((unaligned_uint32_t*) p) [0].val = (line >> 6 & mask) + offset; 25 | ((unaligned_uint32_t*) p) [1].val = (line >> 2 & mask) + offset; 26 | p += row_bytes; 27 | } 28 | } 29 | else 30 | { 31 | lines += fine_y >> 1; 32 | 33 | if ( fine_y & 1 ) 34 | { 35 | unsigned long line = *lines++; 36 | ((unaligned_uint32_t*) p) [0].val = (line >> 6 & mask) + offset; 37 | ((unaligned_uint32_t*) p) [1].val = (line >> 2 & mask) + offset; 38 | p += row_bytes; 39 | } 40 | 41 | for ( int n = height >> 1; n--; ) 42 | { 43 | unsigned long line = *lines++; 44 | ((unaligned_uint32_t*) p) [0].val = (line >> 4 & mask) + offset; 45 | ((unaligned_uint32_t*) p) [1].val = (line & mask) + offset; 46 | p += row_bytes; 47 | ((unaligned_uint32_t*) p) [0].val = (line >> 6 & mask) + offset; 48 | ((unaligned_uint32_t*) p) [1].val = (line >> 2 & mask) + offset; 49 | p += row_bytes; 50 | } 51 | 52 | if ( height & 1 ) 53 | { 54 | unsigned long line = *lines; 55 | ((unaligned_uint32_t*) p) [0].val = (line >> 4 & mask) + offset; 56 | ((unaligned_uint32_t*) p) [1].val = (line & mask) + offset; 57 | } 58 | } 59 | } 60 | 61 | count = count2; 62 | count2 = 0; 63 | addr -= 32; 64 | attr_table = attr_table - nametable + nametable2; 65 | nametable = nametable2; 66 | if ( !count ) 67 | break; 68 | } 69 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper246.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 20 | * Mapper 246 - Feng Shen Bang (Asia) (Ja) (Unl) 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include "Nes_Mapper.h" 27 | 28 | // https://www.nesdev.org/wiki/INES_Mapper246 29 | 30 | class Mapper246 : public Nes_Mapper { 31 | public: 32 | Mapper246() 33 | { 34 | register_state( regs, sizeof regs ); 35 | } 36 | 37 | virtual void reset_state() 38 | { 39 | regs [ 3 ] = ~0; 40 | } 41 | 42 | virtual void apply_mapping() 43 | { 44 | enable_sram(); 45 | intercept_writes( 0x6000, 0x07 ); 46 | for ( size_t i = 0; i < sizeof regs; i++ ) 47 | write_intercepted( 0, 0x6000 + i, regs [ i ] ); 48 | } 49 | 50 | virtual void write( nes_time_t, nes_addr_t addr, int data ) 51 | { } 52 | 53 | virtual bool write_intercepted( nes_time_t, nes_addr_t addr, int data ) 54 | { 55 | int bank = addr & 0x07; 56 | 57 | if ( addr < 0x6000 || addr > 0x67FF ) 58 | return false; 59 | 60 | regs [ bank ] = data; 61 | if ( bank < 4 ) 62 | { 63 | set_prg_bank( 0x8000 + ( bank << 13 ), bank_8k, data ); 64 | return true; 65 | } 66 | 67 | set_chr_bank( 0x0000 + ( ( bank & 0x03 ) << 11 ) , bank_2k, data ); 68 | 69 | return true; 70 | } 71 | 72 | uint8_t regs [ 8 ]; 73 | }; 74 | 75 | -------------------------------------------------------------------------------- /nes_emu/Nes_Cart.h: -------------------------------------------------------------------------------- 1 | 2 | // NES cartridge data (PRG, CHR, mapper) 3 | 4 | // Nes_Emu 0.7.0 5 | 6 | #ifndef NES_CART_H 7 | #define NES_CART_H 8 | 9 | #include 10 | #include "blargg_common.h" 11 | #include "abstract_file.h" 12 | 13 | class Nes_Cart { 14 | public: 15 | Nes_Cart(); 16 | ~Nes_Cart(); 17 | 18 | // Load iNES file 19 | const char * load_ines( Auto_File_Reader ); 20 | static const char not_ines_file []; 21 | 22 | // to do: support UNIF? 23 | 24 | // True if data is currently loaded 25 | bool loaded() const { return prg_ != NULL; } 26 | 27 | // Free data 28 | void clear(); 29 | 30 | // True if cartridge claims to have battery-backed memory 31 | bool has_battery_ram() const; 32 | 33 | // Size of PRG data 34 | long prg_size() const { return prg_size_; } 35 | 36 | // Size of CHR data 37 | long chr_size() const { return chr_size_; } 38 | 39 | // Change size of PRG (code) data 40 | const char * resize_prg( long ); 41 | 42 | // Change size of CHR (graphics) data 43 | const char * resize_chr( long ); 44 | 45 | // Set mapper and information bytes. LSB and MSB are the standard iNES header 46 | // bytes at offsets 6 and 7. 47 | void set_mapper( int mapper_lsb, int mapper_msb ); 48 | 49 | unsigned mapper_data() const { return mapper; } 50 | 51 | // Initial mirroring setup 52 | int mirroring() const { return mapper & 0x09; } 53 | 54 | // iNES mapper code 55 | int mapper_code() const; 56 | 57 | // Pointer to beginning of PRG data 58 | uint8_t * prg() { return prg_; } 59 | uint8_t const* prg() const { return prg_; } 60 | 61 | // Pointer to beginning of CHR data 62 | uint8_t * chr() { return chr_; } 63 | uint8_t const* chr() const { return chr_; } 64 | 65 | // End of public interface 66 | private: 67 | enum { bank_size = 8 * 1024L }; // bank sizes must be a multiple of this 68 | uint8_t *prg_; 69 | uint8_t *chr_; 70 | long prg_size_; 71 | long chr_size_; 72 | unsigned mapper; 73 | long round_to_bank_size( long n ); 74 | }; 75 | 76 | inline bool Nes_Cart::has_battery_ram() const { return mapper & 0x02; } 77 | 78 | inline void Nes_Cart::set_mapper( int mapper_lsb, int mapper_msb ) 79 | { 80 | mapper = mapper_msb * 0x100 + mapper_lsb; 81 | } 82 | 83 | inline int Nes_Cart::mapper_code() const { return ((mapper >> 8) & 0xf0) | ((mapper >> 4) & 0x0f); } 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper193.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 20 | * Mapper 193 - NTDEC TC-112 21 | * Fighting Hero (Unl) 22 | * War in the Gulf & (its Brazilian localization) 23 | * 24 | */ 25 | 26 | #pragma once 27 | 28 | #include "Nes_Mapper.h" 29 | 30 | // NTDEC's TC-112 mapper IC. 31 | 32 | class Mapper193 : public Nes_Mapper { 33 | public: 34 | Mapper193() 35 | { 36 | register_state( regs, sizeof regs ); 37 | } 38 | 39 | virtual void reset_state() 40 | { } 41 | 42 | virtual void apply_mapping() 43 | { 44 | for ( size_t i = 0; i < sizeof regs; i++ ) 45 | write_intercepted( 0, 0x6000 + i, regs [ i ] ); 46 | set_prg_bank( 0xA000, bank_8k, ~2 ); 47 | set_prg_bank( 0xC000, bank_8k, ~1 ); 48 | set_prg_bank( 0xE000, bank_8k, ~0 ); 49 | intercept_writes( 0x6000, 0x03 ); 50 | } 51 | 52 | virtual void write( nes_time_t, nes_addr_t addr, int data ) 53 | { } 54 | 55 | virtual bool write_intercepted( nes_time_t, nes_addr_t addr, int data ) 56 | { 57 | if ( addr < 0x6000 || addr > 0x6003 ) 58 | return false; 59 | 60 | regs [ addr & 0x03 ] = data; 61 | switch ( addr & 0x03 ) 62 | { 63 | case 0: set_chr_bank( 0x0000, bank_4k, regs [ 0 ] >> 2 ); break; 64 | case 1: set_chr_bank( 0x1000, bank_2k, regs [ 1 ] >> 1 ); break; 65 | case 2: set_chr_bank( 0x1800, bank_2k, regs [ 2 ] >> 1 ); break; 66 | case 3: set_prg_bank( 0x8000, bank_8k, regs [ 3 ] ); break; 67 | } 68 | 69 | return true; 70 | } 71 | 72 | uint8_t regs [ 4 ]; 73 | }; 74 | 75 | -------------------------------------------------------------------------------- /nes_emu/blargg_common.h: -------------------------------------------------------------------------------- 1 | // Sets up common environment for Shay Green's libraries. 2 | // To change configuration options, modify blargg_config.h, not this file. 3 | 4 | // File_Extractor 1.0.0 5 | #ifndef BLARGG_COMMON_H 6 | #define BLARGG_COMMON_H 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | /* Pure virtual functions cause a vtable entry to a "called pure virtual" 13 | error handler, requiring linkage to the C++ runtime library. This macro is 14 | used in place of the "= 0", and simply expands to its argument. During 15 | development, it expands to "= 0", allowing detection of missing overrides. */ 16 | #define BLARGG_PURE( def ) def 17 | 18 | /* My code depends on ASCII anywhere a character or string constant is 19 | compared with data read from a file, and anywhere file data is read and 20 | treated as a string. */ 21 | #if '\n'!=0x0A || ' '!=0x20 || '0'!=0x30 || 'A'!=0x41 || 'a'!=0x61 22 | #error "ASCII character set required" 23 | #endif 24 | 25 | /* My code depends on int being at least 32 bits. Almost everything these days 26 | uses at least 32-bit ints, so it's hard to even find a system with 16-bit ints 27 | to test with. The issue can't be gotten around by using a suitable blargg_int 28 | everywhere either, because int is often converted to implicitly when doing 29 | arithmetic on smaller types. */ 30 | #if UINT_MAX < 0xFFFFFFFF 31 | #error "int must be at least 32 bits" 32 | #endif 33 | 34 | // In case compiler doesn't support these properly. Used rarely. 35 | #define STATIC_CAST(T,expr) static_cast (expr) 36 | 37 | // User configuration can override the above macros if necessary 38 | #include "blargg_config.h" 39 | 40 | // BOOST_STATIC_ASSERT( expr ): Generates compile error if expr is 0. 41 | #ifndef BOOST_STATIC_ASSERT 42 | #ifdef _MSC_VER 43 | // MSVC6 (_MSC_VER < 1300) fails for use of __LINE__ when /Zl is specified 44 | #define BOOST_STATIC_ASSERT( expr ) \ 45 | void blargg_failed_( int (*arg) [2 / (int)!!(expr) - 1] ) 46 | #else 47 | // Some other compilers fail when declaring same function multiple times in class, 48 | // so differentiate them by line 49 | #define BOOST_STATIC_ASSERT( expr ) \ 50 | void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] ) 51 | #endif 52 | #endif 53 | 54 | typedef struct 55 | #ifdef NO_UNALIGNED_ACCESS 56 | __attribute ((packed)) 57 | #endif 58 | { 59 | uint32_t val; 60 | }unaligned_uint32_t; 61 | 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper070.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 20 | * Mapper 180 Crazy Climber 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include "Nes_Mapper.h" 27 | 28 | // Mapper_74x161x162x32 29 | 30 | template < int mapperId > 31 | class Mapper_74x161x162x32 : public Nes_Mapper { 32 | public: 33 | Mapper_74x161x162x32() 34 | { 35 | register_state( &bank, 1 ); 36 | } 37 | 38 | virtual void reset_state() 39 | { 40 | if ( mapperId == 86 ) 41 | bank = ~0; 42 | } 43 | 44 | virtual void apply_mapping() 45 | { 46 | if ( mapperId == 152 ) write( 0, 0, bank ); 47 | if ( mapperId == 70 ) write( 0, 0, bank ); 48 | if ( mapperId == 86 ) 49 | { 50 | intercept_writes( 0x6000, 1 ); 51 | write_intercepted( 0, 0x6000, bank ); 52 | } 53 | } 54 | 55 | virtual bool write_intercepted( nes_time_t, nes_addr_t addr, int data ) 56 | { 57 | if ( addr != 0x6000 ) return false; 58 | if ( mapperId == 152 ) return false; 59 | if ( mapperId == 70 ) return false; 60 | 61 | bank = data; 62 | set_prg_bank( 0x8000, bank_32k, ( bank >> 4 ) & 0x03 ); 63 | set_chr_bank( 0x0000, bank_8k, ( ( bank >> 4 ) & 0x04 ) | ( bank & 0x03 ) ); 64 | 65 | return true; 66 | } 67 | 68 | virtual void write( nes_time_t, nes_addr_t addr, int data ) 69 | { 70 | if ( mapperId == 86) return; 71 | 72 | bank = handle_bus_conflict (addr, data ); 73 | set_prg_bank( 0x8000, bank_16k, ( bank >> 4 ) & 0x07 ); 74 | set_chr_bank( 0x0000, bank_8k, bank & 0x0F ); 75 | mirror_single( ( bank >> 7) & 0x01 ); 76 | } 77 | 78 | uint8_t bank; 79 | }; 80 | 81 | typedef Mapper_74x161x162x32<70> Mapper070; -------------------------------------------------------------------------------- /nes_emu/mappers/mapper079.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | * 19 | * This mapper was added by retrowertz for Libretro port of QuickNES. 20 | * 21 | * Mapper 079 22 | * Mapper 113 23 | * Nina-03 / Nina-06 24 | */ 25 | 26 | #include "Nes_Mapper.h" 27 | 28 | #pragma once 29 | 30 | template < bool multicart > 31 | class Mapper_AveNina : public Nes_Mapper { 32 | public: 33 | Mapper_AveNina() 34 | { 35 | register_state( ®s, 1 ); 36 | } 37 | 38 | void write_regs(); 39 | 40 | virtual void reset_state() 41 | { 42 | intercept_writes( 0x4000, 0x1000 ); 43 | intercept_writes( 0x5000, 0x1000 ); 44 | } 45 | 46 | virtual void apply_mapping() 47 | { 48 | write_intercepted( 0, 0x4100, regs ); 49 | } 50 | 51 | virtual bool write_intercepted( nes_time_t, nes_addr_t addr , int data ) 52 | { 53 | if ( addr < 0x4100 || addr > 0x5FFF ) 54 | return false; 55 | 56 | if ( addr & 0x100 ) 57 | regs = data; 58 | 59 | write_regs(); 60 | return true; 61 | } 62 | 63 | virtual void write( nes_time_t, nes_addr_t addr, int data ) 64 | { 65 | if ( multicart == 0 && 66 | ( ( addr == 0x8000 ) || ( addr & 0xFCB0 ) == 0xFCB0 ) ) 67 | set_chr_bank( 0, bank_8k, data & 0x07 ); 68 | } 69 | 70 | uint8_t regs; 71 | }; 72 | 73 | template < bool multicart > 74 | void Mapper_AveNina< multicart >::write_regs() 75 | { 76 | if ( multicart == 0 ) 77 | { 78 | set_prg_bank ( 0x8000, bank_32k, ( regs >> 3 ) & 0x01 ); 79 | set_chr_bank ( 0, bank_8k, regs & 0x07 ); 80 | } 81 | else 82 | { 83 | set_prg_bank ( 0x8000, bank_32k, ( regs >> 3 ) & 0x07 ); 84 | set_chr_bank ( 0x0000, bank_8k, ( ( regs >> 3 ) & 0x08 ) | ( regs & 0x07 ) ); 85 | if ( regs & 0x80 ) mirror_vert(); 86 | else mirror_horiz(); 87 | } 88 | } 89 | 90 | typedef Mapper_AveNina Mapper079; 91 | -------------------------------------------------------------------------------- /nes_emu/Nes_Vrc6_Apu.h: -------------------------------------------------------------------------------- 1 | 2 | // Konami VRC6 sound chip emulator 3 | 4 | // Nes_Snd_Emu 0.1.7 5 | 6 | #ifndef NES_VRC6_APU_H 7 | #define NES_VRC6_APU_H 8 | 9 | #include 10 | 11 | #include "Nes_Apu.h" 12 | #include "Blip_Buffer.h" 13 | 14 | struct vrc6_apu_state_t; 15 | 16 | class Nes_Vrc6_Apu { 17 | public: 18 | Nes_Vrc6_Apu(); 19 | ~Nes_Vrc6_Apu(); 20 | 21 | // See Nes_Apu.h for reference 22 | void reset(); 23 | void volume( double ); 24 | void treble_eq( blip_eq_t const& ); 25 | void output( Blip_Buffer* ); 26 | enum { osc_count = 3 }; 27 | void osc_output( int index, Blip_Buffer* ); 28 | void end_frame( nes_time_t ); 29 | void save_state( vrc6_apu_state_t* ) const; 30 | void load_state( vrc6_apu_state_t const& ); 31 | 32 | // Oscillator 0 write-only registers are at $9000-$9002 33 | // Oscillator 1 write-only registers are at $A000-$A002 34 | // Oscillator 2 write-only registers are at $B000-$B002 35 | enum { reg_count = 3 }; 36 | enum { base_addr = 0x9000 }; 37 | enum { addr_step = 0x1000 }; 38 | void write_osc( nes_time_t, int osc, int reg, int data ); 39 | 40 | private: 41 | // noncopyable 42 | Nes_Vrc6_Apu( const Nes_Vrc6_Apu& ); 43 | Nes_Vrc6_Apu& operator = ( const Nes_Vrc6_Apu& ); 44 | 45 | struct Vrc6_Osc 46 | { 47 | uint8_t regs [3]; 48 | Blip_Buffer* output; 49 | int delay; 50 | int last_amp; 51 | int phase; 52 | int amp; // only used by saw 53 | 54 | int period() const 55 | { 56 | return (regs [2] & 0x0f) * 0x100L + regs [1] + 1; 57 | } 58 | }; 59 | 60 | Vrc6_Osc oscs [osc_count]; 61 | nes_time_t last_time; 62 | 63 | Blip_Synth saw_synth; 64 | Blip_Synth square_synth; 65 | 66 | void run_until( nes_time_t ); 67 | void run_square( Vrc6_Osc& osc, nes_time_t ); 68 | void run_saw( nes_time_t ); 69 | }; 70 | 71 | struct vrc6_apu_state_t 72 | { 73 | uint8_t regs [3] [3]; 74 | uint8_t saw_amp; 75 | uint16_t delays [3]; 76 | uint8_t phases [3]; 77 | uint8_t unused; 78 | }; 79 | BOOST_STATIC_ASSERT( sizeof (vrc6_apu_state_t) == 20 ); 80 | 81 | inline void Nes_Vrc6_Apu::osc_output( int i, Blip_Buffer* buf ) 82 | { 83 | oscs [i].output = buf; 84 | } 85 | 86 | inline void Nes_Vrc6_Apu::volume( double v ) 87 | { 88 | double const factor = 0.0967 * 2; 89 | saw_synth.volume( factor / 31 * v ); 90 | square_synth.volume( factor * 0.5 / 15 * v ); 91 | } 92 | 93 | inline void Nes_Vrc6_Apu::treble_eq( blip_eq_t const& eq ) 94 | { 95 | saw_synth.treble_eq( eq ); 96 | square_synth.treble_eq( eq ); 97 | } 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper015.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2018. 2 | * This module is free software; you 3 | * can redistribute it and/or modify it under the terms of the GNU Lesser 4 | * General Public License as published by the Free Software Foundation; either 5 | * version 2.1 of the License, or (at your option) any later version. This 6 | * module is distributed in the hope that it will be useful, but WITHOUT ANY 7 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 8 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 9 | * more details. You should have received a copy of the GNU Lesser General 10 | * Public License along with this module; if not, write to the Free Software 11 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 12 | * 13 | * This mapper was added by retrowertz for Libretro port of QuickNES. 14 | * 15 | * 100-in-1 Contra Function 16 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "Nes_Mapper.h" 21 | 22 | struct Mapper015_state_t 23 | { 24 | uint8_t prg_bank [ 4 ]; 25 | uint8_t mirroring; 26 | }; 27 | 28 | BOOST_STATIC_ASSERT( sizeof (Mapper015_state_t) == 5 ); 29 | 30 | // K-1029, K-1030P 31 | 32 | class Mapper015 : public Nes_Mapper, Mapper015_state_t { 33 | public: 34 | Mapper015() 35 | { 36 | i = 0; 37 | Mapper015_state_t* state = this; 38 | register_state( state, sizeof *state ); 39 | } 40 | 41 | virtual void reset_state() 42 | { 43 | write( 0, 0x8000, 0 ); 44 | } 45 | 46 | virtual void apply_mapping() 47 | { 48 | enable_sram(); 49 | set_chr_bank ( 0, bank_8k, 0 ); 50 | for ( i = 0; i < sizeof prg_bank; i++ ) 51 | set_prg_bank ( 0x8000 + ( i * 0x2000 ), bank_8k, prg_bank [i] ); 52 | switch ( mirroring ) 53 | { 54 | case 0: mirror_vert(); break; 55 | case 1: mirror_horiz(); break; 56 | } 57 | } 58 | 59 | virtual void write( nes_time_t, nes_addr_t addr, int data ) 60 | { 61 | uint8_t bank = ( data & 0x3F ) << 1; 62 | uint8_t sbank = ( data >> 7 ) & 1; 63 | 64 | mirroring = ( data >> 6 ) & 1; 65 | switch ( addr & 3 ) 66 | { 67 | case 0: 68 | for ( i = 0; i < sizeof prg_bank; i++ ) 69 | prg_bank [ i ] = bank + i; 70 | apply_mapping(); 71 | break; 72 | case 2: 73 | for ( i = 0; i < sizeof prg_bank; i++ ) 74 | prg_bank [ i ] = bank | sbank; 75 | apply_mapping(); 76 | break; 77 | case 1: 78 | case 3: 79 | for ( i = 0; i < sizeof prg_bank; i++ ) 80 | { 81 | if ( i >= 2 && !( addr & 2 ) ) 82 | bank = 0x7E; 83 | prg_bank [ i ] = bank + ( i & 1 ); 84 | } 85 | apply_mapping(); 86 | break; 87 | } 88 | } 89 | 90 | unsigned long int i; 91 | }; 92 | 93 | -------------------------------------------------------------------------------- /libretro/libretro-common/include/libretro_gskit_ps2.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2010-2020 The RetroArch team 2 | * 3 | * --------------------------------------------------------------------------------------------- 4 | * The following license statement only applies to this libretro API header (libretro_d3d.h) 5 | * --------------------------------------------------------------------------------------------- 6 | * 7 | * Permission is hereby granted, free of charge, 8 | * to any person obtaining a copy of this software and associated documentation files (the 9 | * "Software"), 10 | * to deal in the Software without restriction, including without limitation the rights to 11 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 12 | * and to permit persons to whom the Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all copies or 16 | * substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 19 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | #ifndef LIBRETRO_GSKIT_PS2_H_ 28 | #define LIBRETRO_GSKIT_PS2_H_ 29 | 30 | #include "libretro.h" 31 | 32 | #if defined(PS2) 33 | 34 | #include 35 | 36 | #define RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION 2 37 | 38 | struct retro_hw_ps2_insets 39 | { 40 | float top; 41 | float left; 42 | float bottom; 43 | float right; 44 | }; 45 | 46 | #define empty_ps2_insets (struct retro_hw_ps2_insets){0.f, 0.f, 0.f, 0.f} 47 | 48 | struct retro_hw_render_interface_gskit_ps2 49 | { 50 | /* Must be set to RETRO_HW_RENDER_INTERFACE_GSKIT_PS2. */ 51 | enum retro_hw_render_interface_type interface_type; 52 | /* Must be set to RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION. */ 53 | unsigned interface_version; 54 | 55 | /* Opaque handle to the GSKit_PS2 backend in the frontend 56 | * which must be passed along to all function pointers 57 | * in this interface. 58 | */ 59 | GSTEXTURE *coreTexture; 60 | struct retro_hw_ps2_insets padding; 61 | }; 62 | typedef struct retro_hw_render_interface_gskit_ps2 RETRO_HW_RENDER_INTEFACE_GSKIT_PS2; 63 | 64 | #endif 65 | 66 | #endif /* LIBRETRO_GSKIT_PS2_H_ */ 67 | -------------------------------------------------------------------------------- /nes_emu/Nes_Namco_Apu.h: -------------------------------------------------------------------------------- 1 | 2 | // Namco 106 sound chip emulator 3 | 4 | // Nes_Snd_Emu 0.1.7 5 | 6 | #ifndef NES_NAMCO_APU_H 7 | #define NES_NAMCO_APU_H 8 | 9 | #include 10 | #include "Nes_Apu.h" 11 | 12 | struct namco_state_t; 13 | 14 | class Nes_Namco_Apu { 15 | public: 16 | Nes_Namco_Apu(); 17 | ~Nes_Namco_Apu(); 18 | 19 | // See Nes_Apu.h for reference. 20 | void volume( double ); 21 | void treble_eq( const blip_eq_t& ); 22 | void output( Blip_Buffer* ); 23 | enum { osc_count = 8 }; 24 | void osc_output( int index, Blip_Buffer* ); 25 | void reset(); 26 | void end_frame( nes_time_t ); 27 | 28 | // Read/write data register is at 0x4800 29 | enum { data_reg_addr = 0x4800 }; 30 | void write_data( nes_time_t, int ); 31 | int read_data(); 32 | 33 | // Write-only address register is at 0xF800 34 | enum { addr_reg_addr = 0xF800 }; 35 | void write_addr( int ); 36 | 37 | // to do: implement save/restore 38 | void save_state( namco_state_t* out ) const; 39 | void load_state( namco_state_t const& ); 40 | 41 | private: 42 | // noncopyable 43 | Nes_Namco_Apu( const Nes_Namco_Apu& ); 44 | Nes_Namco_Apu& operator = ( const Nes_Namco_Apu& ); 45 | 46 | struct Namco_Osc { 47 | long delay; 48 | Blip_Buffer* output; 49 | short last_amp; 50 | short wave_pos; 51 | }; 52 | 53 | Namco_Osc oscs [osc_count]; 54 | 55 | nes_time_t last_time; 56 | int addr_reg; 57 | 58 | enum { reg_count = 0x80 }; 59 | uint8_t reg [reg_count]; 60 | Blip_Synth synth; 61 | 62 | uint8_t& access(); 63 | void run_until( nes_time_t ); 64 | }; 65 | 66 | struct namco_state_t 67 | { 68 | uint8_t regs [0x80]; 69 | uint8_t addr; 70 | uint8_t unused; 71 | uint8_t positions [8]; 72 | uint32_t delays [8]; 73 | }; 74 | 75 | BOOST_STATIC_ASSERT( sizeof (namco_state_t) == 172 ); 76 | 77 | inline uint8_t& Nes_Namco_Apu::access() 78 | { 79 | int addr = addr_reg & 0x7f; 80 | if ( addr_reg & 0x80 ) 81 | addr_reg = (addr + 1) | 0x80; 82 | return reg [addr]; 83 | } 84 | 85 | inline void Nes_Namco_Apu::volume( double v ) { synth.volume( 0.10 / osc_count * v ); } 86 | 87 | inline void Nes_Namco_Apu::treble_eq( const blip_eq_t& eq ) { synth.treble_eq( eq ); } 88 | 89 | inline void Nes_Namco_Apu::write_addr( int v ) { addr_reg = v; } 90 | 91 | inline int Nes_Namco_Apu::read_data() { return access(); } 92 | 93 | inline void Nes_Namco_Apu::osc_output( int i, Blip_Buffer* buf ) 94 | { 95 | oscs [i].output = buf; 96 | } 97 | 98 | inline void Nes_Namco_Apu::write_data( nes_time_t time, int data ) 99 | { 100 | run_until( time ); 101 | access() = data; 102 | } 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper206.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 3/24/18 20 | * 21 | * Mapper 88 22 | * Mapper 154 23 | * Mapper 206 24 | */ 25 | 26 | #pragma once 27 | 28 | #include "Nes_Mapper.h" 29 | 30 | struct namco_34xx_state_t 31 | { 32 | uint8_t bank [ 8 ]; 33 | uint8_t mirr; 34 | uint8_t mode; 35 | }; 36 | 37 | BOOST_STATIC_ASSERT( sizeof (namco_34xx_state_t) == 10 ); 38 | 39 | // Namco_34xx 40 | 41 | class Mapper206 : public Nes_Mapper, namco_34xx_state_t { 42 | public: 43 | Mapper206() 44 | { 45 | namco_34xx_state_t *state = this; 46 | register_state( state, sizeof *state ); 47 | } 48 | 49 | virtual void reset_state() 50 | { } 51 | 52 | virtual void apply_mapping() 53 | { 54 | set_chr_bank( 0x0000, bank_2k, bank [ 0 ] ); 55 | set_chr_bank( 0x0800, bank_2k, bank [ 1 ] ); 56 | for ( int i = 0; i < 4; i++ ) 57 | set_chr_bank( 0x1000 + ( i << 10 ), bank_1k, bank [ i + 2 ] ); 58 | 59 | set_prg_bank( 0x8000, bank_8k, bank [ 6 ] ); 60 | set_prg_bank( 0xA000, bank_8k, bank [ 7 ] ); 61 | set_prg_bank( 0xC000, bank_8k, ~1 ); 62 | set_prg_bank( 0xE000, bank_8k, ~0 ); 63 | } 64 | 65 | virtual void write( nes_time_t, nes_addr_t addr, int data ) 66 | { 67 | switch ( addr & 0xE001 ) 68 | { 69 | case 0x8000: 70 | mode = data; 71 | break; 72 | case 0x8001: 73 | mode &= 0x07; 74 | switch ( mode ) 75 | { 76 | case 0: case 1: 77 | bank [ mode ] = data >> 1; 78 | set_chr_bank( 0x0000 + ( mode << 11 ), bank_2k, bank [ mode ] ); 79 | break; 80 | case 2: case 3: case 4: case 5: 81 | bank [ mode ] = data; 82 | set_chr_bank( 0x1000 + ( ( mode - 2 ) << 10 ), bank_1k, bank [ mode ] ); 83 | break; 84 | case 6: case 7: 85 | bank [ mode ] = data; 86 | set_prg_bank( 0x8000 + ( ( mode - 6 ) << 13 ), bank_8k, bank [ mode ] ); 87 | break; 88 | } 89 | break; 90 | } 91 | } 92 | }; 93 | 94 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper033.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 20 | * Mapper 33 - Taito TC0190 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include "Nes_Mapper.h" 27 | 28 | struct tc0190_state_t 29 | { 30 | uint8_t preg [ 2 ]; 31 | uint8_t creg [ 6 ]; 32 | uint8_t mirr; 33 | }; 34 | 35 | BOOST_STATIC_ASSERT( sizeof ( tc0190_state_t ) == 9 ); 36 | 37 | // TaitoTC0190 38 | 39 | class Mapper033 : public Nes_Mapper, tc0190_state_t { 40 | public: 41 | Mapper033() 42 | { 43 | tc0190_state_t *state = this; 44 | register_state( state, sizeof *state ); 45 | } 46 | 47 | virtual void reset_state() 48 | { } 49 | 50 | virtual void apply_mapping() 51 | { 52 | for ( int i = 0; i < 2; i++ ) 53 | { 54 | set_prg_bank ( 0x8000 + ( i << 13 ), bank_8k, preg [ i ] ); 55 | set_chr_bank ( 0x0000 + ( i << 11 ), bank_2k, creg [ i ] ); 56 | } 57 | 58 | for ( int i = 0; i < 4; i++ ) 59 | set_chr_bank ( 0x1000 + ( i << 10 ), bank_1k, creg [ 2 + i ] ); 60 | 61 | if ( mirr ) mirror_horiz(); 62 | else mirror_vert(); 63 | } 64 | 65 | virtual void write( nes_time_t, nes_addr_t addr, int data ) 66 | { 67 | switch ( addr & 0xA003 ) 68 | { 69 | case 0x8000: 70 | preg [ 0 ] = data & 0x3F; 71 | mirr = data >> 6; 72 | set_prg_bank ( 0x8000, bank_8k, preg [ 0 ] ); 73 | if ( mirr ) mirror_horiz(); 74 | else mirror_vert(); 75 | break; 76 | case 0x8001: 77 | preg [ 1 ] = data & 0x3F; 78 | set_prg_bank ( 0xA000, bank_8k, preg [ 1 ] ); 79 | break; 80 | case 0x8002: case 0x8003: 81 | addr &= 0x01; 82 | creg [ addr ] = data; 83 | set_chr_bank ( addr << 11, bank_2k, creg [ addr ] ); 84 | break; 85 | case 0xA000: case 0xA001: 86 | case 0xA002: case 0xA003: 87 | addr &= 0x03; 88 | creg [ 2 + addr ] = data; 89 | set_chr_bank ( 0x1000 | ( addr << 10 ), bank_1k, creg [ 2 + addr ] ); 90 | break; 91 | } 92 | } 93 | }; 94 | -------------------------------------------------------------------------------- /nes_emu/Effects_Buffer.h: -------------------------------------------------------------------------------- 1 | 2 | // Multi-channel effects buffer with panning, echo and reverb 3 | 4 | // Game_Music_Emu 0.3.0 5 | 6 | #ifndef EFFECTS_BUFFER_H 7 | #define EFFECTS_BUFFER_H 8 | 9 | #include 10 | #include "Multi_Buffer.h" 11 | 12 | // Effects_Buffer uses several buffers and outputs stereo sample pairs. 13 | class Effects_Buffer : public Multi_Buffer { 14 | public: 15 | // If center_only is true, only center buffers are created and 16 | // less memory is used. 17 | Effects_Buffer( bool center_only = false ); 18 | 19 | // Channel Effect Center Pan 20 | // --------------------------------- 21 | // 0,5 reverb pan_1 22 | // 1,6 reverb pan_2 23 | // 2,7 echo - 24 | // 3 echo - 25 | // 4 echo - 26 | 27 | // Channel configuration 28 | struct config_t { 29 | double pan_1; // -1.0 = left, 0.0 = center, 1.0 = right 30 | double pan_2; 31 | double echo_delay; // msec 32 | double echo_level; // 0.0 to 1.0 33 | double reverb_delay; // msec 34 | double delay_variance; // difference between left/right delays (msec) 35 | double reverb_level; // 0.0 to 1.0 36 | bool effects_enabled; // if false, use optimized simple mixer 37 | config_t(); 38 | }; 39 | 40 | // Set configuration of buffer 41 | virtual void config( const config_t& ); 42 | void set_depth( double ); 43 | 44 | public: 45 | ~Effects_Buffer(); 46 | const char *set_sample_rate( long samples_per_sec, int msec = blip_default_length ); 47 | void clock_rate( long ); 48 | void bass_freq( int ); 49 | void clear(); 50 | channel_t channel( int ); 51 | void end_frame( blip_time_t, bool was_stereo = true ); 52 | long read_samples( blip_sample_t*, long ); 53 | long samples_avail() const; 54 | private: 55 | typedef long fixed_t; 56 | 57 | enum { max_buf_count = 7 }; 58 | Blip_Buffer bufs [max_buf_count]; 59 | enum { chan_count = 5 }; 60 | channel_t channels [chan_count]; 61 | config_t config_; 62 | long stereo_remain; 63 | long effect_remain; 64 | int buf_count; 65 | bool effects_enabled; 66 | 67 | blip_sample_t* reverb_buf; 68 | blip_sample_t* echo_buf; 69 | int reverb_pos; 70 | int echo_pos; 71 | 72 | struct { 73 | fixed_t pan_1_levels [2]; 74 | fixed_t pan_2_levels [2]; 75 | int echo_delay_l; 76 | int echo_delay_r; 77 | fixed_t echo_level; 78 | int reverb_delay_l; 79 | int reverb_delay_r; 80 | fixed_t reverb_level; 81 | } chans; 82 | 83 | void mix_mono( blip_sample_t*, long ); 84 | void mix_stereo( blip_sample_t*, long ); 85 | void mix_enhanced( blip_sample_t*, long ); 86 | void mix_mono_enhanced( blip_sample_t*, long ); 87 | }; 88 | 89 | inline Effects_Buffer::channel_t Effects_Buffer::channel( int i ) { 90 | return channels [i % chan_count]; 91 | } 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /nes_emu/Nes_Effects_Buffer.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Nes_Emu 0.7.0. http://www.slack.net/~ant/libs/ 3 | 4 | #include "Nes_Effects_Buffer.h" 5 | 6 | #include "Nes_Apu.h" 7 | 8 | /* Copyright (C) 2004-2006 Shay Green. This module is free software; you 9 | can redistribute it and/or modify it under the terms of the GNU Lesser 10 | General Public License as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. This 12 | module is distributed in the hope that it will be useful, but WITHOUT ANY 13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 15 | more details. You should have received a copy of the GNU Lesser General 16 | Public License along with this module; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 18 | 19 | #include "blargg_source.h" 20 | 21 | Nes_Effects_Buffer::Nes_Effects_Buffer() : 22 | Effects_Buffer( true ) // nes never uses stereo channels 23 | { 24 | config_t c; 25 | c.effects_enabled = false; 26 | config( c ); 27 | } 28 | 29 | Nes_Effects_Buffer::~Nes_Effects_Buffer() { } 30 | 31 | Multi_Buffer* set_apu( Nes_Effects_Buffer* buf, Nes_Apu* apu ) 32 | { 33 | buf->set_apu( apu ); 34 | return buf; 35 | } 36 | 37 | void Nes_Effects_Buffer::enable_nonlinearity( bool b ) 38 | { 39 | if ( b ) 40 | clear(); 41 | Nes_Apu* apu = nonlin.enable( b, channel( 2 ).center ); 42 | apu->osc_output( 0, channel( 0 ).center ); 43 | apu->osc_output( 1, channel( 1 ).center ); 44 | } 45 | 46 | void Nes_Effects_Buffer::config( const config_t& in ) 47 | { 48 | config_t c = in; 49 | if ( !c.effects_enabled ) 50 | { 51 | // effects must always be enabled to keep separate buffers, so 52 | // set parameters to be equivalent to disabled 53 | c.pan_1 = 0; 54 | c.pan_2 = 0; 55 | c.echo_level = 0; 56 | c.reverb_level = 0; 57 | c.effects_enabled = true; 58 | } 59 | Effects_Buffer::config( c ); 60 | } 61 | 62 | const char * Nes_Effects_Buffer::set_sample_rate( long rate, int msec ) 63 | { 64 | enable_nonlinearity( nonlin.enabled ); // reapply 65 | return Effects_Buffer::set_sample_rate( rate, msec ); 66 | } 67 | 68 | void Nes_Effects_Buffer::clear() 69 | { 70 | nonlin.clear(); 71 | Effects_Buffer::clear(); 72 | } 73 | 74 | Nes_Effects_Buffer::channel_t Nes_Effects_Buffer::channel( int i ) 75 | { 76 | return Effects_Buffer::channel( (2 <= i && i <= 4) ? 2 : i & 1 ); 77 | } 78 | 79 | long Nes_Effects_Buffer::read_samples( blip_sample_t* out, long count ) 80 | { 81 | count = 2 * nonlin.make_nonlinear( *channel( 2 ).center, count / 2 ); 82 | return Effects_Buffer::read_samples( out, count ); 83 | } 84 | 85 | void Nes_Effects_Buffer::SaveAudioBufferState() 86 | { 87 | } 88 | 89 | void Nes_Effects_Buffer::RestoreAudioBufferState() 90 | { 91 | } 92 | -------------------------------------------------------------------------------- /nes_emu/Data_Reader.cpp: -------------------------------------------------------------------------------- 1 | // File_Extractor 1.0.0. http://www.slack.net/~ant/ 2 | 3 | #include "Data_Reader.h" 4 | 5 | #include "blargg_endian.h" 6 | #include 7 | 8 | /* Copyright (C) 2005-2009 Shay Green. This module is free software; you 9 | can redistribute it and/or modify it under the terms of the GNU Lesser 10 | General Public License as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. This 12 | module is distributed in the hope that it will be useful, but WITHOUT ANY 13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | details. You should have received a copy of the GNU Lesser General Public 16 | License along with this module; if not, write to the Free Software Foundation, 17 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 18 | 19 | #include "blargg_source.h" 20 | 21 | // Data_Reader 22 | 23 | const char * Data_Reader::read( void* p, int n ) 24 | { 25 | if ( n < 0 ) 26 | return "Internal usage bug"; 27 | 28 | if ( n <= 0 ) 29 | return 0; 30 | 31 | if ( n > remain() ) 32 | return "Truncated file"; 33 | 34 | const char * err = read_v( p, n ); 35 | if ( !err ) 36 | remain_ -= n; 37 | 38 | return err; 39 | } 40 | 41 | const char * Data_Reader::read_avail( void* p, int* n_ ) 42 | { 43 | int n = min( (uint64_t)(*n_), remain() ); 44 | *n_ = 0; 45 | 46 | if ( n < 0 ) 47 | return "Internal usage bug"; 48 | 49 | if ( n <= 0 ) 50 | return 0; 51 | 52 | const char * err = read_v( p, n ); 53 | if ( !err ) 54 | { 55 | remain_ -= n; 56 | *n_ = n; 57 | } 58 | 59 | return err; 60 | } 61 | 62 | const char * Data_Reader::read_avail( void* p, long* n ) 63 | { 64 | int i = STATIC_CAST(int, *n); 65 | const char * err = read_avail( p, &i ); 66 | *n = i; 67 | return err; 68 | } 69 | 70 | const char * Data_Reader::skip_v( int count ) 71 | { 72 | char buf [512]; 73 | while ( count ) 74 | { 75 | int n = min( count, (int) sizeof buf ); 76 | count -= n; 77 | RETURN_ERR( read_v( buf, n ) ); 78 | } 79 | return 0; 80 | } 81 | 82 | const char * Data_Reader::skip( int n ) 83 | { 84 | if ( n < 0 ) 85 | return "Internal usage bug"; 86 | 87 | if ( n <= 0 ) 88 | return 0; 89 | 90 | if ( n > remain() ) 91 | return "Truncated file"; 92 | 93 | const char * err = skip_v( n ); 94 | if ( !err ) 95 | remain_ -= n; 96 | 97 | return err; 98 | } 99 | 100 | 101 | // File_Reader 102 | 103 | // Mem_File_Reader 104 | 105 | Mem_File_Reader::Mem_File_Reader( const void* p, long s ) : 106 | begin( STATIC_CAST(const char*, p) ) 107 | { 108 | set_size( s ); 109 | } 110 | 111 | const char * Mem_File_Reader::read_v( void* p, int s ) 112 | { 113 | memcpy( p, begin + tell(), s ); 114 | return 0; 115 | } 116 | -------------------------------------------------------------------------------- /nes_emu/emu2413_state.cpp: -------------------------------------------------------------------------------- 1 | #include "emu2413_state.h" 2 | #include 3 | 4 | #ifdef __cplusplus 5 | extern "C" 6 | { 7 | #endif 8 | 9 | int OPLL_serialize_size() 10 | { 11 | return sizeof(OPLL_STATE); 12 | } 13 | 14 | void OPLL_serialize(const OPLL * opll, OPLL_STATE* state) 15 | { 16 | int i; 17 | 18 | state->pm_phase = opll->pm_phase; 19 | state->am_phase = opll->am_phase; 20 | 21 | for (i = 0; i < 12; i++) 22 | { 23 | OPLL_SLOT_STATE *slotState = &(state->slot[i]); 24 | const OPLL_SLOT *slot= &(opll->slot[i]); 25 | slotState->feedback = slot->feedback; 26 | slotState->output[0] = slot->output[0]; 27 | slotState->output[1] = slot->output[1]; 28 | slotState->phase = slot->phase; 29 | slotState->pgout = slot->pgout; 30 | slotState->eg_mode = slot->eg_mode; 31 | slotState->eg_phase = slot->eg_phase; 32 | slotState->eg_dphase = slot->eg_dphase; 33 | slotState->egout = slot->egout; 34 | } 35 | } 36 | 37 | #define BYTESWAP(xxxx) {uint32_t _temp = (uint32_t)(xxxx);\ 38 | ((uint8_t*)&(xxxx))[0] = (uint8_t)((_temp) >> 24);\ 39 | ((uint8_t*)&(xxxx))[1] = (uint8_t)((_temp) >> 16);\ 40 | ((uint8_t*)&(xxxx))[2] = (uint8_t)((_temp) >> 8);\ 41 | ((uint8_t*)&(xxxx))[3] = (uint8_t)((_temp) >> 0);\ 42 | } 43 | 44 | 45 | #define SET(xxxx,yyyy) { if ((xxxx) != (yyyy)) {\ 46 | (xxxx) = (yyyy);\ 47 | } 48 | 49 | void OPLL_deserialize(OPLL * opll, const OPLL_STATE* state) 50 | { 51 | int i; 52 | 53 | opll->pm_phase = state->pm_phase; 54 | opll->am_phase = state->am_phase; 55 | 56 | for (i = 0; i < 12; i++) 57 | { 58 | const OPLL_SLOT_STATE *slotState = &(state->slot[i]); 59 | OPLL_SLOT *slot = &(opll->slot[i]); 60 | slot->feedback = slotState->feedback; 61 | slot->output[0] = slotState->output[0]; 62 | slot->output[1] = slotState->output[1]; 63 | slot->phase = slotState->phase; 64 | slot->pgout = slotState->pgout; 65 | slot->eg_mode = slotState->eg_mode; 66 | slot->eg_phase = slotState->eg_phase; 67 | slot->eg_dphase = slotState->eg_dphase; 68 | slot->egout = slotState->egout; 69 | } 70 | } 71 | 72 | static bool IsLittleEndian() 73 | { 74 | int i = 42; 75 | if (((char*)&i)[0] == 42) 76 | { 77 | return true; 78 | } 79 | return false; 80 | } 81 | 82 | void OPLL_state_byteswap(OPLL_STATE *state) 83 | { 84 | int i; 85 | if (IsLittleEndian()) return; 86 | 87 | BYTESWAP(state->pm_phase); 88 | BYTESWAP(state->am_phase); 89 | 90 | for (i = 0; i < 12; i++) 91 | { 92 | OPLL_SLOT_STATE *slotState = &(state->slot[i]); 93 | BYTESWAP(slotState->feedback); 94 | BYTESWAP(slotState->output[0]); 95 | BYTESWAP(slotState->output[1]); 96 | BYTESWAP(slotState->phase); 97 | BYTESWAP(slotState->pgout); 98 | BYTESWAP(slotState->eg_mode); 99 | BYTESWAP(slotState->eg_phase); 100 | BYTESWAP(slotState->eg_dphase); 101 | BYTESWAP(slotState->egout); 102 | } 103 | } 104 | 105 | #ifdef __cplusplus 106 | } 107 | #endif 108 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper207.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 20 | * Taito's X1-005 ( Rev. B ) Fudou Myouou Den 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include "Nes_Mapper.h" 27 | 28 | struct taito_x1005_state_t 29 | { 30 | uint8_t preg [ 3 ]; 31 | uint8_t creg [ 6 ]; 32 | uint8_t nametable [ 2 ]; 33 | }; 34 | 35 | BOOST_STATIC_ASSERT( sizeof (taito_x1005_state_t) == 11 ); 36 | 37 | // TaitoX1005 38 | 39 | class Mapper207 : public Nes_Mapper, taito_x1005_state_t { 40 | public: 41 | Mapper207() 42 | { 43 | taito_x1005_state_t *state = this; 44 | register_state( state, sizeof *state ); 45 | } 46 | 47 | virtual void reset_state() 48 | { } 49 | 50 | virtual void apply_mapping() 51 | { 52 | int i; 53 | intercept_writes( 0x7EF0, 1 ); 54 | for ( i = 0; i < 3; i++ ) 55 | set_prg_bank( 0x8000 + ( i << 13 ), bank_8k, preg [ i ] ); 56 | for ( i = 0; i < 2; i++ ) 57 | set_chr_bank( 0x0000 + ( i << 11 ), bank_2k, creg [ i ] >> 1); 58 | for ( i = 0; i < 4; i++ ) 59 | set_chr_bank( 0x1000 + ( i << 10 ), bank_1k, creg [ 2 + i ] ); 60 | mirror_manual( nametable [ 0 ], nametable [ 0 ], nametable [ 1 ], nametable [ 1 ] ); 61 | } 62 | 63 | virtual bool write_intercepted( nes_time_t, nes_addr_t addr, int data ) 64 | { 65 | if ( addr < 0x7EF0 || addr > 0x7EFF ) 66 | return false; 67 | 68 | if ( ( addr & 0x0F ) < 6 ) 69 | { 70 | creg [ addr & 0x07 ] = data; 71 | if ( ( addr & 0x0F ) < 2 ) 72 | { 73 | nametable [ addr & 0x01 ] = data >> 7; 74 | mirror_manual( nametable [ 0 ], nametable [ 0 ], nametable [ 1 ], nametable [ 1 ] ); 75 | set_chr_bank( ( addr << 11 ) & 0x800, bank_2k, creg [ addr & 0x01 ] >> 1 ); 76 | return true; 77 | } 78 | 79 | set_chr_bank( 0x1000 | ( ( addr - 0x7EF2 ) << 10 ), bank_1k, creg [ addr & 0x07 ] ); 80 | return true; 81 | } 82 | 83 | addr = ( addr - 0x7EFA ) >> 1; 84 | preg [ addr ] = data; 85 | set_prg_bank( 0x8000 | ( addr << 13 ), bank_8k, preg [ addr ] ); 86 | return true; 87 | } 88 | 89 | virtual void write( nes_time_t, nes_addr_t addr, int data ) { } 90 | }; 91 | 92 | -------------------------------------------------------------------------------- /nes_emu/abstract_file.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "abstract_file.h" 3 | 4 | #include "blargg_config.h" 5 | 6 | #include 7 | #include 8 | 9 | /* Copyright (C) 2005-2006 Shay Green. Permission is hereby granted, free of 10 | charge, to any person obtaining a copy of this software module and associated 11 | documentation files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, copy, modify, 13 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and 14 | to permit persons to whom the Software is furnished to do so, subject to the 15 | following conditions: The above copyright notice and this permission notice 16 | shall be included in all copies or substantial portions of the Software. THE 17 | SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 18 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 19 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 23 | 24 | const char *Data_Writer::write( const void*, long ) { return 0; } 25 | 26 | // Mem_Writer 27 | 28 | Mem_Writer::Mem_Writer( void* p, long s, int b ) 29 | { 30 | data_ = (char*) p; 31 | size_ = 0; 32 | allocated = s; 33 | mode = b ? ignore_excess : fixed; 34 | } 35 | 36 | Mem_Writer::Mem_Writer() 37 | { 38 | data_ = 0; 39 | size_ = 0; 40 | allocated = 0; 41 | mode = expanding; 42 | } 43 | 44 | Mem_Writer::~Mem_Writer() 45 | { 46 | if ( ( mode == expanding ) && data_ ) 47 | free( data_ ); 48 | } 49 | 50 | const char *Mem_Writer::write( const void* p, long s ) 51 | { 52 | long remain = allocated - size_; 53 | if ( s > remain ) 54 | { 55 | if ( mode == fixed ) 56 | return "Tried to write more data than expected"; 57 | 58 | if ( mode == ignore_excess ) 59 | { 60 | s = remain; 61 | } 62 | else // expanding 63 | { 64 | long new_allocated = size_ + s; 65 | new_allocated += (new_allocated >> 1) + 2048; 66 | void* p = realloc( data_, new_allocated ); 67 | if ( !p ) 68 | return "Out of memory"; 69 | data_ = (char*) p; 70 | allocated = new_allocated; 71 | } 72 | } 73 | 74 | memcpy( data_ + size_, p, s ); 75 | size_ += s; 76 | 77 | return 0; 78 | } 79 | 80 | // Auto_File_Reader 81 | 82 | const char* Auto_File_Reader::open() 83 | { 84 | return 0; 85 | } 86 | 87 | Auto_File_Reader::~Auto_File_Reader() 88 | { 89 | if ( path ) 90 | delete data; 91 | } 92 | 93 | // Auto_File_Writer 94 | 95 | const char* Auto_File_Writer::open() 96 | { 97 | return 0; 98 | } 99 | 100 | const char* Auto_File_Writer::open_comp( int level ) 101 | { 102 | return 0; 103 | } 104 | 105 | Auto_File_Writer::~Auto_File_Writer() 106 | { 107 | } 108 | -------------------------------------------------------------------------------- /intl/activate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import glob 5 | import random as r 6 | 7 | # -------------------- MAIN -------------------- # 8 | 9 | if __name__ == '__main__': 10 | DIR_PATH = os.path.dirname(os.path.realpath(__file__)) 11 | if os.path.basename(DIR_PATH) != "intl": 12 | raise RuntimeError("Script is not in intl folder!") 13 | 14 | BASE_PATH = os.path.dirname(DIR_PATH) 15 | WORKFLOW_PATH = os.path.join(BASE_PATH, ".github", "workflows") 16 | PREP_WF = os.path.join(WORKFLOW_PATH, "crowdin_prep.yml") 17 | TRANSLATE_WF = os.path.join(WORKFLOW_PATH, "crowdin_translate.yml") 18 | CORE_NAME = os.path.basename(BASE_PATH) 19 | CORE_OP_FILE = os.path.join(BASE_PATH, "**", "libretro_core_options.h") 20 | 21 | core_options_hits = glob.glob(CORE_OP_FILE, recursive=True) 22 | 23 | if len(core_options_hits) == 0: 24 | raise RuntimeError("libretro_core_options.h not found!") 25 | elif len(core_options_hits) > 1: 26 | print("More than one libretro_core_options.h file found:\n\n") 27 | for i, file in enumerate(core_options_hits): 28 | print(f"{i} {file}\n") 29 | 30 | while True: 31 | user_choice = input("Please choose one ('q' will exit): ") 32 | if user_choice == 'q': 33 | exit(0) 34 | elif user_choice.isdigit(): 35 | core_op_file = core_options_hits[int(user_choice)] 36 | break 37 | else: 38 | print("Please make a valid choice!\n\n") 39 | else: 40 | core_op_file = core_options_hits[0] 41 | 42 | core_intl_file = os.path.join(os.path.dirname(core_op_file.replace(BASE_PATH, ''))[1:], 43 | 'libretro_core_options_intl.h') 44 | core_op_file = os.path.join(os.path.dirname(core_op_file.replace(BASE_PATH, ''))[1:], 45 | 'libretro_core_options.h') 46 | minutes = r.randrange(0, 59, 5) 47 | hour = r.randrange(0, 23) 48 | 49 | with open(PREP_WF, 'r') as wf_file: 50 | prep_txt = wf_file.read() 51 | 52 | prep_txt = prep_txt.replace("", CORE_NAME) 53 | prep_txt = prep_txt.replace("/libretro_core_options.h", 54 | core_op_file) 55 | with open(PREP_WF, 'w') as wf_file: 56 | wf_file.write(prep_txt) 57 | 58 | 59 | with open(TRANSLATE_WF, 'r') as wf_file: 60 | translate_txt = wf_file.read() 61 | 62 | translate_txt = translate_txt.replace('<0-59>', f"{minutes}") 63 | translate_txt = translate_txt.replace('<0-23>', f"{hour}") 64 | translate_txt = translate_txt.replace('# Fridays at , UTC', 65 | f"# Fridays at {hour%12}:{minutes if minutes > 9 else '0' + str(minutes)} {'AM' if hour < 12 else 'PM'}, UTC") 66 | translate_txt = translate_txt.replace("", CORE_NAME) 67 | translate_txt = translate_txt.replace('/libretro_core_options_intl.h', 68 | core_intl_file) 69 | with open(TRANSLATE_WF, 'w') as wf_file: 70 | wf_file.write(translate_txt) 71 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper075.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2018. 2 | * This module is free software; you 3 | * can redistribute it and/or modify it under the terms of the GNU Lesser 4 | * General Public License as published by the Free Software Foundation; either 5 | * version 2.1 of the License, or (at your option) any later version. This 6 | * module is distributed in the hope that it will be useful, but WITHOUT ANY 7 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 8 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 9 | * more details. You should have received a copy of the GNU Lesser General 10 | * Public License along with this module; if not, write to the Free Software 11 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 12 | * 13 | * This mapper was added by retrowertz for Libretro port of QuickNES. 14 | * 15 | * VRC-1 Konami 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "Nes_Mapper.h" 21 | 22 | struct vrc1_state_t 23 | { 24 | uint8_t prg_banks [ 3 ]; 25 | uint8_t chr_banks [ 2 ]; 26 | uint8_t chr_banks_hi [ 2 ]; 27 | uint8_t mirroring; 28 | }; 29 | 30 | BOOST_STATIC_ASSERT( sizeof ( vrc1_state_t ) == 8 ); 31 | 32 | // VRC1 33 | 34 | class Mapper075 : public Nes_Mapper, vrc1_state_t { 35 | public: 36 | Mapper075() 37 | { 38 | vrc1_state_t * state = this; 39 | register_state( state, sizeof * state ); 40 | } 41 | 42 | void reset_state() 43 | { 44 | } 45 | 46 | void apply_mapping() 47 | { 48 | update_prg_banks(); 49 | update_chr_banks(); 50 | update_mirroring(); 51 | } 52 | 53 | void write( nes_time_t, nes_addr_t addr, int data ) 54 | { 55 | switch ( addr & 0xF000 ) 56 | { 57 | case 0x8000: 58 | prg_banks [ 0 ] = data & 0xF; 59 | update_prg_banks(); 60 | break; 61 | case 0x9000: 62 | mirroring = data & 1; 63 | chr_banks_hi [ 0 ] = ( data & 2 ) << 3; 64 | chr_banks_hi [ 1 ] = ( data & 4 ) << 2; 65 | update_chr_banks(); 66 | update_mirroring(); 67 | break; 68 | case 0xa000: 69 | prg_banks [ 1 ] = data & 0xF; 70 | update_prg_banks(); 71 | break; 72 | case 0xc000: 73 | prg_banks [ 2 ] = data & 0xF; 74 | update_prg_banks(); 75 | break; 76 | case 0xe000: 77 | chr_banks [ 0 ] = data & 0xF; 78 | update_chr_banks(); 79 | break; 80 | case 0xf000: 81 | chr_banks [ 1 ] = data & 0xF; 82 | update_chr_banks(); 83 | break; 84 | } 85 | } 86 | 87 | void update_prg_banks() 88 | { 89 | set_prg_bank( 0x8000, bank_8k, prg_banks [ 0 ] ); 90 | set_prg_bank( 0xa000, bank_8k, prg_banks [ 1 ] ); 91 | set_prg_bank( 0xc000, bank_8k, prg_banks [ 2 ] ); 92 | } 93 | 94 | void update_chr_banks() 95 | { 96 | set_chr_bank( 0x0000, bank_4k, chr_banks [ 0 ] | chr_banks_hi [ 0 ] ); 97 | set_chr_bank( 0x1000, bank_4k, chr_banks [ 1 ] | chr_banks_hi [ 1 ] ); 98 | } 99 | 100 | void update_mirroring() 101 | { 102 | switch ( mirroring & 1 ) 103 | { 104 | case 1: mirror_horiz(); break; 105 | case 0: mirror_vert(); break; 106 | } 107 | } 108 | }; 109 | 110 | 111 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper001.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Nes_Emu 0.7.0. http://www.slack.net/~ant/ 4 | 5 | #include "Nes_Mapper.h" 6 | 7 | #include 8 | 9 | /* Copyright (C) 2004-2006 Shay Green. This module is free software; you 10 | can redistribute it and/or modify it under the terms of the GNU Lesser 11 | General Public License as published by the Free Software Foundation; either 12 | version 2.1 of the License, or (at your option) any later version. This 13 | module is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 16 | more details. You should have received a copy of the GNU Lesser General 17 | Public License along with this module; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 19 | 20 | #include "blargg_source.h" 21 | 22 | // MMC1 23 | 24 | class Mapper001 : public Nes_Mapper, mmc1_state_t { 25 | public: 26 | Mapper001() 27 | { 28 | mmc1_state_t* state = this; 29 | register_state( state, sizeof *state ); 30 | } 31 | 32 | virtual void reset_state() 33 | { 34 | regs [0] = 0x0f; 35 | regs [1] = 0x00; 36 | regs [2] = 0x01; 37 | regs [3] = 0x00; 38 | } 39 | 40 | virtual void apply_mapping() 41 | { 42 | enable_sram(); // early MMC1 always had SRAM enabled 43 | register_changed( 0 ); 44 | } 45 | 46 | virtual void write( nes_time_t, nes_addr_t addr, int data ) 47 | { 48 | if ( !(data & 0x80) ) 49 | { 50 | buf |= (data & 1) << bit; 51 | bit++; 52 | 53 | if ( bit >= 5 ) 54 | { 55 | int reg = addr >> 13 & 3; 56 | regs [reg] = buf & 0x1f; 57 | 58 | bit = 0; 59 | buf = 0; 60 | 61 | register_changed( reg ); 62 | } 63 | } 64 | else 65 | { 66 | bit = 0; 67 | buf = 0; 68 | regs [0] |= 0x0c; 69 | register_changed( 0 ); 70 | } 71 | } 72 | 73 | 74 | void register_changed( int reg ) 75 | { 76 | // Mirroring 77 | if ( reg == 0 ) 78 | { 79 | int mode = regs [0] & 3; 80 | if ( mode < 2 ) 81 | mirror_single( mode & 1 ); 82 | else if ( mode == 2 ) 83 | mirror_vert(); 84 | else 85 | mirror_horiz(); 86 | } 87 | 88 | // CHR 89 | if ( reg < 3 && cart().chr_size() > 0 ) 90 | { 91 | if ( regs [0] & 0x10 ) 92 | { 93 | set_chr_bank( 0x0000, bank_4k, regs [1] ); 94 | set_chr_bank( 0x1000, bank_4k, regs [2] ); 95 | } 96 | else 97 | { 98 | set_chr_bank( 0, bank_8k, regs [1] >> 1 ); 99 | } 100 | } 101 | 102 | // PRG 103 | int bank = (regs [1] & 0x10) | (regs [3] & 0x0f); 104 | if ( !(regs [0] & 0x08) ) 105 | { 106 | set_prg_bank( 0x8000, bank_32k, bank >> 1 ); 107 | } 108 | else if ( regs [0] & 0x04 ) 109 | { 110 | set_prg_bank( 0x8000, bank_16k, bank ); 111 | set_prg_bank( 0xC000, bank_16k, bank | 0x0f ); 112 | } 113 | else 114 | { 115 | set_prg_bank( 0x8000, bank_16k, bank & ~0x0f ); 116 | set_prg_bank( 0xC000, bank_16k, bank ); 117 | } 118 | } 119 | }; 120 | 121 | 122 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper088.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 3/24/18 20 | * 21 | * Mapper 88 22 | * Mapper 154 23 | * Mapper 206 24 | */ 25 | 26 | #pragma once 27 | 28 | #include "Nes_Mapper.h" 29 | 30 | struct namco_34x3_state_t 31 | { 32 | uint8_t bank [ 8 ]; 33 | uint8_t mirr; 34 | uint8_t mode; 35 | }; 36 | 37 | BOOST_STATIC_ASSERT( sizeof (namco_34x3_state_t) == 10 ); 38 | 39 | template < bool _is154 > 40 | class Mapper_Namco_34x3 : public Nes_Mapper, namco_34x3_state_t { 41 | public: 42 | Mapper_Namco_34x3() 43 | { 44 | namco_34x3_state_t *state = this; 45 | register_state( state, sizeof *state ); 46 | } 47 | 48 | virtual void reset_state() 49 | { } 50 | 51 | virtual void apply_mapping() 52 | { 53 | set_chr_bank( 0x0000, bank_2k, bank [ 0 ] ); 54 | set_chr_bank( 0x0800, bank_2k, bank [ 1 ] ); 55 | for ( int i = 0; i < 4; i++ ) 56 | set_chr_bank( 0x1000 + ( i << 10 ), bank_1k, bank [ i + 2 ] ); 57 | 58 | set_prg_bank( 0x8000, bank_8k, bank [ 6 ] ); 59 | set_prg_bank( 0xA000, bank_8k, bank [ 7 ] ); 60 | set_prg_bank( 0xC000, bank_8k, ~1 ); 61 | set_prg_bank( 0xE000, bank_8k, ~0 ); 62 | 63 | if ( _is154 ) 64 | mirror_single( mirr ); 65 | } 66 | 67 | virtual void write( nes_time_t, nes_addr_t addr, int data ) 68 | { 69 | switch ( addr & 0xE001 ) 70 | { 71 | case 0x8000: 72 | mode = data; 73 | mirr = ( data >> 6 ) & 0x01; 74 | if ( _is154 ) 75 | mirror_single( mirr ); 76 | break; 77 | case 0x8001: 78 | mode &= 0x07; 79 | switch ( mode ) 80 | { 81 | case 0: case 1: 82 | bank [ mode ] = data >> 1; 83 | set_chr_bank( 0x0000 + ( mode << 11 ), bank_2k, bank [ mode ] ); 84 | break; 85 | case 2: case 3: case 4: case 5: 86 | bank [ mode ] = data | 0x40; 87 | set_chr_bank( 0x1000 + ( ( mode - 2 ) << 10 ), bank_1k, bank [ mode ] ); 88 | break; 89 | case 6: case 7: 90 | bank [ mode ] = data; 91 | set_prg_bank( 0x8000 + ( ( mode - 6 ) << 13 ), bank_8k, bank [ mode ] ); 92 | break; 93 | } 94 | break; 95 | case 0xC000: 96 | mirr = ( data >> 6 ) & 0x01; 97 | if ( _is154 ) 98 | mirror_single( mirr ); 99 | } 100 | } 101 | }; 102 | 103 | typedef Mapper_Namco_34x3 Mapper088; 104 | 105 | 106 | // void register_mapper_namco_34xx(); 107 | // void register_mapper_namco_34xx() 108 | // { 109 | // register_mapper< Mapper_Namco_34x3 > ( 88 ); 110 | // register_mapper< Mapper_Namco_34x3 > ( 154 ); 111 | // register_mapper< Mapper_Namco_34xx > ( 206 ); 112 | // } 113 | -------------------------------------------------------------------------------- /nes_emu/abstract_file.h: -------------------------------------------------------------------------------- 1 | 2 | // Abstract file access interfaces 3 | 4 | #ifndef ABSTRACT_FILE_H 5 | #define ABSTRACT_FILE_H 6 | 7 | #undef BLARGG_CONFIG_H 8 | 9 | #include "Data_Reader.h" 10 | 11 | // Supports writing 12 | class Data_Writer { 13 | public: 14 | Data_Writer() { } 15 | virtual ~Data_Writer() { } 16 | 17 | // Write 'n' bytes. NULL on success, otherwise error string. 18 | virtual const char *write( const void*, long n ) = 0; 19 | 20 | private: 21 | // noncopyable 22 | Data_Writer( const Data_Writer& ); 23 | Data_Writer& operator = ( const Data_Writer& ); 24 | }; 25 | 26 | // Write data to memory 27 | class Mem_Writer : public Data_Writer { 28 | char* data_; 29 | long size_; 30 | long allocated; 31 | enum { expanding, fixed, ignore_excess } mode; 32 | public: 33 | // Keep all written data in expanding block of memory 34 | Mem_Writer(); 35 | 36 | // Write to fixed-size block of memory. If ignore_excess is false, returns 37 | // error if more than 'size' data is written, otherwise ignores any excess. 38 | Mem_Writer( void*, long size, int ignore_excess = 0 ); 39 | 40 | const char *write( const void*, long ); 41 | 42 | // Pointer to beginning of written data 43 | char* data() { return data_; } 44 | 45 | // Number of bytes written 46 | long size() const { return size_; } 47 | 48 | ~Mem_Writer(); 49 | }; 50 | 51 | // Auto_File to use in place of Data_Reader&/Data_Writer&, allowing a normal 52 | // file path to be used in addition to a Data_Reader/Data_Writer. 53 | 54 | class Auto_File_Reader { 55 | public: 56 | Auto_File_Reader() : data( 0 ), path( 0 ) { } 57 | Auto_File_Reader( Data_Reader& r ) : data( &r ), path( 0 ) { } 58 | Auto_File_Reader( Auto_File_Reader const& ); 59 | Auto_File_Reader& operator = ( Auto_File_Reader const& ); 60 | ~Auto_File_Reader(); 61 | const char* open(); 62 | 63 | int operator ! () const { return !data; } 64 | Data_Reader* operator -> () const { return data; } 65 | Data_Reader& operator * () const { return *data; } 66 | private: 67 | /* mutable */ Data_Reader* data; 68 | const char* path; 69 | }; 70 | 71 | class Auto_File_Writer { 72 | public: 73 | Auto_File_Writer() : data( 0 ), path( 0 ) { } 74 | Auto_File_Writer( Data_Writer& r ) : data( &r ), path( 0 ) { } 75 | Auto_File_Writer( Auto_File_Writer const& ); 76 | Auto_File_Writer& operator = ( Auto_File_Writer const& ); 77 | ~Auto_File_Writer(); 78 | const char* open(); 79 | const char* open_comp( int level = -1 ); // compress output if possible 80 | 81 | int operator ! () const { return !data; } 82 | Data_Writer* operator -> () const { return data; } 83 | Data_Writer& operator * () const { return *data; } 84 | private: 85 | /* mutable */ Data_Writer* data; 86 | const char* path; 87 | }; 88 | 89 | inline Auto_File_Reader& Auto_File_Reader::operator = ( Auto_File_Reader const& r ) 90 | { 91 | data = r.data; 92 | path = r.path; 93 | ((Auto_File_Reader*) &r)->data = 0; 94 | return *this; 95 | } 96 | inline Auto_File_Reader::Auto_File_Reader( Auto_File_Reader const& r ) { *this = r; } 97 | 98 | inline Auto_File_Writer& Auto_File_Writer::operator = ( Auto_File_Writer const& r ) 99 | { 100 | data = r.data; 101 | path = r.path; 102 | ((Auto_File_Writer*) &r)->data = 0; 103 | return *this; 104 | } 105 | inline Auto_File_Writer::Auto_File_Writer( Auto_File_Writer const& r ) { *this = r; } 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper032.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 20 | * Mapper 32 - Irem's G-101 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include "Nes_Mapper.h" 27 | 28 | struct mapper32_state_t 29 | { 30 | uint8_t chr_bank [ 8 ]; 31 | uint8_t prg_bank [ 2 ]; 32 | uint8_t prg_mode; 33 | uint8_t mirr; 34 | }; 35 | 36 | BOOST_STATIC_ASSERT( sizeof ( mapper32_state_t ) == 12 ); 37 | 38 | // Irem_G101 39 | 40 | class Mapper032 : public Nes_Mapper, mapper32_state_t { 41 | public: 42 | Mapper032() 43 | { 44 | mapper32_state_t * state = this; 45 | register_state( state, sizeof * state ); 46 | } 47 | 48 | virtual void reset_state() 49 | { 50 | prg_bank [ 0 ] = ~1; 51 | prg_bank [ 1 ] = ~0; 52 | enable_sram(); 53 | } 54 | 55 | virtual void apply_mapping() 56 | { 57 | if ( prg_mode == 0 ) 58 | { 59 | set_prg_bank ( 0x8000, bank_8k, prg_bank [ 0 ] ); 60 | set_prg_bank ( 0xA000, bank_8k, prg_bank [ 1 ] ); 61 | set_prg_bank ( 0xC000, bank_8k, ~1 ); 62 | set_prg_bank ( 0xE000, bank_8k, ~0 ); 63 | } 64 | else 65 | { 66 | set_prg_bank ( 0xC000, bank_8k, prg_bank [ 0 ] ); 67 | set_prg_bank ( 0xA000, bank_8k, prg_bank [ 1 ] ); 68 | set_prg_bank ( 0x8000, bank_8k, ~1 ); 69 | set_prg_bank ( 0xE000, bank_8k, ~0 ); 70 | } 71 | 72 | for ( unsigned long int i = 0; i < sizeof chr_bank; i++) 73 | set_chr_bank( ( i << 10 ), bank_1k, chr_bank [ i ] ); 74 | 75 | switch ( mirr ) 76 | { 77 | case 0: mirror_vert(); break; 78 | case 1: mirror_horiz(); break; 79 | } 80 | } 81 | 82 | virtual void write( nes_time_t, nes_addr_t addr, int data ) 83 | { 84 | switch ( addr & 0xF000 ) 85 | { 86 | case 0x8000: 87 | prg_bank [ 0 ] = data; 88 | switch ( prg_mode ) 89 | { 90 | case 0: set_prg_bank ( 0x8000, bank_8k, data ); break; 91 | case 1: set_prg_bank ( 0xC000, bank_8k, data ); break; 92 | } 93 | break; 94 | case 0x9000: 95 | mirr = data & 1; 96 | prg_mode = ( data >> 1 ) & 1; 97 | switch ( data & 1 ) 98 | { 99 | case 0: mirror_vert(); break; 100 | case 1: mirror_horiz(); break; 101 | } 102 | break; 103 | case 0xA000: 104 | prg_bank [ 1 ] = data; 105 | set_prg_bank ( 0xA000, bank_8k, data ); 106 | break; 107 | } 108 | 109 | switch ( addr & 0xF007 ) 110 | { 111 | case 0xB000: case 0xB001: case 0xB002: case 0xB003: 112 | case 0xB004: case 0xB005: case 0xB006: case 0xB007: 113 | chr_bank [ addr & 0x07 ] = data; 114 | set_chr_bank( ( addr & 0x07 ) << 10, bank_1k, data ); 115 | break; 116 | } 117 | } 118 | }; 119 | 120 | -------------------------------------------------------------------------------- /nes_emu/Nes_Fme7_Apu.h: -------------------------------------------------------------------------------- 1 | 2 | // Sunsoft FME-7 sound emulator 3 | 4 | // Nes_Emu 0.7.0 5 | 6 | #ifndef NES_FME7_APU_H 7 | #define NES_FME7_APU_H 8 | 9 | #include 10 | #include "blargg_common.h" 11 | #include "Blip_Buffer.h" 12 | 13 | struct fme7_apu_state_t 14 | { 15 | enum { reg_count = 14 }; 16 | uint8_t regs [reg_count]; 17 | uint8_t phases [3]; // 0 or 1 18 | uint8_t latch; 19 | uint16_t delays [3]; // a, b, c 20 | }; 21 | BOOST_STATIC_ASSERT( sizeof (fme7_apu_state_t) == 24 ); 22 | 23 | class Nes_Fme7_Apu : private fme7_apu_state_t { 24 | public: 25 | Nes_Fme7_Apu(); 26 | 27 | // See Nes_Apu.h for reference 28 | void reset(); 29 | void volume( double ); 30 | void treble_eq( blip_eq_t const& ); 31 | void output( Blip_Buffer* ); 32 | enum { osc_count = 3 }; 33 | void osc_output( int index, Blip_Buffer* ); 34 | void end_frame( blip_time_t ); 35 | void save_state( fme7_apu_state_t* ) const; 36 | void load_state( fme7_apu_state_t const& ); 37 | 38 | // Mask and addresses of registers 39 | enum { addr_mask = 0xe000 }; 40 | enum { data_addr = 0xe000 }; 41 | enum { latch_addr = 0xc000 }; 42 | 43 | // (addr & addr_mask) == latch_addr 44 | void write_latch( int ); 45 | 46 | // (addr & addr_mask) == data_addr 47 | void write_data( blip_time_t, int data ); 48 | 49 | // End of public interface 50 | private: 51 | // noncopyable 52 | Nes_Fme7_Apu( const Nes_Fme7_Apu& ); 53 | Nes_Fme7_Apu& operator = ( const Nes_Fme7_Apu& ); 54 | 55 | static unsigned char amp_table [16]; 56 | 57 | struct { 58 | Blip_Buffer* output; 59 | int last_amp; 60 | } oscs [osc_count]; 61 | blip_time_t last_time; 62 | 63 | enum { amp_range = 192 }; // can be any value; this gives best error/quality tradeoff 64 | Blip_Synth synth; 65 | 66 | void run_until( blip_time_t ); 67 | }; 68 | 69 | inline void Nes_Fme7_Apu::volume( double v ) 70 | { 71 | synth.volume( 0.38 / amp_range * v ); // to do: fine-tune 72 | } 73 | 74 | inline void Nes_Fme7_Apu::treble_eq( blip_eq_t const& eq ) 75 | { 76 | synth.treble_eq( eq ); 77 | } 78 | 79 | inline void Nes_Fme7_Apu::osc_output( int i, Blip_Buffer* buf ) 80 | { 81 | oscs [i].output = buf; 82 | } 83 | 84 | inline void Nes_Fme7_Apu::output( Blip_Buffer* buf ) 85 | { 86 | for ( int i = 0; i < osc_count; i++ ) 87 | osc_output( i, buf ); 88 | } 89 | 90 | inline Nes_Fme7_Apu::Nes_Fme7_Apu() 91 | { 92 | output( NULL ); 93 | volume( 1.0 ); 94 | reset(); 95 | } 96 | 97 | inline void Nes_Fme7_Apu::write_latch( int data ) { latch = data; } 98 | 99 | inline void Nes_Fme7_Apu::write_data( blip_time_t time, int data ) 100 | { 101 | if ( (unsigned) latch >= reg_count ) 102 | { 103 | #ifdef dprintf 104 | dprintf( "FME7 write to %02X (past end of sound registers)\n", (int) latch ); 105 | #endif 106 | return; 107 | } 108 | 109 | run_until( time ); 110 | regs [latch] = data; 111 | } 112 | 113 | inline void Nes_Fme7_Apu::end_frame( blip_time_t time ) 114 | { 115 | if ( time > last_time ) 116 | run_until( time ); 117 | 118 | last_time -= time; 119 | } 120 | 121 | inline void Nes_Fme7_Apu::save_state( fme7_apu_state_t* out ) const 122 | { 123 | *out = *this; 124 | } 125 | 126 | inline void Nes_Fme7_Apu::load_state( fme7_apu_state_t const& in ) 127 | { 128 | reset(); 129 | fme7_apu_state_t* state = this; 130 | *state = in; 131 | 132 | //Run sound channels for 0 cycles for clean audio after loading state 133 | run_until(last_time); 134 | } 135 | 136 | #endif 137 | -------------------------------------------------------------------------------- /nes_emu/Nes_Cart.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Nes_Emu 0.7.0. http://www.slack.net/~ant/ 3 | 4 | #include "Nes_Cart.h" 5 | 6 | #include 7 | #include 8 | 9 | /* Copyright (C) 2004-2006 Shay Green. This module is free software; you 10 | can redistribute it and/or modify it under the terms of the GNU Lesser 11 | General Public License as published by the Free Software Foundation; either 12 | version 2.1 of the License, or (at your option) any later version. This 13 | module is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 16 | more details. You should have received a copy of the GNU Lesser General 17 | Public License along with this module; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 19 | 20 | #include "blargg_source.h" 21 | 22 | char const Nes_Cart::not_ines_file [] = "Not an iNES file"; 23 | 24 | Nes_Cart::Nes_Cart() 25 | { 26 | prg_ = NULL; 27 | chr_ = NULL; 28 | clear(); 29 | } 30 | 31 | Nes_Cart::~Nes_Cart() 32 | { 33 | clear(); 34 | } 35 | 36 | void Nes_Cart::clear() 37 | { 38 | if ( prg_ ) 39 | free( prg_ ); 40 | prg_ = NULL; 41 | 42 | if ( chr_ ) 43 | free( chr_ ); 44 | chr_ = NULL; 45 | 46 | prg_size_ = 0; 47 | chr_size_ = 0; 48 | mapper = 0; 49 | } 50 | 51 | long Nes_Cart::round_to_bank_size( long n ) 52 | { 53 | n += bank_size - 1; 54 | return n - n % bank_size; 55 | } 56 | 57 | const char * Nes_Cart::resize_prg( long size ) 58 | { 59 | if ( size != prg_size_ ) 60 | { 61 | // padding allows CPU to always read operands of instruction, which 62 | // might go past end of data 63 | void* p = realloc( prg_, round_to_bank_size( size ) + 2 ); 64 | CHECK_ALLOC( p || !size ); 65 | prg_ = (uint8_t*) p; 66 | prg_size_ = size; 67 | } 68 | return 0; 69 | } 70 | 71 | const char * Nes_Cart::resize_chr( long size ) 72 | { 73 | if ( size != chr_size_ ) 74 | { 75 | void* p = realloc( chr_, round_to_bank_size( size ) ); 76 | CHECK_ALLOC( p || !size ); 77 | chr_ = (uint8_t*) p; 78 | chr_size_ = size; 79 | } 80 | return 0; 81 | } 82 | 83 | // iNES reading 84 | 85 | struct ines_header_t { 86 | uint8_t signature [4]; 87 | uint8_t prg_count; // number of 16K PRG banks 88 | uint8_t chr_count; // number of 8K CHR banks 89 | uint8_t flags; // MMMM FTBV Mapper low, Four-screen, Trainer, Battery, V mirror 90 | uint8_t flags2; // MMMM --XX Mapper high 4 bits 91 | uint8_t zero [8]; // if zero [7] is non-zero, treat flags2 as zero 92 | }; 93 | BOOST_STATIC_ASSERT( sizeof (ines_header_t) == 16 ); 94 | 95 | const char * Nes_Cart::load_ines( Auto_File_Reader in ) 96 | { 97 | RETURN_ERR( in.open() ); 98 | 99 | ines_header_t h; 100 | RETURN_ERR( in->read( &h, sizeof h ) ); 101 | 102 | if ( 0 != memcmp( h.signature, "NES\x1A", 4 ) ) 103 | return not_ines_file; 104 | 105 | if ( h.zero [7] ) // handle header defaced by a fucking idiot's handle 106 | h.flags2 = 0; 107 | 108 | set_mapper( h.flags, h.flags2 ); 109 | 110 | if ( h.flags & 0x04 ) // skip trainer 111 | RETURN_ERR( in->skip( 512 ) ); 112 | 113 | RETURN_ERR( resize_prg( h.prg_count * 16 * 1024L ) ); 114 | RETURN_ERR( resize_chr( h.chr_count * 8 * 1024L ) ); 115 | 116 | RETURN_ERR( in->read( prg(), prg_size() ) ); 117 | RETURN_ERR( in->read( chr(), chr_size() ) ); 118 | 119 | return 0; 120 | } 121 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper073.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright notice for this file: 2 | * Copyright (C) 2018 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | * This mapper was added by retrowertz for Libretro port of QuickNES. 19 | * 3/24/18 20 | * 21 | * VRC-3 Konami, Salamander 22 | */ 23 | 24 | #pragma once 25 | 26 | #include "Nes_Mapper.h" 27 | 28 | struct vrc3_state_t 29 | { 30 | bool irq_enable; 31 | bool irq_awk; 32 | uint16_t irq_latch; 33 | uint16_t irq_counter; 34 | 35 | uint8_t irq_pending; 36 | uint16_t next_time; 37 | }; 38 | 39 | // VRC3 40 | 41 | class Mapper073 : public Nes_Mapper, vrc3_state_t { 42 | public: 43 | Mapper073() 44 | { 45 | vrc3_state_t * state = this; 46 | register_state( state, sizeof * state ); 47 | } 48 | 49 | void reset_state() 50 | { 51 | } 52 | 53 | void apply_mapping() 54 | { 55 | enable_sram(); 56 | mirror_vert(); 57 | } 58 | 59 | virtual void run_until( nes_time_t end_time ) 60 | { 61 | if ( irq_enable ) 62 | { 63 | long counter = irq_counter + ( end_time - next_time ); 64 | 65 | if ( counter > 0xFFFF ) 66 | { 67 | irq_pending = true; 68 | irq_enable = irq_awk; 69 | irq_counter = irq_latch; 70 | } 71 | else 72 | irq_counter = counter; 73 | } 74 | 75 | next_time = end_time; 76 | } 77 | 78 | virtual void end_frame( nes_time_t end_time ) 79 | { 80 | if ( end_time > next_time ) 81 | run_until( end_time ); 82 | 83 | next_time -= end_time; 84 | } 85 | 86 | virtual nes_time_t next_irq( nes_time_t present ) 87 | { 88 | if ( irq_pending ) 89 | return present; 90 | 91 | if ( !irq_enable ) 92 | return no_irq; 93 | 94 | return 0x10000 - irq_counter + next_time; 95 | } 96 | 97 | void write_irq_counter( int shift, int data ) 98 | { 99 | irq_latch &= ~( 0xF << shift ); 100 | irq_latch |= data << shift; 101 | } 102 | 103 | void write( nes_time_t time, nes_addr_t addr, int data ) 104 | { 105 | data &= 0xF; 106 | 107 | switch ( addr >> 12 ) 108 | { 109 | case 0xF: set_prg_bank( 0x8000, bank_16k, data ); break; 110 | case 0x8: write_irq_counter( 0, data ); break; 111 | case 0x9: write_irq_counter( 4, data ); break; 112 | case 0xA: write_irq_counter( 8, data ); break; 113 | case 0xB: write_irq_counter( 12, data ); break; 114 | case 0xC: 115 | irq_pending = false; 116 | irq_awk = data & 1; 117 | irq_enable = data & 2; 118 | 119 | if ( irq_enable ) 120 | irq_counter = irq_latch; 121 | 122 | break; 123 | case 0xD: 124 | irq_pending = false; 125 | irq_enable = irq_awk; 126 | break; 127 | } 128 | 129 | irq_changed(); 130 | } 131 | }; 132 | 133 | // void register_vrc3_mapper(); 134 | // void register_vrc3_mapper() 135 | // { 136 | // register_mapper< Mapper073> ( 73 ); 137 | // } 138 | -------------------------------------------------------------------------------- /nes_emu/Nes_Fme7_Apu.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Nes_Emu 0.7.0. http://www.slack.net/~ant/ 3 | 4 | #include "Nes_Fme7_Apu.h" 5 | 6 | #include 7 | 8 | /* Copyright (C) 2003-2006 Shay Green. This module is free software; you 9 | can redistribute it and/or modify it under the terms of the GNU Lesser 10 | General Public License as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. This 12 | module is distributed in the hope that it will be useful, but WITHOUT ANY 13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 15 | more details. You should have received a copy of the GNU Lesser General 16 | Public License along with this module; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 18 | 19 | #include "blargg_source.h" 20 | 21 | void Nes_Fme7_Apu::reset() 22 | { 23 | last_time = 0; 24 | 25 | for ( int i = 0; i < osc_count; i++ ) 26 | oscs [i].last_amp = 0; 27 | 28 | fme7_apu_state_t* state = this; 29 | memset( state, 0, sizeof *state ); 30 | } 31 | 32 | unsigned char Nes_Fme7_Apu::amp_table [16] = 33 | { 34 | #define ENTRY( n ) (unsigned char) (n * amp_range + 0.5) 35 | ENTRY(0.0000), ENTRY(0.0078), ENTRY(0.0110), ENTRY(0.0156), 36 | ENTRY(0.0221), ENTRY(0.0312), ENTRY(0.0441), ENTRY(0.0624), 37 | ENTRY(0.0883), ENTRY(0.1249), ENTRY(0.1766), ENTRY(0.2498), 38 | ENTRY(0.3534), ENTRY(0.4998), ENTRY(0.7070), ENTRY(1.0000) 39 | #undef ENTRY 40 | }; 41 | 42 | void Nes_Fme7_Apu::run_until( blip_time_t end_time ) 43 | { 44 | for ( int index = 0; index < osc_count; index++ ) 45 | { 46 | int mode = regs [7] >> index; 47 | int vol_mode = regs [010 + index]; 48 | int volume = amp_table [vol_mode & 0x0f]; 49 | 50 | if ( !oscs [index].output ) 51 | continue; 52 | 53 | if ( (mode & 001) | (vol_mode & 0x10) ) 54 | volume = 0; // noise and envelope aren't supported 55 | 56 | // period 57 | int const period_factor = 16; 58 | unsigned period = (regs [index * 2 + 1] & 0x0f) * 0x100 * period_factor + 59 | regs [index * 2] * period_factor; 60 | if ( period < 50 ) // around 22 kHz 61 | { 62 | volume = 0; 63 | if ( !period ) // on my AY-3-8910A, period doesn't have extra one added 64 | period = period_factor; 65 | } 66 | 67 | // current amplitude 68 | int amp = volume; 69 | if ( !phases [index] ) 70 | amp = 0; 71 | int delta = amp - oscs [index].last_amp; 72 | if ( delta ) 73 | { 74 | oscs [index].last_amp = amp; 75 | synth.offset( last_time, delta, oscs [index].output ); 76 | } 77 | 78 | blip_time_t time = last_time + delays [index]; 79 | if ( time < end_time ) 80 | { 81 | Blip_Buffer* const osc_output = oscs [index].output; 82 | int delta = amp * 2 - volume; 83 | 84 | if ( volume ) 85 | { 86 | do 87 | { 88 | delta = -delta; 89 | synth.offset_inline( time, delta, osc_output ); 90 | time += period; 91 | } 92 | while ( time < end_time ); 93 | 94 | oscs [index].last_amp = (delta + volume) >> 1; 95 | phases [index] = (delta > 0); 96 | } 97 | else 98 | { 99 | // maintain phase when silent 100 | int count = (end_time - time + period - 1) / period; 101 | phases [index] ^= count & 1; 102 | time += (long) count * period; 103 | } 104 | } 105 | 106 | delays [index] = time - end_time; 107 | } 108 | 109 | last_time = end_time; 110 | } 111 | -------------------------------------------------------------------------------- /nes_emu/Nes_File.h: -------------------------------------------------------------------------------- 1 | 2 | // NES block-oriented file access 3 | 4 | // Nes_Emu 0.7.0 5 | 6 | #ifndef NES_FILE_H 7 | #define NES_FILE_H 8 | 9 | #include "blargg_common.h" 10 | #include "abstract_file.h" 11 | #include "nes_data.h" 12 | 13 | // Writes a structured file 14 | class Nes_File_Writer : public Data_Writer { 15 | public: 16 | Nes_File_Writer(); 17 | ~Nes_File_Writer(); 18 | 19 | // Begin writing file with specified signature tag 20 | const char * begin( Auto_File_Writer, nes_tag_t ); 21 | 22 | // Begin tagged group 23 | const char * begin_group( nes_tag_t ); 24 | 25 | // Write tagged block 26 | const char * write_block( nes_tag_t, void const*, long size ); 27 | 28 | // Write tagged block header. 'Size' bytes must be written before next block. 29 | const char * write_block_header( nes_tag_t, long size ); 30 | 31 | // Write data to current block 32 | const char *write( void const*, long ); 33 | 34 | // End tagged group 35 | const char * end_group(); 36 | 37 | // End file 38 | const char * end(); 39 | 40 | private: 41 | Auto_File_Writer out; 42 | long write_remain; 43 | int depth_; 44 | const char * write_header( nes_tag_t tag, long size ); 45 | }; 46 | 47 | // Reads a structured file 48 | class Nes_File_Reader : public Data_Reader { 49 | public: 50 | Nes_File_Reader(); 51 | ~Nes_File_Reader(); 52 | 53 | // If true, verify checksums of any blocks that have them 54 | void enable_checksums( bool = true ); 55 | 56 | // Begin reading file. Until next_block() is called, block_tag() yields tag for file. 57 | const char * begin( Auto_File_Reader ); 58 | 59 | // Read header of next block in current group 60 | const char * next_block(); 61 | 62 | // Type of current block 63 | enum block_type_t { 64 | data_block, 65 | group_begin, 66 | group_end, 67 | invalid 68 | }; 69 | block_type_t block_type() const { return block_type_; } 70 | 71 | // Tag of current block 72 | nes_tag_t block_tag() const { return h.tag; } 73 | 74 | // Read at most s bytes from block and skip any remaining bytes 75 | const char * read_block_data( void*, long s ); 76 | 77 | // Read at most 's' bytes from current block and return number of bytes actually read 78 | virtual const char * read_v( void*, int n ); 79 | 80 | // Skip 's' bytes in current block 81 | virtual const char * skip_v( int s ); 82 | 83 | // Read first sub-block of current group block 84 | const char * enter_group(); 85 | 86 | // Skip past current group 87 | const char * exit_group(); 88 | 89 | // Current depth, where 0 is top-level in file and higher is deeper 90 | int depth() const { return depth_; } 91 | 92 | // True if all data has been read 93 | bool done() const { return depth() == 0 && block_type() == group_end; } 94 | private: 95 | Auto_File_Reader in; 96 | nes_block_t h; 97 | block_type_t block_type_; 98 | int depth_; 99 | const char * read_header(); 100 | }; 101 | 102 | template 103 | inline const char * read_nes_state( Nes_File_Reader& in, T* out ) 104 | { 105 | const char * err = in.read_block_data( out, sizeof *out ); 106 | out->swap(); 107 | return err; 108 | } 109 | 110 | template 111 | inline const char * write_nes_state( Nes_File_Writer& out, T& in ) 112 | { 113 | in.swap(); 114 | const char * err = out.write_block( in.tag, &in, sizeof in ); 115 | in.swap(); 116 | return err; 117 | } 118 | 119 | template 120 | inline const char * write_nes_state( Nes_File_Writer& out, const T& in ) 121 | { 122 | T copy = in; 123 | copy.swap(); 124 | return out.write_block( copy.tag, ©, sizeof copy ); 125 | } 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /nes_emu/Nes_Oscs.h: -------------------------------------------------------------------------------- 1 | 2 | // Private oscillators used by Nes_Apu 3 | 4 | // Nes_Snd_Emu 0.1.7 5 | 6 | #ifndef NES_OSCS_H 7 | #define NES_OSCS_H 8 | 9 | #include "blargg_common.h" 10 | #include "Blip_Buffer.h" 11 | 12 | class Nes_Apu; 13 | 14 | struct Nes_Osc 15 | { 16 | unsigned char regs [4]; 17 | bool reg_written [4]; 18 | Blip_Buffer* output; 19 | int length_counter;// length counter (0 if unused by oscillator) 20 | int delay; // delay until next (potential) transition 21 | int last_amp; // last amplitude oscillator was outputting 22 | 23 | void clock_length( int halt_mask ); 24 | int period() const { 25 | return (regs [3] & 7) * 0x100 + (regs [2] & 0xff); 26 | } 27 | void reset() { 28 | delay = 0; 29 | last_amp = 0; 30 | } 31 | int update_amp( int amp ) { 32 | int delta = amp - last_amp; 33 | last_amp = amp; 34 | return delta; 35 | } 36 | }; 37 | 38 | struct Nes_Envelope : Nes_Osc 39 | { 40 | int envelope; 41 | int env_delay; 42 | 43 | void clock_envelope(); 44 | int volume() const; 45 | void reset() { 46 | envelope = 0; 47 | env_delay = 0; 48 | Nes_Osc::reset(); 49 | } 50 | }; 51 | 52 | // Nes_Square 53 | struct Nes_Square : Nes_Envelope 54 | { 55 | enum { negate_flag = 0x08 }; 56 | enum { shift_mask = 0x07 }; 57 | enum { phase_range = 8 }; 58 | int phase; 59 | int sweep_delay; 60 | 61 | typedef Blip_Synth Synth; 62 | Synth const& synth; // shared between squares 63 | 64 | Nes_Square( Synth const* s ) : synth( *s ) { } 65 | 66 | void clock_sweep( int adjust ); 67 | void run( nes_time_t, nes_time_t ); 68 | void reset() { 69 | sweep_delay = 0; 70 | Nes_Envelope::reset(); 71 | } 72 | nes_time_t maintain_phase( nes_time_t time, nes_time_t end_time, 73 | nes_time_t timer_period ); 74 | }; 75 | 76 | // Nes_Triangle 77 | struct Nes_Triangle : Nes_Osc 78 | { 79 | enum { phase_range = 16 }; 80 | int phase; 81 | int linear_counter; 82 | Blip_Synth synth; 83 | 84 | int calc_amp() const; 85 | void run( nes_time_t, nes_time_t ); 86 | void clock_linear_counter(); 87 | void reset() { 88 | linear_counter = 0; 89 | phase = 1; 90 | Nes_Osc::reset(); 91 | } 92 | nes_time_t maintain_phase( nes_time_t time, nes_time_t end_time, 93 | nes_time_t timer_period ); 94 | }; 95 | 96 | // Nes_Noise 97 | struct Nes_Noise : Nes_Envelope 98 | { 99 | int noise; 100 | Blip_Synth synth; 101 | 102 | void run( nes_time_t, nes_time_t ); 103 | void reset() { 104 | noise = 1 << 14; 105 | Nes_Envelope::reset(); 106 | } 107 | }; 108 | 109 | // Nes_Dmc 110 | struct Nes_Dmc : Nes_Osc 111 | { 112 | int address; // address of next byte to read 113 | int period; 114 | //int length_counter; // bytes remaining to play (already defined in Nes_Osc) 115 | int buf; 116 | int bits_remain; 117 | int bits; 118 | bool buf_full; 119 | bool silence; 120 | 121 | enum { loop_flag = 0x40 }; 122 | 123 | int dac; 124 | 125 | nes_time_t next_irq; 126 | bool irq_enabled; 127 | bool irq_flag; 128 | bool pal_mode; 129 | bool nonlinear; 130 | 131 | int (*prg_reader)( void*, nes_addr_t ); // needs to be initialized to prg read function 132 | void* prg_reader_data; 133 | 134 | Nes_Apu* apu; 135 | 136 | Blip_Synth synth; 137 | 138 | void start(); 139 | void write_register( int, int ); 140 | void run( nes_time_t, nes_time_t ); 141 | void recalc_irq(); 142 | void fill_buffer(); 143 | void reload_sample(); 144 | void reset(); 145 | int count_reads( nes_time_t, nes_time_t* ) const; 146 | nes_time_t next_read_time() const; 147 | }; 148 | 149 | #endif 150 | -------------------------------------------------------------------------------- /nes_emu/Nes_Core.h: -------------------------------------------------------------------------------- 1 | 2 | // Internal NES emulator 3 | 4 | // Nes_Emu 0.7.0 5 | 6 | #ifndef NES_CORE_H 7 | #define NES_CORE_H 8 | 9 | #include "blargg_common.h" 10 | #include "Nes_Apu.h" 11 | #include "Nes_Cpu.h" 12 | #include "Nes_Ppu.h" 13 | class Nes_Mapper; 14 | class Nes_Cart; 15 | class Nes_State; 16 | 17 | class Nes_Core : private Nes_Cpu { 18 | typedef Nes_Cpu cpu; 19 | public: 20 | Nes_Core(); 21 | ~Nes_Core(); 22 | 23 | const char * init(); 24 | const char * open( Nes_Cart const* ); 25 | void reset( bool full_reset = true, bool erase_battery_ram = false ); 26 | blip_time_t emulate_frame(); 27 | void close(); 28 | 29 | void save_state( Nes_State* ) const; 30 | void save_state( Nes_State_* ) const; 31 | void load_state( Nes_State_ const& ); 32 | 33 | void irq_changed(); 34 | void event_changed(); 35 | 36 | public: private: friend class Nes_Emu; 37 | 38 | struct impl_t 39 | { 40 | enum { sram_size = 0x2000 }; 41 | uint8_t sram [sram_size]; 42 | Nes_Apu apu; 43 | 44 | // extra byte allows CPU to always read operand of instruction, which 45 | // might go past end of data 46 | uint8_t unmapped_page [::Nes_Cpu::page_size + 1]; 47 | }; 48 | impl_t* impl; // keep large arrays separate 49 | unsigned long error_count; 50 | bool sram_present; 51 | 52 | public: 53 | unsigned long current_joypad [2]; 54 | int joypad_read_count; 55 | Nes_Cart const* cart; 56 | Nes_Mapper* mapper; 57 | nes_state_t nes; 58 | Nes_Ppu ppu; 59 | 60 | private: 61 | // noncopyable 62 | Nes_Core( const Nes_Core& ); 63 | Nes_Core& operator = ( const Nes_Core& ); 64 | 65 | // Timing 66 | nes_time_t ppu_2002_time; 67 | void disable_rendering() { clock_ = 0; } 68 | nes_time_t earliest_irq( nes_time_t present ); 69 | nes_time_t ppu_frame_length( nes_time_t present ); 70 | nes_time_t earliest_event( nes_time_t present ); 71 | 72 | // APU and Joypad 73 | joypad_state_t joypad; 74 | int read_io( nes_addr_t ); 75 | void write_io( nes_addr_t, int data ); 76 | static int read_dmc( void* emu, nes_addr_t ); 77 | static void apu_irq_changed( void* emu ); 78 | 79 | // CPU 80 | unsigned sram_readable; 81 | unsigned sram_writable; 82 | unsigned lrom_readable; 83 | nes_time_t clock_; 84 | nes_time_t cpu_time_offset; 85 | nes_time_t emulate_frame_(); 86 | nes_addr_t read_vector( nes_addr_t ); 87 | void vector_interrupt( nes_addr_t ); 88 | static void log_unmapped( nes_addr_t addr, int data = -1 ); 89 | void cpu_set_irq_time( nes_time_t t ) { cpu::set_irq_time_( t - 1 - cpu_time_offset ); } 90 | void cpu_set_end_time( nes_time_t t ) { cpu::set_end_time_( t - 1 - cpu_time_offset ); } 91 | nes_time_t cpu_time() const { return clock_ + 1; } 92 | void cpu_adjust_time( int offset ); 93 | 94 | public: private: friend class Nes_Ppu; 95 | void set_ppu_2002_time( nes_time_t t ) { ppu_2002_time = t - 1 - cpu_time_offset; } 96 | 97 | public: private: friend class Nes_Mapper; 98 | void enable_prg_6000(); 99 | void enable_sram( bool enabled, bool read_only = false ); 100 | nes_time_t clock() const { return clock_; } 101 | void add_mapper_intercept( nes_addr_t start, unsigned size, bool read, bool write ); 102 | 103 | public: private: friend class Nes_Cpu; 104 | int cpu_read_ppu( nes_addr_t, nes_time_t ); 105 | int cpu_read( nes_addr_t, nes_time_t ); 106 | void cpu_write( nes_addr_t, int data, nes_time_t ); 107 | void cpu_write_2007( int data ); 108 | 109 | private: 110 | unsigned char data_reader_mapped [page_count + 1]; // extra entry for overflow 111 | unsigned char data_writer_mapped [page_count + 1]; 112 | }; 113 | 114 | int mem_differs( void const* p, int cmp, unsigned long s ); 115 | 116 | #endif 117 | -------------------------------------------------------------------------------- /nes_emu/nes_cpu_io.h: -------------------------------------------------------------------------------- 1 | 2 | #include "Nes_Core.h" 3 | #include "Nes_Mapper.h" 4 | 5 | #include "blargg_source.h" 6 | 7 | int Nes_Core::cpu_read( nes_addr_t addr, nes_time_t time ) 8 | { 9 | //LOG_FREQ( "cpu_read", 16, addr >> 12 ); 10 | 11 | { 12 | int result = cpu::low_mem [addr & 0x7FF]; 13 | if ( !(addr & 0xE000) ) 14 | return result; 15 | } 16 | 17 | { 18 | int result = *cpu::get_code( addr ); 19 | if ( addr > 0x7FFF ) 20 | return result; 21 | } 22 | 23 | time += cpu_time_offset; 24 | if ( addr < 0x4000 ) 25 | return ppu.read( addr, time ); 26 | 27 | clock_ = time; 28 | if ( data_reader_mapped [addr >> page_bits] ) 29 | { 30 | int result = mapper->read( time, addr ); 31 | if ( result >= 0 ) 32 | return result; 33 | } 34 | 35 | if ( addr < 0x6000 ) 36 | return read_io( addr ); 37 | 38 | if ( addr < sram_readable ) 39 | return impl->sram [addr & (impl_t::sram_size - 1)]; 40 | 41 | if ( addr < lrom_readable ) 42 | return *cpu::get_code( addr ); 43 | 44 | #ifndef NDEBUG 45 | log_unmapped( addr ); 46 | #endif 47 | 48 | return addr >> 8; // simulate open bus 49 | } 50 | 51 | inline int Nes_Core::cpu_read_ppu( nes_addr_t addr, nes_time_t time ) 52 | { 53 | //LOG_FREQ( "cpu_read_ppu", 16, addr >> 12 ); 54 | 55 | // Read of status register (0x2002) is heavily optimized since many games 56 | // poll it hundreds of times per frame. 57 | nes_time_t next = ppu_2002_time; 58 | int result = ppu.r2002; 59 | if ( addr == 0x2002 ) 60 | { 61 | ppu.second_write = false; 62 | if ( time >= next ) 63 | result = ppu.read_2002( time + cpu_time_offset ); 64 | } 65 | else 66 | { 67 | result = cpu::low_mem [addr & 0x7FF]; 68 | if ( addr >= 0x2000 ) 69 | result = cpu_read( addr, time ); 70 | } 71 | 72 | return result; 73 | } 74 | 75 | void Nes_Core::cpu_write_2007( int data ) 76 | { 77 | // ppu.write_2007() is inlined 78 | if ( ppu.write_2007( data ) & Nes_Ppu::vaddr_clock_mask ) 79 | mapper->a12_clocked(); 80 | } 81 | 82 | void Nes_Core::cpu_write( nes_addr_t addr, int data, nes_time_t time ) 83 | { 84 | //LOG_FREQ( "cpu_write", 16, addr >> 12 ); 85 | 86 | if ( !(addr & 0xE000) ) 87 | { 88 | cpu::low_mem [addr & 0x7FF] = data; 89 | return; 90 | } 91 | 92 | time += cpu_time_offset; 93 | if ( addr < 0x4000 ) 94 | { 95 | if ( (addr & 7) == 7 ) 96 | cpu_write_2007( data ); 97 | else 98 | ppu.write( time, addr, data ); 99 | return; 100 | } 101 | 102 | clock_ = time; 103 | if ( data_writer_mapped [addr >> page_bits] && mapper->write_intercepted( time, addr, data ) ) 104 | return; 105 | 106 | if ( addr < 0x6000 ) 107 | { 108 | write_io( addr, data ); 109 | return; 110 | } 111 | 112 | if ( addr < sram_writable ) 113 | { 114 | impl->sram [addr & (impl_t::sram_size - 1)] = data; 115 | return; 116 | } 117 | 118 | if ( addr > 0x7FFF ) 119 | { 120 | mapper->write( clock_, addr, data ); 121 | return; 122 | } 123 | 124 | #ifndef NDEBUG 125 | log_unmapped( addr, data ); 126 | #endif 127 | } 128 | 129 | #define NES_CPU_READ_PPU( cpu, addr, time ) \ 130 | STATIC_CAST(Nes_Core&,*cpu).cpu_read_ppu( addr, time ) 131 | 132 | #define NES_CPU_READ( cpu, addr, time ) \ 133 | STATIC_CAST(Nes_Core&,*cpu).cpu_read( addr, time ) 134 | 135 | #define NES_CPU_WRITEX( cpu, addr, data, time ){\ 136 | STATIC_CAST(Nes_Core&,*cpu).cpu_write( addr, data, time );\ 137 | } 138 | 139 | #define NES_CPU_WRITE( cpu, addr, data, time ){\ 140 | if ( addr < 0x800 ) cpu->low_mem [addr] = data;\ 141 | else if ( addr == 0x2007 ) STATIC_CAST(Nes_Core&,*cpu).cpu_write_2007( data );\ 142 | else STATIC_CAST(Nes_Core&,*cpu).cpu_write( addr, data, time );\ 143 | } 144 | -------------------------------------------------------------------------------- /nes_emu/Nes_State.h: -------------------------------------------------------------------------------- 1 | 2 | // NES state snapshot for saving and restoring emulator state 3 | 4 | // Nes_Emu 0.7.0 5 | 6 | #ifndef NES_STATE_H 7 | #define NES_STATE_H 8 | 9 | #include "Nes_File.h" 10 | #include "Nes_Cpu.h" 11 | class Nes_Emu; 12 | class Nes_State; 13 | 14 | typedef long frame_count_t; 15 | 16 | // Writes state to a file 17 | class Nes_State_Writer : public Nes_File_Writer { 18 | public: 19 | // Begin writing file 20 | const char * begin( Auto_File_Writer ); 21 | 22 | // Write emulator's current state to file and end 23 | const char * end( Nes_Emu const& ); 24 | 25 | // Write state to file and end 26 | const char * end( Nes_State const& ); 27 | }; 28 | 29 | // Reads state from a file 30 | class Nes_State_Reader : public Nes_File_Reader { 31 | public: 32 | 33 | // Begin reading state snapshot from file 34 | const char * begin( Auto_File_Reader, Nes_State* = 0 ); 35 | 36 | // Go to next unrecognized block in file 37 | const char * next_block(); 38 | 39 | // State as read from file. Only valid after all blocks have been read. 40 | Nes_State const& state() const; 41 | 42 | public: 43 | Nes_State_Reader(); 44 | ~Nes_State_Reader(); 45 | private: 46 | Nes_State* owned; 47 | Nes_State* state_; 48 | }; 49 | 50 | class Nes_State_ { 51 | public: 52 | 53 | const char * write_blocks( Nes_File_Writer& ) const; 54 | void set_nes_state( nes_state_t const& ); 55 | const char * read_blocks( Nes_File_Reader& ); 56 | 57 | enum { ram_size = 0x800 }; 58 | enum { sram_max = 0x2000 }; 59 | enum { spr_ram_size = 0x100 }; 60 | enum { nametable_max = 0x800 }; 61 | enum { chr_max = 0x2000 }; 62 | uint8_t *ram, *sram, *spr_ram, *nametable, *chr; 63 | nes_state_t nes; 64 | Nes_Cpu::registers_t* cpu; 65 | joypad_state_t* joypad; 66 | apu_state_t* apu; 67 | ppu_state_t* ppu; 68 | mapper_state_t* mapper; 69 | 70 | bool nes_valid, cpu_valid, joypad_valid, apu_valid, ppu_valid; 71 | bool mapper_valid, ram_valid, spr_ram_valid; 72 | short sram_size, nametable_size, chr_size; 73 | 74 | // Invalidate all state 75 | void clear(); 76 | 77 | // Change timestamp 78 | void set_timestamp( frame_count_t ); 79 | 80 | // Timestamp snapshot was taken at 81 | frame_count_t timestamp() const; 82 | }; 83 | 84 | // Snapshot of emulator state 85 | class Nes_State : private Nes_State_ { 86 | public: 87 | 88 | Nes_State(); 89 | 90 | // Write snapshot to file 91 | const char * write( Auto_File_Writer ) const; 92 | 93 | // Read snapshot from file 94 | const char * read( Auto_File_Reader ); 95 | 96 | private: 97 | Nes_Cpu::registers_t cpu; 98 | joypad_state_t joypad; 99 | apu_state_t apu; 100 | ppu_state_t ppu; 101 | mapper_state_t mapper; 102 | uint8_t ram [ram_size]; 103 | uint8_t sram [sram_max]; 104 | uint8_t spr_ram [spr_ram_size]; 105 | uint8_t nametable [nametable_max]; 106 | uint8_t chr [chr_max]; 107 | 108 | friend class Nes_Emu; 109 | friend class Nes_State_Writer; 110 | friend class Nes_State_Reader; 111 | }; 112 | 113 | frame_count_t const invalid_frame_count = LONG_MAX / 2 + 1; // a large positive value 114 | 115 | int mem_differs( void const* in, int compare, unsigned long count ); 116 | 117 | inline Nes_State const& Nes_State_Reader::state() const 118 | { 119 | return *state_; 120 | } 121 | 122 | inline const char * Nes_State_Writer::begin( Auto_File_Writer dw ) 123 | { 124 | return Nes_File_Writer::begin( dw, state_file_tag ); 125 | } 126 | 127 | inline void Nes_State_::set_timestamp( frame_count_t t ) { nes.frame_count = t; } 128 | 129 | inline frame_count_t Nes_State_::timestamp() const { return nes.frame_count; } 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /nes_emu/Nes_Cpu.h: -------------------------------------------------------------------------------- 1 | 2 | // NES 6502 CPU emulator 3 | 4 | // Nes_Emu 0.7.0 5 | 6 | #ifndef NES_CPU_H 7 | #define NES_CPU_H 8 | 9 | #include 10 | #include "blargg_common.h" 11 | 12 | typedef long nes_time_t; // clock cycle count 13 | typedef unsigned nes_addr_t; // 16-bit address 14 | 15 | class Nes_Cpu { 16 | public: 17 | // Clear registers, unmap memory, and map code pages to unmapped_page. 18 | void reset( void const* unmapped_page = 0 ); 19 | 20 | // Map code memory (memory accessed via the program counter). Start and size 21 | // must be multiple of page_size. 22 | enum { page_bits = 11 }; 23 | enum { page_count = 0x10000 >> page_bits }; 24 | enum { page_size = 1L << page_bits }; 25 | void map_code( nes_addr_t start, unsigned size, void const* code ); 26 | 27 | // Access memory as the emulated CPU does. 28 | int read( nes_addr_t ); 29 | void write( nes_addr_t, int data ); 30 | uint8_t* get_code( nes_addr_t ); // non-const to allow debugger to modify code 31 | 32 | // Push a byte on the stack 33 | void push_byte( int ); 34 | 35 | // NES 6502 registers. *Not* kept updated during a call to run(). 36 | struct registers_t { 37 | long pc; // more than 16 bits to allow overflow detection 38 | uint8_t a; 39 | uint8_t x; 40 | uint8_t y; 41 | uint8_t status; 42 | uint8_t sp; 43 | }; 44 | //registers_t r; 45 | 46 | // Reasons that run() returns 47 | enum result_t { 48 | result_cycles, // Requested number of cycles (or more) were executed 49 | result_sei, // I flag just set and IRQ time would generate IRQ now 50 | result_cli, // I flag just cleared but IRQ should occur *after* next instr 51 | result_badop // unimplemented/illegal instruction 52 | }; 53 | 54 | result_t run( nes_time_t end_time ); 55 | 56 | nes_time_t time() const { return clock_count; } 57 | void reduce_limit( int offset ); 58 | void set_end_time_( nes_time_t t ); 59 | void set_irq_time_( nes_time_t t ); 60 | unsigned long error_count() const { return error_count_; } 61 | 62 | // If PC exceeds 0xFFFF and encounters page_wrap_opcode, it will be silently wrapped. 63 | enum { page_wrap_opcode = 0xF2 }; 64 | 65 | // One of the many opcodes that are undefined and stop CPU emulation. 66 | enum { bad_opcode = 0xD2 }; 67 | 68 | private: 69 | uint8_t const* code_map [page_count + 1]; 70 | nes_time_t clock_limit; 71 | nes_time_t clock_count; 72 | nes_time_t irq_time_; 73 | nes_time_t end_time_; 74 | unsigned long error_count_; 75 | 76 | enum { irq_inhibit = 0x04 }; 77 | void set_code_page( int, uint8_t const* ); 78 | void update_clock_limit(); 79 | 80 | public: 81 | registers_t r; 82 | 83 | // low_mem is a full page size so it can be mapped with code_map 84 | uint8_t low_mem [page_size > 0x800 ? page_size : 0x800]; 85 | }; 86 | 87 | inline uint8_t* Nes_Cpu::get_code( nes_addr_t addr ) 88 | { 89 | return (uint8_t*) code_map [addr >> page_bits] + addr; 90 | } 91 | 92 | inline void Nes_Cpu::update_clock_limit() 93 | { 94 | nes_time_t t = end_time_; 95 | if ( t > irq_time_ && !(r.status & irq_inhibit) ) 96 | t = irq_time_; 97 | clock_limit = t; 98 | } 99 | 100 | inline void Nes_Cpu::set_end_time_( nes_time_t t ) 101 | { 102 | end_time_ = t; 103 | update_clock_limit(); 104 | } 105 | 106 | inline void Nes_Cpu::set_irq_time_( nes_time_t t ) 107 | { 108 | irq_time_ = t; 109 | update_clock_limit(); 110 | } 111 | 112 | inline void Nes_Cpu::reduce_limit( int offset ) 113 | { 114 | clock_limit -= offset; 115 | end_time_ -= offset; 116 | irq_time_ -= offset; 117 | } 118 | 119 | inline void Nes_Cpu::push_byte( int data ) 120 | { 121 | int sp = r.sp; 122 | r.sp = (sp - 1) & 0xFF; 123 | low_mem [0x100 + sp] = data; 124 | } 125 | 126 | #endif 127 | -------------------------------------------------------------------------------- /intl/crowdin_source_upload.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import re 4 | import os 5 | import shutil 6 | import subprocess 7 | import sys 8 | import urllib.request 9 | import zipfile 10 | import core_option_translation as t 11 | 12 | # -------------------- MAIN -------------------- # 13 | 14 | if __name__ == '__main__': 15 | # Check Crowdin API Token and core name 16 | try: 17 | API_KEY = sys.argv[1] 18 | CORE_NAME = t.clean_file_name(sys.argv[2]) 19 | except IndexError as e: 20 | print('Please provide Crowdin API Token and core name!') 21 | raise e 22 | 23 | DIR_PATH = t.os.path.dirname(t.os.path.realpath(__file__)) 24 | YAML_PATH = t.os.path.join(DIR_PATH, 'crowdin.yaml') 25 | 26 | # Apply Crowdin API Key 27 | with open(YAML_PATH, 'r') as crowdin_config_file: 28 | crowdin_config = crowdin_config_file.read() 29 | crowdin_config = re.sub(r'"api_token": "_secret_"', 30 | f'"api_token": "{API_KEY}"', 31 | crowdin_config, 1) 32 | crowdin_config = re.sub(r'/_core_name_', 33 | f'/{CORE_NAME}' 34 | , crowdin_config) 35 | with open(YAML_PATH, 'w') as crowdin_config_file: 36 | crowdin_config_file.write(crowdin_config) 37 | 38 | try: 39 | # Download Crowdin CLI 40 | jar_name = 'crowdin-cli.jar' 41 | jar_path = t.os.path.join(DIR_PATH, jar_name) 42 | crowdin_cli_file = 'crowdin-cli.zip' 43 | crowdin_cli_url = 'https://downloads.crowdin.com/cli/v3/' + crowdin_cli_file 44 | crowdin_cli_path = t.os.path.join(DIR_PATH, crowdin_cli_file) 45 | 46 | if not os.path.isfile(t.os.path.join(DIR_PATH, jar_name)): 47 | print('download crowdin-cli.jar') 48 | urllib.request.urlretrieve(crowdin_cli_url, crowdin_cli_path) 49 | with zipfile.ZipFile(crowdin_cli_path, 'r') as zip_ref: 50 | jar_dir = t.os.path.join(DIR_PATH, zip_ref.namelist()[0]) 51 | for file in zip_ref.namelist(): 52 | if file.endswith(jar_name): 53 | jar_file = file 54 | break 55 | zip_ref.extract(jar_file, path=DIR_PATH) 56 | os.rename(t.os.path.join(DIR_PATH, jar_file), jar_path) 57 | os.remove(crowdin_cli_path) 58 | shutil.rmtree(jar_dir) 59 | 60 | print('upload source *.json') 61 | subprocess.run(['java', '-jar', jar_path, 'upload', 'sources', '--config', YAML_PATH]) 62 | 63 | # Reset Crowdin API Key 64 | with open(YAML_PATH, 'r') as crowdin_config_file: 65 | crowdin_config = crowdin_config_file.read() 66 | crowdin_config = re.sub(r'"api_token": ".*?"', 67 | '"api_token": "_secret_"', 68 | crowdin_config, 1) 69 | 70 | # TODO this is NOT safe! 71 | crowdin_config = re.sub(re.escape(f'/{CORE_NAME}'), 72 | '/_core_name_', 73 | crowdin_config) 74 | 75 | with open(YAML_PATH, 'w') as crowdin_config_file: 76 | crowdin_config_file.write(crowdin_config) 77 | 78 | except Exception as e: 79 | # Try really hard to reset Crowdin API Key 80 | with open(YAML_PATH, 'r') as crowdin_config_file: 81 | crowdin_config = crowdin_config_file.read() 82 | crowdin_config = re.sub(r'"api_token": ".*?"', 83 | '"api_token": "_secret_"', 84 | crowdin_config, 1) 85 | 86 | # TODO this is NOT safe! 87 | crowdin_config = re.sub(re.escape(f'/{CORE_NAME}'), 88 | '/_core_name_', 89 | crowdin_config) 90 | 91 | with open(YAML_PATH, 'w') as crowdin_config_file: 92 | crowdin_config_file.write(crowdin_config) 93 | raise e 94 | -------------------------------------------------------------------------------- /intl/crowdin_translation_download.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import re 4 | import os 5 | import shutil 6 | import subprocess 7 | import sys 8 | import urllib.request 9 | import zipfile 10 | import core_option_translation as t 11 | 12 | # -------------------- MAIN -------------------- # 13 | 14 | if __name__ == '__main__': 15 | # Check Crowdin API Token and core name 16 | try: 17 | API_KEY = sys.argv[1] 18 | CORE_NAME = t.clean_file_name(sys.argv[2]) 19 | except IndexError as e: 20 | print('Please provide Crowdin API Token and core name!') 21 | raise e 22 | 23 | DIR_PATH = t.os.path.dirname(t.os.path.realpath(__file__)) 24 | YAML_PATH = t.os.path.join(DIR_PATH, 'crowdin.yaml') 25 | 26 | # Apply Crowdin API Key 27 | with open(YAML_PATH, 'r') as crowdin_config_file: 28 | crowdin_config = crowdin_config_file.read() 29 | crowdin_config = re.sub(r'"api_token": "_secret_"', 30 | f'"api_token": "{API_KEY}"', 31 | crowdin_config, 1) 32 | crowdin_config = re.sub(r'/_core_name_', 33 | f'/{CORE_NAME}' 34 | , crowdin_config) 35 | with open(YAML_PATH, 'w') as crowdin_config_file: 36 | crowdin_config_file.write(crowdin_config) 37 | 38 | try: 39 | # Download Crowdin CLI 40 | jar_name = 'crowdin-cli.jar' 41 | jar_path = t.os.path.join(DIR_PATH, jar_name) 42 | crowdin_cli_file = 'crowdin-cli.zip' 43 | crowdin_cli_url = 'https://downloads.crowdin.com/cli/v3/' + crowdin_cli_file 44 | crowdin_cli_path = t.os.path.join(DIR_PATH, crowdin_cli_file) 45 | 46 | if not os.path.isfile(t.os.path.join(DIR_PATH, jar_name)): 47 | print('download crowdin-cli.jar') 48 | urllib.request.urlretrieve(crowdin_cli_url, crowdin_cli_path) 49 | with zipfile.ZipFile(crowdin_cli_path, 'r') as zip_ref: 50 | jar_dir = t.os.path.join(DIR_PATH, zip_ref.namelist()[0]) 51 | for file in zip_ref.namelist(): 52 | if file.endswith(jar_name): 53 | jar_file = file 54 | break 55 | zip_ref.extract(jar_file, path=DIR_PATH) 56 | os.rename(t.os.path.join(DIR_PATH, jar_file), jar_path) 57 | os.remove(crowdin_cli_path) 58 | shutil.rmtree(jar_dir) 59 | 60 | print('download translation *.json') 61 | subprocess.run(['java', '-jar', jar_path, 'download', '--config', YAML_PATH]) 62 | 63 | # Reset Crowdin API Key 64 | with open(YAML_PATH, 'r') as crowdin_config_file: 65 | crowdin_config = crowdin_config_file.read() 66 | crowdin_config = re.sub(r'"api_token": ".*?"', 67 | '"api_token": "_secret_"', 68 | crowdin_config, 1) 69 | 70 | # TODO this is NOT safe! 71 | crowdin_config = re.sub(re.escape(f'/{CORE_NAME}'), 72 | '/_core_name_', 73 | crowdin_config) 74 | 75 | with open(YAML_PATH, 'w') as crowdin_config_file: 76 | crowdin_config_file.write(crowdin_config) 77 | 78 | except Exception as e: 79 | # Try really hard to reset Crowdin API Key 80 | with open(YAML_PATH, 'r') as crowdin_config_file: 81 | crowdin_config = crowdin_config_file.read() 82 | crowdin_config = re.sub(r'"api_token": ".*?"', 83 | '"api_token": "_secret_"', 84 | crowdin_config, 1) 85 | 86 | # TODO this is NOT safe! 87 | crowdin_config = re.sub(re.escape(f'/{CORE_NAME}'), 88 | '/_core_name_', 89 | crowdin_config) 90 | 91 | with open(YAML_PATH, 'w') as crowdin_config_file: 92 | crowdin_config_file.write(crowdin_config) 93 | raise e 94 | -------------------------------------------------------------------------------- /nes_emu/Data_Reader.h: -------------------------------------------------------------------------------- 1 | // Lightweight interface for reading data from byte stream 2 | 3 | // File_Extractor 1.0.0 4 | #ifndef DATA_READER_H 5 | #define DATA_READER_H 6 | 7 | #include 8 | #include "blargg_common.h" 9 | 10 | /* Some functions accept a long instead of int for convenience where caller has 11 | a long due to some other interface, and would otherwise have to get a warning, 12 | or cast it (and verify that it wasn't outside the range of an int). 13 | 14 | To really support huge (>2GB) files, long isn't a solution, since there's no 15 | guarantee it's more than 32 bits. We'd need to use long long (if available), or 16 | something compiler-specific, and change all places file sizes or offsets are 17 | used. */ 18 | 19 | // Supports reading and finding out how many bytes are remaining 20 | class Data_Reader { 21 | public: 22 | 23 | // Reads min(*n,remain()) bytes and sets *n to this number, thus trying to read more 24 | // tham remain() bytes doesn't result in error, just *n being set to remain(). 25 | const char * read_avail( void* p, int* n ); 26 | const char * read_avail( void* p, long* n ); 27 | 28 | // Reads exactly n bytes, or returns error if they couldn't ALL be read. 29 | // Reading past end of file results in blargg_err_file_eof. 30 | const char * read( void* p, int n ); 31 | 32 | // Number of bytes remaining until end of file 33 | uint64_t remain() const { return remain_; } 34 | 35 | // Reads and discards n bytes. Skipping past end of file results in blargg_err_file_eof. 36 | const char * skip( int n ); 37 | 38 | virtual ~Data_Reader() { } 39 | 40 | private: 41 | // noncopyable 42 | Data_Reader( const Data_Reader& ); 43 | Data_Reader& operator = ( const Data_Reader& ); 44 | 45 | // Derived interface 46 | protected: 47 | Data_Reader() : remain_( 0 ) { } 48 | 49 | // Sets remain 50 | void set_remain( uint64_t n ) { remain_ = n; } 51 | 52 | // Do same as read(). Guaranteed that 0 < n <= remain(). Value of remain() is updated 53 | // AFTER this call succeeds, not before. set_remain() should NOT be called from this. 54 | virtual const char * read_v( void*, int n ) BLARGG_PURE( { (void)n; return 0; } ) 55 | 56 | // Do same as skip(). Guaranteed that 0 < n <= remain(). Default just reads data 57 | // and discards it. Value of remain() is updated AFTER this call succeeds, not 58 | // before. set_remain() should NOT be called from this. 59 | virtual const char * skip_v( int n ); 60 | 61 | private: 62 | uint64_t remain_; 63 | }; 64 | 65 | 66 | // Supports seeking in addition to Data_Reader operations 67 | class File_Reader : public Data_Reader { 68 | public: 69 | 70 | // Size of file 71 | uint64_t size() const { return size_; } 72 | 73 | // Current position in file 74 | uint64_t tell() const { return size_ - remain(); } 75 | 76 | // Derived interface 77 | protected: 78 | // Sets size and resets position 79 | void set_size( uint64_t n ) { size_ = n; Data_Reader::set_remain( n ); } 80 | void set_size( int n ) { set_size( STATIC_CAST(uint64_t, n) ); } 81 | void set_size( long n ) { set_size( STATIC_CAST(uint64_t, n) ); } 82 | 83 | // Sets reported position 84 | void set_tell( uint64_t i ) { Data_Reader::set_remain( size_ - i ); } 85 | // Implementation 86 | protected: 87 | File_Reader() : size_( 0 ) { } 88 | 89 | private: 90 | uint64_t size_; 91 | 92 | void set_remain(); // avoid accidental use of set_remain 93 | }; 94 | 95 | 96 | // Treats range of memory as a file 97 | class Mem_File_Reader : public File_Reader { 98 | public: 99 | 100 | Mem_File_Reader( const void* begin, long size ); 101 | 102 | // Implementation 103 | protected: 104 | virtual const char * read_v( void*, int ); 105 | 106 | private: 107 | const char* const begin; 108 | }; 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /nes_emu/mappers/mapper005.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // NES MMC5 mapper, currently only tailored for Castlevania 3 (U) 4 | 5 | // Nes_Emu 0.7.0. http://www.slack.net/~ant/ 6 | 7 | #include "Nes_Mapper.h" 8 | 9 | #include "Nes_Core.h" 10 | #include 11 | 12 | /* Copyright (C) 2004-2006 Shay Green. This module is free software; you 13 | can redistribute it and/or modify it under the terms of the GNU Lesser 14 | General Public License as published by the Free Software Foundation; either 15 | version 2.1 of the License, or (at your option) any later version. This 16 | module is distributed in the hope that it will be useful, but WITHOUT ANY 17 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 18 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 19 | more details. You should have received a copy of the GNU Lesser General 20 | Public License along with this module; if not, write to the Free Software 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 22 | 23 | #include "blargg_source.h" 24 | 25 | 26 | struct mmc5_state_t 27 | { 28 | enum { reg_count = 0x30 }; 29 | uint8_t regs [0x30]; 30 | uint8_t irq_enabled; 31 | }; 32 | // to do: finalize state format 33 | BOOST_STATIC_ASSERT( sizeof (mmc5_state_t) == 0x31 ); 34 | 35 | // MMC5 36 | 37 | class Mapper005 : public Nes_Mapper, mmc5_state_t { 38 | public: 39 | Mapper005() 40 | { 41 | mmc5_state_t* state = this; 42 | register_state( state, sizeof *state ); 43 | } 44 | 45 | virtual void reset_state() 46 | { 47 | irq_time = no_irq; 48 | regs [0x00] = 2; 49 | regs [0x01] = 3; 50 | regs [0x14] = 0x7f; 51 | regs [0x15] = 0x7f; 52 | regs [0x16] = 0x7f; 53 | regs [0x17] = 0x7f; 54 | } 55 | 56 | virtual void read_state( mapper_state_t const& in ) 57 | { 58 | Nes_Mapper::read_state( in ); 59 | irq_time = no_irq; 60 | } 61 | 62 | enum { regs_addr = 0x5100 }; 63 | 64 | virtual nes_time_t next_irq( nes_time_t ) 65 | { 66 | if ( irq_enabled & 0x80 ) 67 | return irq_time; 68 | 69 | return no_irq; 70 | } 71 | 72 | virtual bool write_intercepted( nes_time_t time, nes_addr_t addr, int data ) 73 | { 74 | int reg = addr - regs_addr; 75 | if ( (unsigned) reg < reg_count ) 76 | { 77 | regs [reg] = data; 78 | switch ( reg ) 79 | { 80 | case 0x05: 81 | mirror_manual( data & 3, data >> 2 & 3, 82 | data >> 4 & 3, data >> 6 & 3 ); 83 | break; 84 | 85 | case 0x15: 86 | set_prg_bank( 0x8000, bank_16k, data >> 1 & 0x3f ); 87 | break; 88 | 89 | case 0x16: 90 | set_prg_bank( 0xC000, bank_8k, data & 0x7f ); 91 | break; 92 | 93 | case 0x17: 94 | set_prg_bank( 0xE000, bank_8k, data & 0x7f ); 95 | break; 96 | 97 | case 0x20: 98 | case 0x21: 99 | case 0x22: 100 | case 0x23: 101 | case 0x28: 102 | case 0x29: 103 | case 0x2a: 104 | case 0x2b: 105 | set_chr_bank( ((reg >> 1 & 4) + (reg & 3)) * 0x400, bank_1k, data ); 106 | break; 107 | } 108 | } 109 | else if ( addr == 0x5203 ) 110 | { 111 | irq_time = no_irq; 112 | if ( data && data < 240 ) 113 | { 114 | irq_time = (341 * 21 + 128 + (data * 341)) / 3; 115 | if ( irq_time < time ) 116 | irq_time = no_irq; 117 | } 118 | irq_changed(); 119 | } 120 | else if ( addr == 0x5204 ) 121 | { 122 | irq_enabled = data; 123 | irq_changed(); 124 | } 125 | else 126 | { 127 | return false; 128 | } 129 | 130 | return true; 131 | } 132 | 133 | void apply_mapping() 134 | { 135 | static unsigned char list [] = { 136 | 0x05, 0x15, 0x16, 0x17, 137 | 0x20, 0x21, 0x22, 0x23, 138 | 0x28, 0x29, 0x2a, 0x2b 139 | }; 140 | 141 | for ( int i = 0; i < (int) sizeof list; i++ ) 142 | write_intercepted( 0, regs_addr + list [i], regs [list [i]] ); 143 | intercept_writes( 0x5100, 0x200 ); 144 | } 145 | 146 | virtual void write( nes_time_t, nes_addr_t, int ) { } 147 | 148 | nes_time_t irq_time; 149 | }; 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /nes_emu/Nes_Ppu.h: -------------------------------------------------------------------------------- 1 | 2 | // NES PPU emulator 3 | 4 | // Nes_Emu 0.7.0 5 | 6 | #ifndef NES_PPU_H 7 | #define NES_PPU_H 8 | 9 | #include "Nes_Ppu_Rendering.h" 10 | class Nes_Mapper; 11 | class Nes_Core; 12 | 13 | typedef long nes_time_t; 14 | typedef long ppu_time_t; // ppu_time_t = nes_time_t * ppu_overclock 15 | 16 | ppu_time_t const ppu_overclock = 3; // PPU clocks for each CPU clock 17 | 18 | class Nes_Ppu : public Nes_Ppu_Rendering { 19 | typedef Nes_Ppu_Rendering base; 20 | public: 21 | Nes_Ppu( Nes_Core* ); 22 | 23 | // Begin PPU frame and return beginning CPU timestamp 24 | nes_time_t begin_frame( ppu_time_t ); 25 | 26 | nes_time_t nmi_time() { return nmi_time_; } 27 | void acknowledge_nmi() { nmi_time_ = LONG_MAX / 2 + 1; } 28 | 29 | int read_2002( nes_time_t ); 30 | int read( unsigned addr, nes_time_t ); 31 | void write( nes_time_t, unsigned addr, int ); 32 | 33 | void render_bg_until( nes_time_t ); 34 | void render_until( nes_time_t ); 35 | 36 | // CPU time that frame will have ended by 37 | int frame_length() const { return frame_length_; } 38 | 39 | // End frame rendering and return PPU timestamp for next frame 40 | ppu_time_t end_frame( nes_time_t ); 41 | 42 | // Do direct memory copy to sprite RAM 43 | void dma_sprites( nes_time_t, void const* in ); 44 | 45 | int burst_phase; 46 | 47 | private: 48 | 49 | Nes_Core& emu; 50 | 51 | enum { indefinite_time = LONG_MAX / 2 + 1 }; 52 | 53 | void suspend_rendering(); 54 | int read_( unsigned addr, nes_time_t ); // note swapped arguments! 55 | 56 | // NES<->PPU time conversion 57 | int extra_clocks; 58 | ppu_time_t ppu_time( nes_time_t t ) const { return t * ppu_overclock + extra_clocks; } 59 | nes_time_t nes_time( ppu_time_t t ) const { return (t - extra_clocks) / ppu_overclock; } 60 | 61 | // frame 62 | nes_time_t nmi_time_; 63 | int end_vbl_mask; 64 | int frame_length_; 65 | int frame_length_extra; 66 | bool frame_ended; 67 | void end_vblank(); 68 | void run_end_frame( nes_time_t ); 69 | 70 | // bg rendering 71 | nes_time_t next_bg_time; 72 | ppu_time_t scanline_time; 73 | ppu_time_t hblank_time; 74 | int scanline_count; 75 | int frame_phase; 76 | void render_bg_until_( nes_time_t ); 77 | void run_scanlines( int count ); 78 | 79 | // sprite rendering 80 | ppu_time_t next_sprites_time; 81 | int next_sprites_scanline; 82 | void render_until_( nes_time_t ); 83 | 84 | // $2002 status register 85 | nes_time_t next_status_event; 86 | void query_until( nes_time_t ); 87 | 88 | // sprite hit 89 | nes_time_t next_sprite_hit_check; 90 | void update_sprite_hit( nes_time_t ); 91 | 92 | // open bus decay 93 | void update_open_bus( nes_time_t ); 94 | void poke_open_bus( nes_time_t, int, int mask ); 95 | nes_time_t earliest_open_bus_decay(); 96 | 97 | // sprite max 98 | nes_time_t next_sprite_max_run; // doesn't need to run until this time 99 | nes_time_t sprite_max_set_time; // if 0, needs to be recalculated 100 | int next_sprite_max_scanline; 101 | void run_sprite_max_( nes_time_t ); 102 | void run_sprite_max( nes_time_t ); 103 | void invalidate_sprite_max_(); 104 | void invalidate_sprite_max( nes_time_t ); 105 | 106 | friend int nes_cpu_read_likely_ppu( class Nes_Core*, unsigned, nes_time_t ); 107 | }; 108 | 109 | inline void Nes_Ppu::suspend_rendering() 110 | { 111 | next_bg_time = indefinite_time; 112 | next_sprites_time = indefinite_time; 113 | extra_clocks = 0; 114 | } 115 | 116 | inline Nes_Ppu::Nes_Ppu( Nes_Core* e ) : emu( *e ) 117 | { 118 | burst_phase = 0; 119 | suspend_rendering(); 120 | } 121 | 122 | inline void Nes_Ppu::render_until( nes_time_t t ) 123 | { 124 | if ( t > next_sprites_time ) 125 | render_until_( t ); 126 | } 127 | 128 | inline void Nes_Ppu::render_bg_until( nes_time_t t ) 129 | { 130 | if ( t > next_bg_time ) 131 | render_bg_until_( t ); 132 | } 133 | 134 | inline void Nes_Ppu::update_open_bus( nes_time_t time ) 135 | { 136 | if ( time >= decay_low ) open_bus &= ~0x1F; 137 | if ( time >= decay_high ) open_bus &= ~0xE0; 138 | } 139 | 140 | #endif 141 | -------------------------------------------------------------------------------- /nes_emu/Nes_Ppu_Sprites.h: -------------------------------------------------------------------------------- 1 | 2 | int sprite_2 = sprite [2]; 3 | 4 | // pixels 5 | ptrdiff_t next_row = this->scanline_row_bytes; 6 | uint8_t* out = this->scanline_pixels + sprite [3] + 7 | (top_minus_one + skip - begin_minus_one) * next_row; 8 | cache_t const* lines = get_sprite_tile( sprite ); 9 | 10 | int dir = 1; 11 | uint8_t* scanlines = this->sprite_scanlines + 1 + top_minus_one + skip; 12 | 13 | if ( sprite_2 & 0x80 ) 14 | { 15 | // vertical flip 16 | out -= next_row; 17 | out += visible * next_row; 18 | next_row = -next_row; 19 | dir = -1; 20 | scanlines += visible - 1; 21 | #if CLIPPED 22 | int height = this->sprite_height(); 23 | skip = height - skip - visible; 24 | #endif 25 | } 26 | 27 | // attributes 28 | unsigned long offset = (sprite_2 & 3) * 0x04040404 + (this->palette_offset + 0x10101010); 29 | 30 | unsigned long const mask = 0x03030303 + zero; 31 | unsigned long const maskgen = 0x80808080 + zero; 32 | 33 | #define DRAW_PAIR( shift ) { \ 34 | int sprite_count = *scanlines; \ 35 | CALC_FOUR( ((unaligned_uint32_t*) out) [0].val, (line >> (shift + 4)), out0 ) \ 36 | CALC_FOUR( ((unaligned_uint32_t*) out) [1].val, (line >> shift), out1 ) \ 37 | if ( sprite_count < this->max_sprites ) { \ 38 | ((unaligned_uint32_t*) out) [0].val = out0; \ 39 | ((unaligned_uint32_t*) out) [1].val = out1; \ 40 | } \ 41 | if ( CLIPPED ) visible--; \ 42 | out += next_row; \ 43 | *scanlines = sprite_count + 1; \ 44 | scanlines += dir; \ 45 | if ( CLIPPED && !visible ) break; \ 46 | } 47 | 48 | if ( !(sprite_2 & 0x20) ) 49 | { 50 | // front 51 | unsigned long const maskgen2 = 0x7f7f7f7f + zero; 52 | 53 | #define CALC_FOUR( in, line, out ) \ 54 | unsigned long out; \ 55 | { \ 56 | unsigned long bg = in; \ 57 | unsigned long sp = line & mask; \ 58 | unsigned long bgm = maskgen2 + ((bg >> 4) & mask); \ 59 | unsigned long spm = (maskgen - sp) & maskgen2; \ 60 | unsigned long m = (bgm & spm) >> 2; \ 61 | out = (bg & ~m) | ((sp + offset) & m); \ 62 | } 63 | 64 | #if CLIPPED 65 | lines += skip >> 1; 66 | unsigned long line = *lines++; 67 | if ( skip & 1 ) 68 | goto front_skip; 69 | 70 | while ( true ) 71 | { 72 | DRAW_PAIR( 0 ) 73 | front_skip: 74 | DRAW_PAIR( 2 ) 75 | line = *lines++; 76 | } 77 | #else 78 | for ( int n = visible >> 1; n--; ) 79 | { 80 | unsigned long line = *lines++; 81 | DRAW_PAIR( 0 ) 82 | DRAW_PAIR( 2 ) 83 | } 84 | #endif 85 | 86 | #undef CALC_FOUR 87 | } 88 | else 89 | { 90 | // behind 91 | unsigned long const omask = 0x20202020 + zero; 92 | unsigned long const bg_or = 0xc3c3c3c3 + zero; 93 | 94 | #define CALC_FOUR( in, line, out ) \ 95 | unsigned long out; \ 96 | { \ 97 | unsigned long bg = in; \ 98 | unsigned long sp = line & mask; \ 99 | unsigned long bgm = maskgen - (bg & mask); \ 100 | unsigned long spm = maskgen - sp; \ 101 | out = (bg & (bgm | bg_or)) | (spm & omask) | \ 102 | (((offset & spm) + sp) & ~(bgm >> 2)); \ 103 | } 104 | 105 | #if CLIPPED 106 | lines += skip >> 1; 107 | unsigned long line = *lines++; 108 | if ( skip & 1 ) 109 | goto back_skip; 110 | 111 | while ( true ) 112 | { 113 | DRAW_PAIR( 0 ) 114 | back_skip: 115 | DRAW_PAIR( 2 ) 116 | line = *lines++; 117 | } 118 | #else 119 | for ( int n = visible >> 1; n--; ) 120 | { 121 | unsigned long line = *lines++; 122 | DRAW_PAIR( 0 ) 123 | DRAW_PAIR( 2 ) 124 | } 125 | #endif 126 | 127 | #undef CALC_FOUR 128 | } 129 | 130 | #undef CLIPPED 131 | #undef DRAW_PAIR 132 | -------------------------------------------------------------------------------- /nes_emu/blargg_endian.h: -------------------------------------------------------------------------------- 1 | 2 | // CPU Byte Order Utilities 3 | 4 | // Nes_Emu 0.7.0 5 | 6 | #ifndef BLARGG_ENDIAN 7 | #define BLARGG_ENDIAN 8 | 9 | #include "blargg_common.h" 10 | 11 | // BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16) 12 | #if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \ 13 | defined (__x86_64__) || defined (__ia64__) 14 | #define BLARGG_CPU_X86 1 15 | #define BLARGG_CPU_CISC 1 16 | #endif 17 | 18 | #if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc) 19 | #define BLARGG_CPU_POWERPC 1 20 | #endif 21 | 22 | inline unsigned get_le16( void const* p ) { 23 | return ((unsigned char*) p) [1] * 0x100u + 24 | ((unsigned char*) p) [0]; 25 | } 26 | inline unsigned get_be16( void const* p ) { 27 | return ((unsigned char*) p) [0] * 0x100u + 28 | ((unsigned char*) p) [1]; 29 | } 30 | inline unsigned long get_le32( void const* p ) { 31 | return ((unsigned char*) p) [3] * 0x01000000ul + 32 | ((unsigned char*) p) [2] * 0x00010000ul + 33 | ((unsigned char*) p) [1] * 0x00000100ul + 34 | ((unsigned char*) p) [0]; 35 | } 36 | inline unsigned long get_be32( void const* p ) { 37 | return ((unsigned char*) p) [0] * 0x01000000ul + 38 | ((unsigned char*) p) [1] * 0x00010000ul + 39 | ((unsigned char*) p) [2] * 0x00000100ul + 40 | ((unsigned char*) p) [3]; 41 | } 42 | inline void set_le16( void* p, unsigned n ) { 43 | ((unsigned char*) p) [1] = (unsigned char) (n >> 8); 44 | ((unsigned char*) p) [0] = (unsigned char) n; 45 | } 46 | inline void set_be16( void* p, unsigned n ) { 47 | ((unsigned char*) p) [0] = (unsigned char) (n >> 8); 48 | ((unsigned char*) p) [1] = (unsigned char) n; 49 | } 50 | inline void set_le32( void* p, unsigned long n ) { 51 | ((unsigned char*) p) [3] = (unsigned char) (n >> 24); 52 | ((unsigned char*) p) [2] = (unsigned char) (n >> 16); 53 | ((unsigned char*) p) [1] = (unsigned char) (n >> 8); 54 | ((unsigned char*) p) [0] = (unsigned char) n; 55 | } 56 | inline void set_be32( void* p, unsigned long n ) { 57 | ((unsigned char*) p) [0] = (unsigned char) (n >> 24); 58 | ((unsigned char*) p) [1] = (unsigned char) (n >> 16); 59 | ((unsigned char*) p) [2] = (unsigned char) (n >> 8); 60 | ((unsigned char*) p) [3] = (unsigned char) n; 61 | } 62 | 63 | #if BLARGG_NONPORTABLE 64 | // Optimized implementation if byte order is known 65 | #ifdef MSB_FIRST 66 | #define GET_BE16( addr ) (*(uint16_t*) (addr)) 67 | #define GET_BE32( addr ) (*(uint32_t*) (addr)) 68 | #define SET_BE16( addr, data ) (void) (*(uint16_t*) (addr) = (data)) 69 | #define SET_BE32( addr, data ) (void) (*(uint32_t*) (addr) = (data)) 70 | #else 71 | #define GET_LE16( addr ) (*(uint16_t*) (addr)) 72 | #define SET_LE16( addr, data ) (void) (*(uint16_t*) (addr) = (data)) 73 | #define SET_LE32( addr, data ) (void) (*(uint32_t*) (addr) = (data)) 74 | #endif 75 | 76 | #if BLARGG_CPU_POWERPC && defined (__MWERKS__) 77 | // PowerPC has special byte-reversed instructions 78 | // to do: assumes that PowerPC is running in big-endian mode 79 | // to do: implement for other compilers which don't support these macros 80 | #define GET_LE16( addr ) (__lhbrx( (addr), 0 )) 81 | #define SET_LE16( addr, data ) (__sthbrx( (data), (addr), 0 )) 82 | #define SET_LE32( addr, data ) (__stwbrx( (data), (addr), 0 )) 83 | #endif 84 | #endif 85 | 86 | #ifndef GET_LE16 87 | #define GET_LE16( addr ) get_le16( addr ) 88 | #define SET_LE16( addr, data ) set_le16( addr, data ) 89 | #define SET_LE32( addr, data ) set_le32( addr, data ) 90 | #endif 91 | 92 | #ifndef GET_BE16 93 | #define GET_BE16( addr ) get_be16( addr ) 94 | #define GET_BE32( addr ) get_be32( addr ) 95 | #define SET_BE16( addr, data ) set_be16( addr, data ) 96 | #define SET_BE32( addr, data ) set_be32( addr, data ) 97 | #endif 98 | 99 | // auto-selecting versions 100 | 101 | inline void set_le( uint16_t* p, unsigned n ) { SET_LE16( p, n ); } 102 | inline void set_le( uint32_t* p, unsigned long n ) { SET_LE32( p, n ); } 103 | inline void set_be( uint16_t* p, unsigned n ) { SET_BE16( p, n ); } 104 | inline void set_be( uint32_t* p, unsigned long n ) { SET_BE32( p, n ); } 105 | inline unsigned get_be( uint16_t* p ) { return GET_BE16( p ); } 106 | inline unsigned long get_be( uint32_t* p ) { return GET_BE32( p ); } 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /nes_emu/nes_util.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Nes_Emu 0.7.0. http://www.slack.net/~ant/ 3 | 4 | #include "nes_util.h" 5 | 6 | #include "Nes_Cart.h" 7 | #include "Nes_Emu.h" 8 | #include 9 | #include 10 | 11 | /* Copyright (C) 2004-2006 Shay Green. This module is free software; you 12 | can redistribute it and/or modify it under the terms of the GNU Lesser 13 | General Public License as published by the Free Software Foundation; either 14 | version 2.1 of the License, or (at your option) any later version. This 15 | module is distributed in the hope that it will be useful, but WITHOUT ANY 16 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 17 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 18 | more details. You should have received a copy of the GNU Lesser General 19 | Public License along with this module; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 21 | 22 | #include "blargg_source.h" 23 | 24 | // game_genie_patch_t 25 | 26 | const char *game_genie_patch_t::decode( const char* in ) 27 | { 28 | int const code_len = 8; 29 | unsigned char result [code_len] = { 0 }; 30 | int in_len = strlen( in ); 31 | if ( in_len != 6 && in_len != 8 ) 32 | return "Game Genie code is wrong length"; 33 | for ( int i = 0; i < code_len; i++ ) 34 | { 35 | char c = 'A'; 36 | if ( i < in_len ) 37 | c = toupper( in [i] ); 38 | 39 | static char const letters [17] = "AEPOZXLUGKISTVYN"; 40 | char const* p = strchr( (char*) letters, c ); 41 | if ( !p ) 42 | return "Game Genie code had invalid character"; 43 | int n = p - letters; 44 | 45 | result [i] |= n >> 1; 46 | result [(i + 1) % code_len] |= (n << 3) & 0x0f; 47 | } 48 | 49 | addr = result [3]<<12 | result [5]<<8 | result [2]<<4 | result [4]; 50 | change_to = result [1]<<4 | result [0]; 51 | compare_with = -1; 52 | if ( addr & 0x8000 ) 53 | compare_with = result [7]<<4 | result [6]; 54 | addr |= 0x8000; 55 | 56 | return 0; 57 | } 58 | 59 | int game_genie_patch_t::apply( Nes_Cart& cart ) const 60 | { 61 | // determine bank size 62 | long bank_size = 32 * 1024L; // mappers 0, 2, 3, 7, 11, 34, 71, 87 63 | switch ( cart.mapper_code() ) 64 | { 65 | case 1: // MMC1 66 | case 71: // Camerica 67 | case 232: // Quattro 68 | bank_size = 16 * 1024L; 69 | break; 70 | 71 | case 4: // MMC3 72 | case 5: // MMC5 73 | case 24: // VRC6 74 | case 26: // VRC6 75 | case 69: // FME7 76 | bank_size = 8 * 1024L; 77 | break; 78 | } 79 | 80 | // patch each bank (not very good, since it might patch banks that never occupy 81 | // that address) 82 | int mask = (compare_with >= 0 ? ~0 : 0); 83 | uint8_t* p = cart.prg() + addr % bank_size; 84 | int count = 0; 85 | for ( int n = cart.prg_size() / bank_size; n--; p += bank_size ) 86 | { 87 | if ( !((*p ^ compare_with) & mask) ) 88 | { 89 | *p = change_to; 90 | count++; 91 | } 92 | } 93 | return count; 94 | } 95 | 96 | // Cheat_Value_Finder 97 | 98 | Cheat_Value_Finder::Cheat_Value_Finder() 99 | { 100 | emu = NULL; 101 | } 102 | 103 | void Cheat_Value_Finder::start( Nes_Emu* new_emu ) 104 | { 105 | emu = new_emu; 106 | pos = 0; 107 | memcpy( original, emu->low_mem(), low_mem_size ); 108 | memset( changed, 0, low_mem_size ); 109 | } 110 | 111 | void Cheat_Value_Finder::rescan() 112 | { 113 | uint8_t const* low_mem = emu->low_mem(); 114 | for ( int i = 0; i < low_mem_size; i++ ) 115 | changed [i] |= original [i] ^ low_mem [i]; 116 | memcpy( original, emu->low_mem(), low_mem_size ); 117 | } 118 | 119 | void Cheat_Value_Finder::search( int new_original, int new_changed ) 120 | { 121 | original_value = new_original; 122 | changed_value = new_changed; 123 | pos = -1; 124 | } 125 | 126 | int Cheat_Value_Finder::next_match( int* addr ) 127 | { 128 | uint8_t const* low_mem = emu->low_mem(); 129 | while ( ++pos < low_mem_size ) 130 | { 131 | if ( !changed [pos] ) 132 | { 133 | int old = (original [pos] - original_value) & 0xff; 134 | int cur = (low_mem [pos] - changed_value) & 0xff; 135 | 136 | if ( old == cur ) 137 | { 138 | if ( addr ) 139 | *addr = pos; 140 | return (char) old; // sign-extend 141 | } 142 | } 143 | } 144 | 145 | return no_match; 146 | } 147 | 148 | int Cheat_Value_Finder::change_value( int new_value ) 149 | { 150 | int result = emu->low_mem() [pos]; 151 | emu->low_mem() [pos] = new_value; 152 | return result; 153 | } 154 | --------------------------------------------------------------------------------