├── vgm ├── sn76489.vgm └── ym2612.vgm ├── .gitignore ├── assets ├── m5stack-synth-01.jpg └── m5stack-synth-02.jpg ├── .vscode ├── extensions.json ├── c_cpp_properties.json └── settings.json ├── flashrom.sh ├── .editorconfig ├── Makefile ├── partitions.csv ├── .gitmodules ├── main ├── component.mk └── main.cpp ├── components └── synth │ ├── src │ ├── panning.h │ ├── mamedef.h │ ├── panning.c │ ├── sn76489.h │ ├── ym2612.hpp │ ├── sn76489.c │ └── ym2612.cpp │ └── component.mk ├── .github └── workflows │ ├── m5stack.yml │ └── release.yml ├── README.md ├── LICENSE.txt └── sdkconfig /vgm/sn76489.vgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/h1romas4/m5stack-synth-emulation/HEAD/vgm/sn76489.vgm -------------------------------------------------------------------------------- /vgm/ym2612.vgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/h1romas4/m5stack-synth-emulation/HEAD/vgm/ym2612.vgm -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | *.o 3 | *.vgm 4 | *.pcm 5 | components/synth/vgmplay 6 | !vgm/sn76489.vgm 7 | !vgm/ym2612.vgm 8 | -------------------------------------------------------------------------------- /assets/m5stack-synth-01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/h1romas4/m5stack-synth-emulation/HEAD/assets/m5stack-synth-01.jpg -------------------------------------------------------------------------------- /assets/m5stack-synth-02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/h1romas4/m5stack-synth-emulation/HEAD/assets/m5stack-synth-02.jpg -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "ms-vscode.cpptools", 4 | "EditorConfig.EditorConfig" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /flashrom.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | . ${IDF_PATH}/add_path.sh 3 | esptool.py --chip esp32 --port "/dev/ttyUSB0" --baud 115200 write_flash -fs 4MB 0x211000 "$1" 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a 3 | # project subdirectory. 4 | # 5 | 6 | PROJECT_NAME := m5stack-synth-emulation 7 | 8 | include $(IDF_PATH)/make/project.mk 9 | 10 | -------------------------------------------------------------------------------- /partitions.csv: -------------------------------------------------------------------------------- 1 | # Name, Type, SubType, Offset, Size, Flags 2 | nvs, data, nvs, 0x9000, 0x5000, 3 | otadata, data, ota, 0xe000, 0x2000, 4 | app0, app, ota_0, 0x10000, 0x200000, 5 | eeprom, data, 0x99, 0x210000,0x1000, 6 | sound, data, 0x01, 0x211000,0x1EF000 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "components/arduino"] 2 | path = components/arduino 3 | url = https://github.com/espressif/arduino-esp32.git 4 | [submodule "components/m5stack"] 5 | path = components/m5stack 6 | url = https://github.com/m5stack/m5stack.git 7 | [submodule "esp-idf"] 8 | path = esp-idf 9 | url = https://github.com/espressif/esp-idf.git 10 | -------------------------------------------------------------------------------- /main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Main component makefile. 3 | # 4 | # This Makefile can be left empty. By default, it will take the sources in the 5 | # src/ directory, compile them and link them into lib(subdirectory_name).a 6 | # in the build directory. This behaviour is entirely configurable, 7 | # please read the ESP-IDF documents if you need to do this. 8 | # 9 | -------------------------------------------------------------------------------- /components/synth/src/panning.h: -------------------------------------------------------------------------------- 1 | /* 2 | panning.h by Maxim in 2006 3 | Implements "simple equal power" panning using sine distribution 4 | I am not an expert on this stuff, but this is the best sounding of the methods I've tried 5 | */ 6 | 7 | #ifndef PANNING_H 8 | #define PANNING_H 9 | 10 | void calc_panning(float channels[2], int position); 11 | void centre_panning(float channels[2]); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /components/synth/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Main Makefile. This is basically the same as a component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | 6 | COMPONENT_SRCDIRS := src 7 | COMPONENT_OBJS := src/sn76489.o src/panning.o src/ym2612.o 8 | COMPONENT_ADD_INCLUDEDIRS := src 9 | 10 | CFLAGS := -Wno-unused-result 11 | CFLAGS := -Wno-unused-function 12 | CFLAGS := -mlongcalls 13 | CPPFLAGS := -DESP32_SYNTH 14 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Linux", 5 | "includePath": [ 6 | "${workspaceRoot}", 7 | "${env:IDF_PATH}/components/" 8 | ], 9 | "browse": { 10 | "limitSymbolsToIncludedHeaders": true, 11 | "databaseFilename": "", 12 | "path": [ 13 | "${workspaceRoot}", 14 | "${env:IDF_PATH}/esp-idf/components/" 15 | ] 16 | }, 17 | "intelliSenseMode": "clang-x64", 18 | "compilerPath": "~/toolchain/xtensa-esp32-elf", 19 | "cStandard": "c11", 20 | "cppStandard": "c++17" 21 | } 22 | ], 23 | "version": 4 24 | } 25 | -------------------------------------------------------------------------------- /.github/workflows/m5stack.yml: -------------------------------------------------------------------------------- 1 | name: M5Stack CI 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-18.04 8 | steps: 9 | - uses: actions/checkout@v1 10 | with: 11 | submodules: recursive 12 | 13 | - name: esp-idf Toolchain Setup 14 | run: | 15 | sudo apt-get install gcc git wget make libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-cryptography python-future 16 | wget https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz 17 | tar zxvf xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz 18 | 19 | - name: Build 20 | run: | 21 | export PATH=$(pwd)/xtensa-esp32-elf/bin:${PATH} 22 | export IDF_PATH=$(pwd)/esp-idf 23 | python -m pip install --user -r $IDF_PATH/requirements.txt 24 | make 25 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "C_Cpp.intelliSenseEngine": "Tag Parser", 3 | "files.associations": { 4 | "array": "cpp", 5 | "unordered_map": "cpp", 6 | "vector": "cpp", 7 | "initializer_list": "cpp", 8 | "string_view": "cpp", 9 | "*.ipp": "cpp", 10 | "sn76496.h": "c", 11 | "*.tcc": "c", 12 | "streambuf": "c", 13 | "istream": "cpp", 14 | "optional": "cpp", 15 | "ostream": "cpp", 16 | "ratio": "cpp", 17 | "system_error": "cpp", 18 | "type_traits": "cpp", 19 | "condition_variable": "cpp", 20 | "future": "cpp", 21 | "chrono": "c", 22 | "utility": "cpp", 23 | "unordered_set": "cpp", 24 | "fstream": "cpp", 25 | "sstream": "cpp", 26 | "thread": "cpp", 27 | "tuple": "cpp" 28 | } 29 | } -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: M5Stack Release CI 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-18.04 11 | steps: 12 | - uses: actions/checkout@v1 13 | with: 14 | submodules: recursive 15 | 16 | - name: esp-idf Toolchain Setup 17 | run: | 18 | sudo apt-get install gcc git wget make libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-cryptography python-future 19 | wget https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz 20 | tar zxvf xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz 21 | 22 | - name: Build 23 | run: | 24 | export PATH=$(pwd)/xtensa-esp32-elf/bin:${PATH} 25 | export IDF_PATH=$(pwd)/esp-idf 26 | python -m pip install --user -r $IDF_PATH/requirements.txt 27 | make 28 | 29 | - name: Archive 30 | run: | 31 | tar zcvf release.tar.gz \ 32 | build/ota_data_initial.bin \ 33 | build/bootloader/bootloader.bin \ 34 | build/m5stack-synth-emulation.bin \ 35 | build/partitions.bin \ 36 | vgm/sn76489.vgm \ 37 | vgm/ym2612.vgm 38 | 39 | - uses: ncipollo/release-action@v1 40 | with: 41 | artifacts: "release.tar.gz" 42 | token: ${{ secrets.GITHUB_TOKEN }} 43 | -------------------------------------------------------------------------------- /components/synth/src/mamedef.h: -------------------------------------------------------------------------------- 1 | #ifndef __MAMEDEF_H__ 2 | #define __MAMEDEF_H__ 3 | 4 | // typedefs to use MAME's (U)INTxx types (copied from MAME\src\ods\odscomm.h) 5 | /* 8-bit values */ 6 | typedef unsigned char UINT8; 7 | typedef signed char INT8; 8 | 9 | /* 16-bit values */ 10 | typedef unsigned short UINT16; 11 | typedef signed short INT16; 12 | 13 | /* 32-bit values */ 14 | #ifndef _WINDOWS_H 15 | typedef unsigned int UINT32; 16 | typedef signed int INT32; 17 | #endif 18 | 19 | /* 64-bit values */ 20 | #ifndef _WINDOWS_H 21 | #ifdef _MSC_VER 22 | typedef signed __int64 INT64; 23 | typedef unsigned __int64 UINT64; 24 | #else 25 | __extension__ typedef unsigned long long UINT64; 26 | __extension__ typedef signed long long INT64; 27 | #endif 28 | #endif 29 | 30 | /* offsets and addresses are 32-bit (for now...) */ 31 | typedef UINT32 offs_t; 32 | 33 | /* stream_sample_t is used to represent a single sample in a sound stream */ 34 | typedef INT32 stream_sample_t; 35 | 36 | #if defined(VGM_BIG_ENDIAN) 37 | #define BYTE_XOR_BE(x) (x) 38 | #elif defined(VGM_LITTLE_ENDIAN) 39 | #define BYTE_XOR_BE(x) ((x) ^ 0x01) 40 | #else 41 | // don't define BYTE_XOR_BE so that it throws an error when compiling 42 | #endif 43 | 44 | #if defined(_MSC_VER) 45 | //#define INLINE static __forceinline 46 | #define INLINE static __inline 47 | #elif defined(__GNUC__) 48 | #define INLINE static __inline__ 49 | #else 50 | #define INLINE static inline 51 | #endif 52 | #ifndef M_PI 53 | #define M_PI 3.14159265358979323846 54 | #endif 55 | 56 | #ifdef _DEBUG 57 | #define logerror printf 58 | #else 59 | #define logerror 60 | #endif 61 | 62 | extern stream_sample_t* DUMMYBUF[]; 63 | 64 | typedef void (*SRATE_CALLBACK)(void*, UINT32); 65 | 66 | #endif // __MAMEDEF_H__ 67 | -------------------------------------------------------------------------------- /components/synth/src/panning.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "panning.h" 4 | 5 | #ifndef PI 6 | #define PI 3.14159265359 7 | #endif 8 | #ifndef SQRT2 9 | #define SQRT2 1.414213562 10 | #endif 11 | #define RANGE 512 12 | 13 | //----------------------------------------------------------------- 14 | // Set the panning values for the two stereo channels (L,R) 15 | // for a position -256..0..256 L..C..R 16 | //----------------------------------------------------------------- 17 | void calc_panning(float channels[2], int position) 18 | { 19 | if ( position > RANGE / 2 ) 20 | position = RANGE / 2; 21 | else if ( position < -RANGE / 2 ) 22 | position = -RANGE / 2; 23 | position += RANGE / 2; // make -256..0..256 -> 0..256..512 24 | 25 | // Equal power law: equation is 26 | // right = sin( position / range * pi / 2) * sqrt( 2 ) 27 | // left is equivalent to right with position = range - position 28 | // position is in the range 0 .. RANGE 29 | // RANGE / 2 = centre, result = 1.0f 30 | channels[1] = (float)( sin( (double)position / RANGE * PI / 2 ) * SQRT2 ); 31 | position = RANGE - position; 32 | channels[0] = (float)( sin( (double)position / RANGE * PI / 2 ) * SQRT2 ); 33 | } 34 | 35 | //----------------------------------------------------------------- 36 | // Reset the panning values to the centre position 37 | //----------------------------------------------------------------- 38 | void centre_panning(float channels[2]) 39 | { 40 | channels[0] = channels[1] = 1.0f; 41 | } 42 | 43 | /*//----------------------------------------------------------------- 44 | // Generate a stereo position in the range 0..RANGE 45 | // with Gaussian distribution, mean RANGE/2, S.D. RANGE/5 46 | //----------------------------------------------------------------- 47 | int random_stereo() 48 | { 49 | int n = (int)(RANGE/2 + gauss_rand() * (RANGE * 0.2) ); 50 | if ( n > RANGE ) n = RANGE; 51 | if ( n < 0 ) n = 0; 52 | return n; 53 | } 54 | 55 | //----------------------------------------------------------------- 56 | // Generate a Gaussian random number with mean 0, variance 1 57 | // Copied from an ancient C newsgroup FAQ 58 | //----------------------------------------------------------------- 59 | double gauss_rand() 60 | { 61 | static double V1, V2, S; 62 | static int phase = 0; 63 | double X; 64 | 65 | if(phase == 0) { 66 | do { 67 | double U1 = (double)rand() / RAND_MAX; 68 | double U2 = (double)rand() / RAND_MAX; 69 | 70 | V1 = 2 * U1 - 1; 71 | V2 = 2 * U2 - 1; 72 | S = V1 * V1 + V2 * V2; 73 | } while(S >= 1 || S == 0); 74 | 75 | X = V1 * sqrt(-2 * log(S) / S); 76 | } else 77 | X = V2 * sqrt(-2 * log(S) / S); 78 | 79 | phase = 1 - phase; 80 | 81 | return X; 82 | }*/ 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # m5stack-synth-emulation 2 | 3 | GENESIS/MEGADRIVE(YM2612+SN76489) VGM player on ESP32/M5Stack 4 | 5 | ## Demo 6 | 7 | ![](https://raw.githubusercontent.com/h1romas4/m5stack-synth-emulation/master/assets/m5stack-synth-02.jpg) 8 | 9 | [https://www.youtube.com/watch?v=dunNtkFS8gc](https://www.youtube.com/watch?v=dunNtkFS8gc) 10 | 11 | ## Require 12 | 13 | * M5Stack 14 | * [esp32-idf toolchain setup](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/index.html#setup-toolchain) 15 | 16 | ``` 17 | $ xtensa-esp32-elf-gcc -v 18 | gcc version 5.2.0 (crosstool-NG crosstool-ng-1.22.0-80-g6c4433a) 19 | ``` 20 | 21 | ## Build 22 | 23 | ![](https://github.com/h1romas4/m5stack-synth-emulation/workflows/M5Stack%20CI/badge.svg) 24 | 25 | **Compile** 26 | 27 | ``` 28 | git clone --recursive https://github.com/h1romas4/m5stack-synth-emulation.git 29 | cd m5stack-synth-emulation 30 | # This repository includes eps-idf v3.2.3 31 | export IDF_PATH=$(pwd)/esp-idf 32 | make 33 | ``` 34 | 35 | **Upload sample VGM file to M5Stack flash** 36 | 37 | ``` 38 | ./flashrom.sh vgm/ym2612.vgm 39 | ``` 40 | 41 | **Play music** 42 | 43 | ``` 44 | make flash monitor 45 | ``` 46 | 47 | **Create VGM file** 48 | 49 | * [mml2vgm](https://github.com/kuma4649/mml2vgm) by [kumatan](https://github.com/kuma4649) san 50 | * [mucomMD2vgm](https://github.com/kuma4649/mucomMD2vgm) by [kumatan](https://github.com/kuma4649) san 51 | 52 | ## Binary release 53 | 54 | Extract [release.tar.gz](https://github.com/h1romas4/m5stack-synth-emulation/releases) and Assign the binary to the following address: 55 | 56 | |address|module| 57 | |-|-| 58 | |`0x1000`|`build/bootloader/bootloader.bin`| 59 | |`0x8000`|`build/partitions.bin`| 60 | |`0xe000`|`build/ota_data_initial.bin`| 61 | |`0x10000`|`build/m5stack-synth-emulation.bin`| 62 | |`0x211000`|`vgm/ym2612.vgm` or `vgm/sn76489.vgm`| 63 | 64 | ``` 65 | python ${IDF_PATH}/components/esptool_py/esptool/esptool.py \ 66 | --chip esp32 \ 67 | --port \ 68 | --baud 921600 \ 69 | --before default_reset \ 70 | --after hard_reset write_flash -z \ 71 | --flash_mode dio --flash_freq 80m \ 72 | --flash_size detect \ 73 | 0x1000 ./build/bootloader/bootloader.bin \ 74 | 0x8000 ./build/partitions.bin \ 75 | 0xe000 ./build/ota_data_initial.bin \ 76 | 0x10000 ./build/m5stack-synth-emulation.bin \ 77 | 0x211000 ./vgm/ym2612.vgm 78 | ``` 79 | 80 | ## Dependencies 81 | 82 | |name|version| 83 | |-|-| 84 | |[esp-idf](https://docs.espressif.com/projects/esp-idf/en/v3.2.3/get-started/index.html)|v3.2.3| 85 | |[esp32-arduino](https://github.com/espressif/arduino-esp32)|1.0.4| 86 | |[m5stack](https://github.com/m5stack/M5Stack)|0.2.9| 87 | 88 | ## License 89 | 90 | [GNU General Public License v2.0](https://github.com/h1romas4/m5stack-synth-emulation/blob/master/LICENSE.txt) 91 | 92 | ## Thanks! 93 | 94 | * [sn76489.c](https://github.com/vgmrips/vgmplay/blob/master/VGMPlay/chips/sn76489.c) 95 | * [ym2612.cpp](https://github.com/lutris/gens/blob/master/src/gens/gens_core/sound/ym2612.cpp) 96 | -------------------------------------------------------------------------------- /components/synth/src/sn76489.h: -------------------------------------------------------------------------------- 1 | #ifndef _SN76489_H_ 2 | #define _SN76489_H_ 3 | 4 | // all these defines are defined in mamedef.h, but GCC's #ifdef doesn't seem to know typedefs 5 | /*#ifndef INT32 6 | #define INT32 signed long 7 | #endif 8 | #ifndef UINT16 9 | #define UINT16 unsigned short 10 | #endif 11 | #ifndef INT16 12 | #define INT16 signed short 13 | #endif 14 | #ifndef INT8 15 | #define INT8 signed char 16 | #endif*/ 17 | #ifndef uint8 18 | #define uint8 signed char 19 | #endif 20 | 21 | 22 | /*#define MAX_SN76489 4*/ 23 | 24 | /* 25 | More testing is needed to find and confirm feedback patterns for 26 | SN76489 variants and compatible chips. 27 | */ 28 | enum feedback_patterns { 29 | FB_BBCMICRO = 0x8005, /* Texas Instruments TMS SN76489N (original) from BBC Micro computer */ 30 | FB_SC3000 = 0x0006, /* Texas Instruments TMS SN76489AN (rev. A) from SC-3000H computer */ 31 | FB_SEGAVDP = 0x0009, /* SN76489 clone in Sega's VDP chips (315-5124, 315-5246, 315-5313, Game Gear) */ 32 | }; 33 | 34 | enum sr_widths { 35 | SRW_SC3000BBCMICRO = 15, 36 | SRW_SEGAVDP = 16 37 | }; 38 | 39 | enum volume_modes { 40 | VOL_TRUNC = 0, /* Volume levels 13-15 are identical */ 41 | VOL_FULL = 1, /* Volume levels 13-15 are unique */ 42 | }; 43 | 44 | enum mute_values { 45 | MUTE_ALLOFF = 0, /* All channels muted */ 46 | MUTE_TONE1 = 1, /* Tone 1 mute control */ 47 | MUTE_TONE2 = 2, /* Tone 2 mute control */ 48 | MUTE_TONE3 = 4, /* Tone 3 mute control */ 49 | MUTE_NOISE = 8, /* Noise mute control */ 50 | MUTE_ALLON = 15, /* All channels enabled */ 51 | }; 52 | 53 | typedef struct 54 | { 55 | int Mute; // per-channel muting 56 | int BoostNoise; // double noise volume when non-zero 57 | 58 | /* Variables */ 59 | float Clock; 60 | float dClock; 61 | int PSGStereo; 62 | int NumClocksForSample; 63 | int WhiteNoiseFeedback; 64 | int SRWidth; 65 | 66 | /* PSG registers: */ 67 | int Registers[8]; /* Tone, vol x4 */ 68 | int LatchedRegister; 69 | int NoiseShiftRegister; 70 | int NoiseFreq; /* Noise channel signal generator frequency */ 71 | 72 | /* Output calculation variables */ 73 | int ToneFreqVals[4]; /* Frequency register values (counters) */ 74 | int ToneFreqPos[4]; /* Frequency channel flip-flops */ 75 | int Channels[4]; /* Value of each channel, before stereo is applied */ 76 | float IntermediatePos[4]; /* intermediate values used at boundaries between + and - (does not need double accuracy)*/ 77 | 78 | float panning[4][2]; /* fake stereo */ 79 | 80 | int NgpFlags; /* bit 7 - NGP Mode on/off, bit 0 - is 2nd NGP chip */ 81 | void* NgpChip2; 82 | } SN76489_Context; 83 | 84 | /* Function prototypes */ 85 | SN76489_Context* SN76489_Init(int PSGClockValue, int SamplingRate); 86 | void SN76489_Reset(SN76489_Context* chip); 87 | void SN76489_Shutdown(SN76489_Context* chip); 88 | void SN76489_Config(SN76489_Context* chip, /*int mute,*/ int feedback, int sw_width, int boost_noise); 89 | /* 90 | void SN76489_SetContext(SN76489_Context* chip, uint8 *data); 91 | void SN76489_GetContext(SN76489_Context* chip, uint8 *data); 92 | uint8 *SN76489_GetContextPtr(int chip); 93 | int SN76489_GetContextSize(void);*/ 94 | void SN76489_Write(SN76489_Context* chip, int data); 95 | void SN76489_GGStereoWrite(SN76489_Context* chip, int data); 96 | //void SN76489_Update(SN76489_Context* chip, INT16 **buffer, int length); 97 | void SN76489_Update(SN76489_Context* chip, int **buffer, int length); 98 | 99 | /* Non-standard getters and setters */ 100 | //int SN76489_GetMute(SN76489_Context* chip); 101 | void SN76489_SetMute(SN76489_Context* chip, int val); 102 | 103 | void SN76489_SetPanning(SN76489_Context* chip, int ch0, int ch1, int ch2, int ch3); 104 | 105 | /* and a non-standard data getter */ 106 | //void SN76489_UpdateOne(SN76489_Context* chip, int *l, int *r); 107 | 108 | #endif /* _SN76489_H_ */ 109 | -------------------------------------------------------------------------------- /components/synth/src/ym2612.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Gens: Yamaha YM2612 FM synthesis chip emulator. * 3 | * * 4 | * Copyright (c) 1999-2002 by Stéphane Dallongeville * 5 | * Copyright (c) 2003-2004 by Stéphane Akhoun * 6 | * Copyright (c) 2008-2009 by David Korth * 7 | * * 8 | * This program is free software; you can redistribute it and/or modify it * 9 | * under the terms of the GNU General Public License as published by the * 10 | * Free Software Foundation; either version 2 of the License, or (at your * 11 | * option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, but * 14 | * WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 16 | * GNU General Public License for more details. * 17 | * * 18 | * You should have received a copy of the GNU General Public License along * 19 | * with this program; if not, write to the Free Software Foundation, Inc., * 20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 21 | ***************************************************************************/ 22 | 23 | #ifndef GENS_YM2612_HPP 24 | #define GENS_YM2612_HPP 25 | 26 | #include 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | // Change it if you need to do long update 33 | #define MAX_UPDATE_LENGTH 4096 34 | 35 | // Gens always uses 16 bits sound (in 32 bits buffer) and do the convertion later if needed. 36 | #define OUTPUT_BITS 16 37 | 38 | typedef struct slot__ 39 | { 40 | unsigned int *DT; // paramètre detune 41 | int MUL; // paramètre "multiple de fréquence" 42 | int TL; // Total Level = volume lorsque l'enveloppe est au plus haut 43 | int TLL; // Total Level ajusted 44 | int SLL; // Sustin Level (ajusted) = volume où l'enveloppe termine sa première phase de régression 45 | int KSR_S; // Key Scale Rate Shift = facteur de prise en compte du KSL dans la variations de l'enveloppe 46 | int KSR; // Key Scale Rate = cette valeur est calculée par rapport à la fréquence actuelle, elle va influer 47 | // sur les différents paramètres de l'enveloppe comme l'attaque, le decay ... comme dans la réalité ! 48 | int SEG; // Type enveloppe SSG 49 | unsigned int *AR; // Attack Rate (table pointeur) = Taux d'attaque (AR[KSR]) 50 | unsigned int *DR; // Decay Rate (table pointeur) = Taux pour la régression (DR[KSR]) 51 | unsigned int *SR; // Sustin Rate (table pointeur) = Taux pour le maintien (SR[KSR]) 52 | unsigned int *RR; // Release Rate (table pointeur) = Taux pour le relâchement (RR[KSR]) 53 | int Fcnt; // Frequency Count = compteur-fréquence pour déterminer l'amplitude actuelle (SIN[Finc >> 16]) 54 | int Finc; // frequency step = pas d'incrémentation du compteur-fréquence 55 | // plus le pas est grand, plus la fréquence est aïgu (ou haute) 56 | int Ecurp; // Envelope current phase = cette variable permet de savoir dans quelle phase 57 | // de l'enveloppe on se trouve, par exemple phase d'attaque ou phase de maintenue ... 58 | // en fonction de la valeur de cette variable, on va appeler une fonction permettant 59 | // de mettre à jour l'enveloppe courante. 60 | int Ecnt; // Envelope counter = le compteur-enveloppe permet de savoir où l'on se trouve dans l'enveloppe 61 | int Einc; // Envelope step courant 62 | int Ecmp; // Envelope counter limite pour la prochaine phase 63 | int EincA; // Envelope step for Attack = pas d'incrémentation du compteur durant la phase d'attaque 64 | // cette valeur est égal à AR[KSR] 65 | int EincD; // Envelope step for Decay = pas d'incrémentation du compteur durant la phase de regression 66 | // cette valeur est égal à DR[KSR] 67 | int EincS; // Envelope step for Sustain = pas d'incrémentation du compteur durant la phase de maintenue 68 | // cette valeur est égal à SR[KSR] 69 | int EincR; // Envelope step for Release = pas d'incrémentation du compteur durant la phase de relâchement 70 | // cette valeur est égal à RR[KSR] 71 | int *OUTp; // pointeur of SLOT output = pointeur permettant de connecter la sortie de ce slot à l'entrée 72 | // d'un autre ou carrement à la sortie de la voie 73 | int INd; // input data of the slot = données en entrée du slot 74 | int ChgEnM; // Change envelop mask. 75 | int AMS; // AMS depth level of this SLOT = degré de modulation de l'amplitude par le LFO 76 | int AMSon; // AMS enable flag = drapeau d'activation de l'AMS 77 | 78 | } slot_; 79 | 80 | typedef struct channel__ 81 | { 82 | int S0_OUT[4]; // anciennes sorties slot 0 (pour le feed back) 83 | int Old_OUTd; // ancienne sortie de la voie (son brut) 84 | int OUTd; // sortie de la voie (son brut) 85 | int LEFT; // LEFT enable flag 86 | int RIGHT; // RIGHT enable flag 87 | int ALGO; // Algorythm = détermine les connections entre les opérateurs 88 | int FB; // shift count of self feed back = degré de "Feed-Back" du SLOT 1 (il est son unique entrée) 89 | int FMS; // Fréquency Modulation Sensitivity of channel = degré de modulation de la fréquence sur la voie par le LFO 90 | int AMS; // Amplitude Modulation Sensitivity of channel = degré de modulation de l'amplitude sur la voie par le LFO 91 | int FNUM[4]; // hauteur fréquence de la voie (+ 3 pour le mode spécial) 92 | int FOCT[4]; // octave de la voie (+ 3 pour le mode spécial) 93 | int KC[4]; // Key Code = valeur fonction de la fréquence (voir KSR pour les slots, KSR = KC >> KSR_S) 94 | slot_ SLOT[4]; // four slot.operators = les 4 slots de la voie 95 | int FFlag; // Frequency step recalculation flag 96 | } channel_; 97 | 98 | typedef struct ym2612__ 99 | { 100 | int Clock; // Horloge YM2612 101 | int Rate; // Sample Rate (11025/22050/44100) 102 | int TimerBase; // TimerBase calculation 103 | int status; // YM2612 Status (timer overflow) 104 | int OPNAadr; // addresse pour l'écriture dans l'OPN A (propre à l'émulateur) 105 | int OPNBadr; // addresse pour l'écriture dans l'OPN B (propre à l'émulateur) 106 | int LFOcnt; // LFO counter = compteur-fréquence pour le LFO 107 | int LFOinc; // LFO step counter = pas d'incrémentation du compteur-fréquence du LFO 108 | // plus le pas est grand, plus la fréquence est grande 109 | 110 | int TimerA; // timerA limit = valeur jusqu'à laquelle le timer A doit compter 111 | int TimerAL; 112 | int TimerAcnt; // timerA counter = valeur courante du Timer A 113 | int TimerB; // timerB limit = valeur jusqu'à laquelle le timer B doit compter 114 | int TimerBL; 115 | int TimerBcnt; // timerB counter = valeur courante du Timer B 116 | int Mode; // Mode actuel des voie 3 et 6 (normal / spécial) 117 | int DAC; // DAC enabled flag 118 | int DACdata; // DAC data 119 | 120 | int dummy; // MSVC++ enforces 8-byte alignment on doubles. This forces said alignment on gcc. 121 | double Frequence; // Fréquence de base, se calcul par rapport à l'horlage et au sample rate 122 | 123 | unsigned int Inter_Cnt; // Interpolation Counter 124 | unsigned int Inter_Step; // Interpolation Step 125 | channel_ CHANNEL[6]; // Les 6 voies du YM2612 126 | 127 | int REG[2][0x100]; // Sauvegardes des valeurs de tout les registres, c'est facultatif 128 | // cela nous rend le débuggage plus facile 129 | } ym2612_; 130 | 131 | /* Gens */ 132 | 133 | extern int YM2612_Enable; 134 | extern int YM2612_Improv; 135 | extern int DAC_Enable; 136 | extern int *YM_Buf[2]; 137 | extern int YM_Len; 138 | 139 | /* end */ 140 | 141 | int YM2612_Init(int clock, int rate, int interpolation); 142 | int YM2612_End(void); 143 | int YM2612_Reset(void); 144 | uint8_t YM2612_Read(void); 145 | int YM2612_Write(unsigned int adr, uint8_t data); 146 | void YM2612_Update(int **buf, int length); 147 | 148 | /* Gens */ 149 | 150 | void YM2612_DacAndTimers_Update(int **buffer, int length); 151 | void YM2612_Special_Update(void); 152 | int YM2612_Get_Reg(int regID); 153 | 154 | /* Savestate functionality. */ 155 | int YM2612_Save(unsigned char SAVE[0x200]); 156 | int YM2612_Restore(unsigned char SAVE[0x200]); 157 | 158 | /* GSX v7 savestate functionality. */ 159 | // struct _gsx_v7_ym2612; 160 | // int YM2612_Save_Full(struct _gsx_v7_ym2612 *save); 161 | // int YM2612_Restore_Full(struct _gsx_v7_ym2612 *save); 162 | 163 | void YM2612_ClearBuffer(int **buffer, int length); 164 | /* end */ 165 | 166 | #ifdef __cplusplus 167 | } 168 | #endif 169 | 170 | #endif /* GENS_YM2612_HPP */ 171 | -------------------------------------------------------------------------------- /main/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "nvs_flash.h" 3 | #include "esp_partition.h" 4 | #include 5 | #include "driver/i2s.h" 6 | #include "ym2612.hpp" 7 | extern "C" { 8 | #include "sn76489.h" 9 | } 10 | 11 | #define SAMPLING_RATE 44100 12 | #define FRAME_SIZE_MAX 2048 13 | 14 | #define STEREO 2 15 | #define MONO 0 16 | 17 | uint8_t *vgm; 18 | uint32_t vgmpos = 0x40; 19 | bool vgmend = false; 20 | uint32_t vgmloopoffset; 21 | uint32_t datpos; 22 | uint32_t pcmpos; 23 | uint32_t pcmoffset; 24 | 25 | uint32_t clock_sn76489; 26 | uint32_t clock_ym2612; 27 | 28 | SN76489_Context *sn76489; 29 | 30 | uint8_t *get_vgmdata() 31 | { 32 | uint8_t* data; 33 | const esp_partition_t* part; 34 | spi_flash_mmap_handle_t hrom; 35 | esp_err_t err; 36 | 37 | nvs_flash_init(); 38 | 39 | part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_PHY, NULL); 40 | if (part == 0) { 41 | printf("Couldn't find vgm part!\n"); 42 | } 43 | 44 | err = esp_partition_mmap(part, 0, 0x1EF000, SPI_FLASH_MMAP_DATA, (const void**)&data, &hrom); 45 | if (err != ESP_OK) { 46 | printf("Couldn't map vgm part!\n"); 47 | } 48 | printf("read vgm data @%p\n", data); 49 | 50 | return (uint8_t *)data; 51 | } 52 | 53 | uint8_t get_vgm_ui8() 54 | { 55 | return vgm[vgmpos++]; 56 | } 57 | 58 | uint16_t get_vgm_ui16() 59 | { 60 | return get_vgm_ui8() + (get_vgm_ui8() << 8); 61 | } 62 | 63 | uint32_t get_vgm_ui32() 64 | { 65 | return get_vgm_ui8() + (get_vgm_ui8() << 8) + (get_vgm_ui8() << 16) + (get_vgm_ui8() << 24); 66 | } 67 | 68 | uint16_t parse_vgm() 69 | { 70 | uint8_t command; 71 | uint16_t wait = 0; 72 | uint8_t reg; 73 | uint8_t dat; 74 | 75 | command = get_vgm_ui8(); 76 | switch (command) { 77 | case 0x50: 78 | dat = get_vgm_ui8(); 79 | SN76489_Write(sn76489, dat); 80 | break; 81 | case 0x52: 82 | case 0x53: 83 | reg = get_vgm_ui8(); 84 | dat = get_vgm_ui8(); 85 | YM2612_Write(0 + ((command & 1) << 1), reg); 86 | YM2612_Write(1 + ((command & 1) << 1), dat); 87 | break; 88 | case 0x61: 89 | wait = get_vgm_ui16(); 90 | break; 91 | case 0x62: 92 | wait = 735; 93 | break; 94 | case 0x63: 95 | wait = 882; 96 | break; 97 | case 0x66: 98 | if(vgmloopoffset == 0) { 99 | vgmend = true; 100 | } else { 101 | vgmpos = vgmloopoffset; 102 | } 103 | break; 104 | case 0x67: 105 | get_vgm_ui8(); // 0x66 106 | get_vgm_ui8(); // 0x00 data type 107 | datpos = vgmpos + 4; 108 | vgmpos += get_vgm_ui32(); // size of data, in bytes 109 | break; 110 | case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: 111 | case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f: 112 | wait = (command & 0x0f) + 1; 113 | break; 114 | case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: 115 | case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f: 116 | wait = (command & 0x0f); 117 | YM2612_Write(0, 0x2a); 118 | YM2612_Write(1, vgm[datpos + pcmpos + pcmoffset]); 119 | pcmoffset++; 120 | break; 121 | case 0xe0: 122 | pcmpos = get_vgm_ui32(); 123 | pcmoffset = 0; 124 | break; 125 | default: 126 | printf("unknown cmd at 0x%x: 0x%x\n", vgmpos, vgm[vgmpos]); 127 | vgmpos++; 128 | break; 129 | } 130 | 131 | return wait; 132 | } 133 | 134 | static const i2s_port_t i2s_num = I2S_NUM_0; // i2s port number 135 | 136 | void init_dac(void) 137 | { 138 | i2s_config_t i2s_config = { 139 | .mode = static_cast(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN), 140 | .sample_rate = SAMPLING_RATE, 141 | .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, 142 | .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, 143 | .communication_format = static_cast(I2S_COMM_FORMAT_I2S_MSB), 144 | .intr_alloc_flags = 0, 145 | .dma_buf_count = 16, 146 | .dma_buf_len = 512, 147 | .use_apll = false, 148 | .tx_desc_auto_clear = true, 149 | .fixed_mclk = 0 150 | }; 151 | 152 | i2s_driver_install(i2s_num, &i2s_config, 0, NULL); 153 | i2s_set_pin(i2s_num, NULL); 154 | } 155 | 156 | // The setup routine runs once when M5Stack starts up 157 | void setup() 158 | { 159 | // Initialize the M5Stack object 160 | M5.begin(); 161 | 162 | // Initialize 163 | M5.Lcd.fillScreen(BLACK); 164 | M5.Lcd.print("MEGADRIVE/GENESIS sound emulation by M5Stack.\n\n"); 165 | 166 | // Load vgm data 167 | vgm = get_vgmdata(); 168 | 169 | // read vgm header 170 | vgmpos = 0x0C; clock_sn76489 = get_vgm_ui32(); 171 | vgmpos = 0x2C; clock_ym2612 = get_vgm_ui32(); 172 | vgmpos = 0x1c; vgmloopoffset = get_vgm_ui32(); 173 | vgmpos = 0x34; vgmpos = 0x34 + get_vgm_ui32(); 174 | 175 | if(clock_ym2612 == 0) clock_ym2612 = 7670453; 176 | if(clock_sn76489 == 0) clock_sn76489 = 3579545; 177 | 178 | printf("clock_sn76489 : %d\n", clock_sn76489); 179 | printf("clock_ym2612 : %d\n", clock_ym2612); 180 | printf("vgmpos : %x\n", vgmpos); 181 | 182 | // init sound chip 183 | sn76489 = SN76489_Init(clock_sn76489, SAMPLING_RATE); 184 | SN76489_Reset(sn76489); 185 | YM2612_Init(clock_ym2612, SAMPLING_RATE, 0); 186 | 187 | // init internal DAC 188 | init_dac(); 189 | } 190 | 191 | short audio_write_sound_stereo(int sample32) 192 | { 193 | short sample16; 194 | 195 | if (sample32 < -0x7FFF) { 196 | sample16 = -0x7FFF; 197 | } else if (sample32 > 0x7FFF) { 198 | sample16 = 0x7FFF; 199 | } else { 200 | sample16 = (short)(sample32); 201 | } 202 | 203 | // for I2S_MODE_DAC_BUILT_IN 204 | sample16 = sample16 ^ 0x8000U; 205 | 206 | return sample16; 207 | } 208 | 209 | // The loop routine runs over and over again forever 210 | void loop() 211 | { 212 | size_t bytes_written = 0; 213 | 214 | uint16_t frame_size; 215 | uint32_t frame_all = 0; 216 | 217 | // malloc sound buffer 218 | int **buflr; 219 | 220 | buflr = (int **)malloc(sizeof(int *) * STEREO); 221 | buflr[0] = (int *)heap_caps_malloc(FRAME_SIZE_MAX * sizeof(int), MALLOC_CAP_8BIT); 222 | if(buflr[0] == NULL) printf("pcm buffer0 alloc fail.\n"); 223 | buflr[1] = (int *)heap_caps_malloc(FRAME_SIZE_MAX * sizeof(int), MALLOC_CAP_8BIT); 224 | if(buflr[1] == NULL) printf("pcm buffer1 alloc fail.\n"); 225 | 226 | printf("last free memory8 %d\n", heap_caps_get_free_size(MALLOC_CAP_8BIT)); 227 | 228 | // free memory 229 | M5.Lcd.printf("frame max size: %d\n", FRAME_SIZE_MAX); 230 | M5.Lcd.printf("free memory: %d byte\n", heap_caps_get_free_size(MALLOC_CAP_8BIT)); 231 | 232 | int32_t last_frame_size; 233 | int32_t update_frame_size; 234 | do { 235 | frame_size = parse_vgm(); 236 | last_frame_size = frame_size; 237 | do { 238 | if(last_frame_size > FRAME_SIZE_MAX) { 239 | update_frame_size = FRAME_SIZE_MAX; 240 | } else { 241 | update_frame_size = last_frame_size; 242 | } 243 | // get sampling 244 | SN76489_Update(sn76489, (int **)buflr, update_frame_size); 245 | YM2612_Update((int **)buflr, update_frame_size); 246 | YM2612_DacAndTimers_Update((int **)buflr, update_frame_size); 247 | for(uint32_t i = 0; i < update_frame_size; i++) { 248 | short d[STEREO]; 249 | d[0] = audio_write_sound_stereo(buflr[0][i]); 250 | d[1] = audio_write_sound_stereo(buflr[1][i]); 251 | i2s_write((i2s_port_t)i2s_num, d, sizeof(short) * STEREO, &bytes_written, portMAX_DELAY); 252 | } 253 | last_frame_size -= FRAME_SIZE_MAX; 254 | } while(last_frame_size > 0); 255 | frame_all += frame_size; 256 | } while(!vgmend); 257 | 258 | free(buflr[0]); 259 | free(buflr[1]); 260 | free(buflr); 261 | 262 | YM2612_End(); 263 | SN76489_Shutdown(sn76489); 264 | 265 | M5.Lcd.printf("\ntotal frame: %d %d\n", frame_all, frame_all / SAMPLING_RATE); 266 | 267 | i2s_driver_uninstall((i2s_port_t)i2s_num); //stop & destroy i2s driver 268 | 269 | M5.update(); 270 | 271 | while(true) { 272 | asm volatile("nop\n\t nop\n\t nop\n\t nop\n\t"); 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /components/synth/src/sn76489.c: -------------------------------------------------------------------------------- 1 | /* 2 | SN76489 emulation 3 | by Maxim in 2001 and 2002 4 | converted from my original Delphi implementation 5 | 6 | I'm a C newbie so I'm sure there are loads of stupid things 7 | in here which I'll come back to some day and redo 8 | 9 | Includes: 10 | - Super-high quality tone channel "oversampling" by calculating fractional positions on transitions 11 | - Noise output pattern reverse engineered from actual SMS output 12 | - Volume levels taken from actual SMS output 13 | 14 | 07/08/04 Charles MacDonald 15 | Modified for use with SMS Plus: 16 | - Added support for multiple PSG chips. 17 | - Added reset/config/update routines. 18 | - Added context management routines. 19 | - Removed SN76489_GetValues(). 20 | - Removed some unused variables. 21 | */ 22 | 23 | #include // malloc/free 24 | #include // for FLT_MIN 25 | #include // for memcpy 26 | #include "mamedef.h" 27 | #include "sn76489.h" 28 | #include "panning.h" 29 | 30 | #define NoiseInitialState 0x8000 /* Initial state of shift register */ 31 | #define PSG_CUTOFF 0x6 /* Value below which PSG does not output */ 32 | 33 | static const int PSGVolumeValues[16] = { 34 | /* // These values are taken from a real SMS2's output 35 | {892,892,892,760,623,497,404,323,257,198,159,123,96,75,60,0}, // I can't remember why 892... :P some scaling I did at some point 36 | // these values are true volumes for 2dB drops at each step (multiply previous by 10^-0.1) 37 | 1516,1205,957,760,603,479,381,303,240,191,152,120,96,76,60,0*/ 38 | // The MAME core uses 0x2000 as maximum volume (0x1000 for bipolar output) 39 | 4096, 3254, 2584, 2053, 1631, 1295, 1029, 817, 649, 516, 410, 325, 258, 205, 163, 0 40 | }; 41 | 42 | /*static SN76489_Context SN76489[MAX_SN76489];*/ 43 | static SN76489_Context* LastChipInit = NULL; 44 | //static unsigned short int FNumLimit; 45 | 46 | 47 | SN76489_Context* SN76489_Init( int PSGClockValue, int SamplingRate) 48 | { 49 | int i; 50 | SN76489_Context* chip = (SN76489_Context*)malloc(sizeof(SN76489_Context)); 51 | if(chip) 52 | { 53 | chip->dClock=(float)(PSGClockValue & 0x7FFFFFF)/16/SamplingRate; 54 | 55 | SN76489_SetMute(chip, MUTE_ALLON); 56 | SN76489_Config(chip, /*MUTE_ALLON,*/ FB_SEGAVDP, SRW_SEGAVDP, 1); 57 | 58 | for( i = 0; i <= 3; i++ ) 59 | centre_panning(chip->panning[i]); 60 | //SN76489_Reset(chip); 61 | 62 | if ((PSGClockValue & 0x80000000) && LastChipInit != NULL) 63 | { 64 | // Activate special NeoGeoPocket Mode 65 | LastChipInit->NgpFlags = 0x80 | 0x00; 66 | chip->NgpFlags = 0x80 | 0x01; 67 | chip->NgpChip2 = LastChipInit; 68 | LastChipInit->NgpChip2 = chip; 69 | LastChipInit = NULL; 70 | } 71 | else 72 | { 73 | chip->NgpFlags = 0x00; 74 | chip->NgpChip2 = NULL; 75 | LastChipInit = chip; 76 | } 77 | } 78 | return chip; 79 | } 80 | 81 | void SN76489_Reset(SN76489_Context* chip) 82 | { 83 | int i; 84 | 85 | chip->PSGStereo = 0xFF; 86 | 87 | for( i = 0; i <= 3; i++ ) 88 | { 89 | /* Initialise PSG state */ 90 | chip->Registers[2*i] = 1; /* tone freq=1 */ 91 | chip->Registers[2*i+1] = 0xf; /* vol=off */ 92 | chip->NoiseFreq = 0x10; 93 | 94 | /* Set counters to 0 */ 95 | chip->ToneFreqVals[i] = 0; 96 | 97 | /* Set flip-flops to 1 */ 98 | chip->ToneFreqPos[i] = 1; 99 | 100 | /* Set intermediate positions to do-not-use value */ 101 | chip->IntermediatePos[i] = FLT_MIN; 102 | 103 | /* Set panning to centre */ 104 | //centre_panning( chip->panning[i] ); 105 | } 106 | 107 | chip->LatchedRegister = 0; 108 | 109 | /* Initialise noise generator */ 110 | chip->NoiseShiftRegister = NoiseInitialState; 111 | 112 | /* Zero clock */ 113 | chip->Clock = 0; 114 | } 115 | 116 | void SN76489_Shutdown(SN76489_Context* chip) 117 | { 118 | free(chip); 119 | } 120 | 121 | void SN76489_Config(SN76489_Context* chip, /*int mute,*/ int feedback, int sr_width, int boost_noise) 122 | { 123 | //chip->Mute = mute; 124 | chip->WhiteNoiseFeedback = feedback; 125 | chip->SRWidth = sr_width; 126 | } 127 | 128 | /* 129 | void SN76489_SetContext(int which, uint8 *data) 130 | { 131 | memcpy( &SN76489[which], data, sizeof(SN76489_Context) ); 132 | } 133 | 134 | void SN76489_GetContext(int which, uint8 *data) 135 | { 136 | memcpy( data, &SN76489[which], sizeof(SN76489_Context) ); 137 | } 138 | 139 | uint8 *SN76489_GetContextPtr(int which) 140 | { 141 | return (uint8 *)&SN76489[which]; 142 | } 143 | 144 | int SN76489_GetContextSize(void) 145 | { 146 | return sizeof(SN76489_Context); 147 | } 148 | */ 149 | void SN76489_Write(SN76489_Context* chip, int data) 150 | { 151 | if ( data & 0x80 ) 152 | { 153 | /* Latch/data byte %1 cc t dddd */ 154 | chip->LatchedRegister = ( data >> 4 ) & 0x07; 155 | chip->Registers[chip->LatchedRegister] = 156 | ( chip->Registers[chip->LatchedRegister] & 0x3f0 ) /* zero low 4 bits */ 157 | | ( data & 0xf ); /* and replace with data */ 158 | } else { 159 | /* Data byte %0 - dddddd */ 160 | if ( !( chip->LatchedRegister % 2 ) && ( chip->LatchedRegister < 5 ) ) 161 | /* Tone register */ 162 | chip->Registers[chip->LatchedRegister] = 163 | ( chip->Registers[chip->LatchedRegister] & 0x00f) /* zero high 6 bits */ 164 | | ( ( data & 0x3f ) << 4 ); /* and replace with data */ 165 | else 166 | /* Other register */ 167 | chip->Registers[chip->LatchedRegister]=data&0x0f; /* Replace with data */ 168 | } 169 | switch (chip->LatchedRegister) { 170 | case 0: 171 | case 2: 172 | case 4: /* Tone channels */ 173 | if ( chip->Registers[chip->LatchedRegister] == 0 ) 174 | chip->Registers[chip->LatchedRegister] = 1; /* Zero frequency changed to 1 to avoid div/0 */ 175 | break; 176 | case 6: /* Noise */ 177 | chip->NoiseShiftRegister = NoiseInitialState; /* reset shift register */ 178 | chip->NoiseFreq = 0x10 << ( chip->Registers[6] & 0x3 ); /* set noise signal generator frequency */ 179 | break; 180 | } 181 | } 182 | 183 | void SN76489_GGStereoWrite(SN76489_Context* chip, int data) 184 | { 185 | chip->PSGStereo=data; 186 | } 187 | 188 | //void SN76489_Update(SN76489_Context* chip, INT16 **buffer, int length) 189 | void SN76489_Update(SN76489_Context* chip, int **buffer, int length) 190 | { 191 | int i, j; 192 | int NGPMode; 193 | SN76489_Context* chip2; 194 | SN76489_Context* chip_t; 195 | SN76489_Context* chip_n; 196 | 197 | NGPMode = (chip->NgpFlags >> 7) & 0x01; 198 | if (! NGPMode) 199 | { 200 | chip2 = NULL; 201 | chip_t = chip_n = chip; 202 | } 203 | else 204 | { 205 | chip2 = (SN76489_Context*)chip->NgpChip2; 206 | if (! (chip->NgpFlags & 0x01)) 207 | { 208 | chip_t = chip; 209 | chip_n = chip2; 210 | } 211 | else 212 | { 213 | chip_t = chip2; 214 | chip_n = chip; 215 | } 216 | } 217 | 218 | for( j = 0; j < length; j++ ) 219 | { 220 | /* Tone channels */ 221 | for ( i = 0; i <= 2; ++i ) 222 | if ( (chip_t->Mute >> i) & 1 ) 223 | { 224 | if ( chip_t->IntermediatePos[i] != FLT_MIN ) 225 | /* Intermediate position (antialiasing) */ 226 | chip->Channels[i] = (short)( PSGVolumeValues[chip->Registers[2 * i + 1]] * chip_t->IntermediatePos[i] ); 227 | else 228 | /* Flat (no antialiasing needed) */ 229 | chip->Channels[i]= PSGVolumeValues[chip->Registers[2 * i + 1]] * chip_t->ToneFreqPos[i]; 230 | } 231 | else 232 | /* Muted channel */ 233 | chip->Channels[i] = 0; 234 | 235 | /* Noise channel */ 236 | if ( (chip_t->Mute >> 3) & 1 ) 237 | { 238 | //chip->Channels[3] = PSGVolumeValues[chip->Registers[7]] * ( chip_n->NoiseShiftRegister & 0x1 ) * 2; /* double noise volume */ 239 | // Now the noise is bipolar, too. -Valley Bell 240 | chip->Channels[3] = PSGVolumeValues[chip->Registers[7]] * (( chip_n->NoiseShiftRegister & 0x1 ) * 2 - 1); 241 | // due to the way the white noise works here, it seems twice as loud as it should be 242 | if (chip->Registers[6] & 0x4 ) 243 | chip->Channels[3] >>= 1; 244 | } 245 | else 246 | chip->Channels[i] = 0; 247 | 248 | // Build stereo result into buffer 249 | buffer[0][j] = 0; 250 | buffer[1][j] = 0; 251 | if (! chip->NgpFlags) 252 | { 253 | // For all 4 channels 254 | for ( i = 0; i <= 3; ++i ) 255 | { 256 | if ( ( ( chip->PSGStereo >> i ) & 0x11 ) == 0x11 ) 257 | { 258 | // no GG stereo for this channel 259 | if ( chip->panning[i][0] == 1.0f ) 260 | { 261 | buffer[0][j] += chip->Channels[i]; // left 262 | buffer[1][j] += chip->Channels[i]; // right 263 | } 264 | else 265 | { 266 | buffer[0][j] += (INT32)( chip->panning[i][0] * chip->Channels[i] ); // left 267 | buffer[1][j] += (INT32)( chip->panning[i][1] * chip->Channels[i] ); // right 268 | } 269 | } 270 | else 271 | { 272 | // GG stereo overrides panning 273 | buffer[0][j] += ( chip->PSGStereo >> (i+4) & 0x1 ) * chip->Channels[i]; // left 274 | buffer[1][j] += ( chip->PSGStereo >> i & 0x1 ) * chip->Channels[i]; // right 275 | } 276 | } 277 | } 278 | else 279 | { 280 | if (! (chip->NgpFlags & 0x01)) 281 | { 282 | // For all 3 tone channels 283 | for (i = 0; i < 3; i ++) 284 | { 285 | buffer[0][j] += (chip->PSGStereo >> (i+4) & 0x1 ) * chip ->Channels[i]; // left 286 | buffer[1][j] += (chip->PSGStereo >> i & 0x1 ) * chip2->Channels[i]; // right 287 | } 288 | } 289 | else 290 | { 291 | // noise channel 292 | i = 3; 293 | buffer[0][j] += (chip->PSGStereo >> (i+4) & 0x1 ) * chip2->Channels[i]; // left 294 | buffer[1][j] += (chip->PSGStereo >> i & 0x1 ) * chip ->Channels[i]; // right 295 | } 296 | } 297 | 298 | /* Increment clock by 1 sample length */ 299 | chip->Clock += chip->dClock; 300 | chip->NumClocksForSample = (int)chip->Clock; /* truncate */ 301 | chip->Clock -= chip->NumClocksForSample; /* remove integer part */ 302 | 303 | /* Decrement tone channel counters */ 304 | for ( i = 0; i <= 2; ++i ) 305 | chip->ToneFreqVals[i] -= chip->NumClocksForSample; 306 | 307 | /* Noise channel: match to tone2 or decrement its counter */ 308 | if ( chip->NoiseFreq == 0x80 ) 309 | chip->ToneFreqVals[3] = chip->ToneFreqVals[2]; 310 | else 311 | chip->ToneFreqVals[3] -= chip->NumClocksForSample; 312 | 313 | /* Tone channels: */ 314 | for ( i = 0; i <= 2; ++i ) { 315 | if ( chip->ToneFreqVals[i] <= 0 ) { /* If the counter gets below 0... */ 316 | if (chip->Registers[i*2]>=PSG_CUTOFF) { 317 | /* For tone-generating values, calculate how much of the sample is + and how much is - */ 318 | /* This is optimised into an even more confusing state than it was in the first place... */ 319 | chip->IntermediatePos[i] = ( chip->NumClocksForSample - chip->Clock + 2 * chip->ToneFreqVals[i] ) * chip->ToneFreqPos[i] / ( chip->NumClocksForSample + chip->Clock ); 320 | /* Flip the flip-flop */ 321 | chip->ToneFreqPos[i] = -chip->ToneFreqPos[i]; 322 | } else { 323 | /* stuck value */ 324 | chip->ToneFreqPos[i] = 1; 325 | chip->IntermediatePos[i] = FLT_MIN; 326 | } 327 | chip->ToneFreqVals[i] += chip->Registers[i*2] * ( chip->NumClocksForSample / chip->Registers[i*2] + 1 ); 328 | } 329 | else 330 | /* signal no antialiasing needed */ 331 | chip->IntermediatePos[i] = FLT_MIN; 332 | } 333 | 334 | /* Noise channel */ 335 | if ( chip->ToneFreqVals[3] <= 0 ) { 336 | /* If the counter gets below 0... */ 337 | /* Flip the flip-flop */ 338 | chip->ToneFreqPos[3] = -chip->ToneFreqPos[3]; 339 | if (chip->NoiseFreq != 0x80) 340 | /* If not matching tone2, decrement counter */ 341 | chip->ToneFreqVals[3] += chip->NoiseFreq * ( chip->NumClocksForSample / chip->NoiseFreq + 1 ); 342 | if (chip->ToneFreqPos[3] == 1) { 343 | /* On the positive edge of the square wave (only once per cycle) */ 344 | int Feedback; 345 | if ( chip->Registers[6] & 0x4 ) { 346 | /* White noise */ 347 | /* Calculate parity of fed-back bits for feedback */ 348 | switch (chip->WhiteNoiseFeedback) { 349 | /* Do some optimised calculations for common (known) feedback values */ 350 | case 0x0003: /* SC-3000, BBC %00000011 */ 351 | case 0x0009: /* SMS, GG, MD %00001001 */ 352 | /* If two bits fed back, I can do Feedback=(nsr & fb) && (nsr & fb ^ fb) */ 353 | /* since that's (one or more bits set) && (not all bits set) */ 354 | Feedback = ( ( chip->NoiseShiftRegister & chip->WhiteNoiseFeedback ) 355 | && ( (chip->NoiseShiftRegister & chip->WhiteNoiseFeedback ) ^ chip->WhiteNoiseFeedback ) ); 356 | break; 357 | default: 358 | /* Default handler for all other feedback values */ 359 | /* XOR fold bits into the final bit */ 360 | Feedback = chip->NoiseShiftRegister & chip->WhiteNoiseFeedback; 361 | Feedback ^= Feedback >> 8; 362 | Feedback ^= Feedback >> 4; 363 | Feedback ^= Feedback >> 2; 364 | Feedback ^= Feedback >> 1; 365 | Feedback &= 1; 366 | break; 367 | } 368 | } else /* Periodic noise */ 369 | Feedback=chip->NoiseShiftRegister&1; 370 | 371 | chip->NoiseShiftRegister=(chip->NoiseShiftRegister>>1) | (Feedback << (chip->SRWidth-1)); 372 | } 373 | } 374 | } 375 | } 376 | 377 | /*void SN76489_UpdateOne(SN76489_Context* chip, int *l, int *r) 378 | { 379 | INT16 tl,tr; 380 | INT16 *buff[2] = { &tl, &tr }; 381 | SN76489_Update( chip, buff, 1 ); 382 | *l = tl; 383 | *r = tr; 384 | }*/ 385 | 386 | 387 | /*int SN76489_GetMute(SN76489_Context* chip) 388 | { 389 | return chip->Mute; 390 | }*/ 391 | 392 | void SN76489_SetMute(SN76489_Context* chip, int val) 393 | { 394 | chip->Mute=val; 395 | } 396 | 397 | void SN76489_SetPanning(SN76489_Context* chip, int ch0, int ch1, int ch2, int ch3) 398 | { 399 | calc_panning( chip->panning[0], ch0 ); 400 | calc_panning( chip->panning[1], ch1 ); 401 | calc_panning( chip->panning[2], ch2 ); 402 | calc_panning( chip->panning[3], ch3 ); 403 | } 404 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /sdkconfig: -------------------------------------------------------------------------------- 1 | # 2 | # Automatically generated file; DO NOT EDIT. 3 | # Espressif IoT Development Framework Configuration 4 | # 5 | 6 | # 7 | # SDK tool configuration 8 | # 9 | CONFIG_TOOLPREFIX="xtensa-esp32-elf-" 10 | CONFIG_PYTHON="python" 11 | CONFIG_MAKE_WARN_UNDEFINED_VARIABLES=y 12 | 13 | # 14 | # Arduino Configuration 15 | # 16 | CONFIG_ENABLE_ARDUINO_DEPENDS=y 17 | CONFIG_AUTOSTART_ARDUINO=y 18 | CONFIG_ARDUINO_RUN_CORE0= 19 | CONFIG_ARDUINO_RUN_CORE1=y 20 | CONFIG_ARDUINO_RUN_NO_AFFINITY= 21 | CONFIG_ARDUINO_RUNNING_CORE=1 22 | CONFIG_ARDUINO_EVENT_RUN_CORE0= 23 | CONFIG_ARDUINO_EVENT_RUN_CORE1=y 24 | CONFIG_ARDUINO_EVENT_RUN_NO_AFFINITY= 25 | CONFIG_ARDUINO_EVENT_RUNNING_CORE=1 26 | CONFIG_ARDUINO_UDP_RUN_CORE0= 27 | CONFIG_ARDUINO_UDP_RUN_CORE1=y 28 | CONFIG_ARDUINO_UDP_RUN_NO_AFFINITY= 29 | CONFIG_ARDUINO_UDP_RUNNING_CORE=1 30 | CONFIG_DISABLE_HAL_LOCKS= 31 | 32 | # 33 | # Debug Log Configuration 34 | # 35 | CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_NONE= 36 | CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_ERROR= 37 | CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_WARN= 38 | CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_INFO= 39 | CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_DEBUG=y 40 | CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_VERBOSE= 41 | CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL=4 42 | CONFIG_ARDUHAL_LOG_COLORS= 43 | CONFIG_ARDUHAL_ESP_LOG= 44 | CONFIG_ARDUHAL_PARTITION_SCHEME_DEFAULT=y 45 | CONFIG_ARDUHAL_PARTITION_SCHEME_MINIMAL= 46 | CONFIG_ARDUHAL_PARTITION_SCHEME_NO_OTA= 47 | CONFIG_ARDUHAL_PARTITION_SCHEME_HUGE_APP= 48 | CONFIG_ARDUHAL_PARTITION_SCHEME_MIN_SPIFFS= 49 | CONFIG_ARDUHAL_PARTITION_SCHEME="default" 50 | CONFIG_AUTOCONNECT_WIFI= 51 | CONFIG_ARDUINO_SELECTIVE_COMPILATION= 52 | 53 | # 54 | # Bootloader config 55 | # 56 | CONFIG_LOG_BOOTLOADER_LEVEL_NONE= 57 | CONFIG_LOG_BOOTLOADER_LEVEL_ERROR= 58 | CONFIG_LOG_BOOTLOADER_LEVEL_WARN=y 59 | CONFIG_LOG_BOOTLOADER_LEVEL_INFO= 60 | CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG= 61 | CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE= 62 | CONFIG_LOG_BOOTLOADER_LEVEL=2 63 | CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y 64 | CONFIG_BOOTLOADER_FACTORY_RESET= 65 | CONFIG_BOOTLOADER_APP_TEST= 66 | CONFIG_BOOTLOADER_WDT_ENABLE=y 67 | CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE= 68 | CONFIG_BOOTLOADER_WDT_TIME_MS=9000 69 | 70 | # 71 | # Security features 72 | # 73 | CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT= 74 | CONFIG_SECURE_BOOT_ENABLED= 75 | CONFIG_FLASH_ENCRYPTION_ENABLED= 76 | 77 | # 78 | # Serial flasher config 79 | # 80 | CONFIG_ESPTOOLPY_PORT="/dev/ttyUSB0" 81 | CONFIG_ESPTOOLPY_BAUD_115200B= 82 | CONFIG_ESPTOOLPY_BAUD_230400B= 83 | CONFIG_ESPTOOLPY_BAUD_921600B=y 84 | CONFIG_ESPTOOLPY_BAUD_2MB= 85 | CONFIG_ESPTOOLPY_BAUD_OTHER= 86 | CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 87 | CONFIG_ESPTOOLPY_BAUD=921600 88 | CONFIG_ESPTOOLPY_COMPRESSED=y 89 | CONFIG_FLASHMODE_QIO= 90 | CONFIG_FLASHMODE_QOUT= 91 | CONFIG_FLASHMODE_DIO=y 92 | CONFIG_FLASHMODE_DOUT= 93 | CONFIG_ESPTOOLPY_FLASHMODE="dio" 94 | CONFIG_ESPTOOLPY_FLASHFREQ_80M=y 95 | CONFIG_ESPTOOLPY_FLASHFREQ_40M= 96 | CONFIG_ESPTOOLPY_FLASHFREQ_26M= 97 | CONFIG_ESPTOOLPY_FLASHFREQ_20M= 98 | CONFIG_ESPTOOLPY_FLASHFREQ="80m" 99 | CONFIG_ESPTOOLPY_FLASHSIZE_1MB= 100 | CONFIG_ESPTOOLPY_FLASHSIZE_2MB= 101 | CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y 102 | CONFIG_ESPTOOLPY_FLASHSIZE_8MB= 103 | CONFIG_ESPTOOLPY_FLASHSIZE_16MB= 104 | CONFIG_ESPTOOLPY_FLASHSIZE="4MB" 105 | CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y 106 | CONFIG_ESPTOOLPY_BEFORE_RESET=y 107 | CONFIG_ESPTOOLPY_BEFORE_NORESET= 108 | CONFIG_ESPTOOLPY_BEFORE="default_reset" 109 | CONFIG_ESPTOOLPY_AFTER_RESET=y 110 | CONFIG_ESPTOOLPY_AFTER_NORESET= 111 | CONFIG_ESPTOOLPY_AFTER="hard_reset" 112 | CONFIG_MONITOR_BAUD_9600B= 113 | CONFIG_MONITOR_BAUD_57600B= 114 | CONFIG_MONITOR_BAUD_115200B=y 115 | CONFIG_MONITOR_BAUD_230400B= 116 | CONFIG_MONITOR_BAUD_921600B= 117 | CONFIG_MONITOR_BAUD_2MB= 118 | CONFIG_MONITOR_BAUD_OTHER= 119 | CONFIG_MONITOR_BAUD_OTHER_VAL=115200 120 | CONFIG_MONITOR_BAUD=115200 121 | 122 | # 123 | # Partition Table 124 | # 125 | CONFIG_PARTITION_TABLE_SINGLE_APP= 126 | CONFIG_PARTITION_TABLE_TWO_OTA= 127 | CONFIG_PARTITION_TABLE_CUSTOM=y 128 | CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" 129 | CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" 130 | CONFIG_PARTITION_TABLE_OFFSET=0x8000 131 | CONFIG_PARTITION_TABLE_MD5=y 132 | 133 | # 134 | # Compiler options 135 | # 136 | CONFIG_OPTIMIZATION_LEVEL_DEBUG=y 137 | CONFIG_OPTIMIZATION_LEVEL_RELEASE= 138 | CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y 139 | CONFIG_OPTIMIZATION_ASSERTIONS_SILENT= 140 | CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED= 141 | CONFIG_CXX_EXCEPTIONS=y 142 | CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 143 | CONFIG_STACK_CHECK_NONE=y 144 | CONFIG_STACK_CHECK_NORM= 145 | CONFIG_STACK_CHECK_STRONG= 146 | CONFIG_STACK_CHECK_ALL= 147 | CONFIG_STACK_CHECK= 148 | CONFIG_WARN_WRITE_STRINGS= 149 | CONFIG_DISABLE_GCC8_WARNINGS= 150 | 151 | # 152 | # Component config 153 | # 154 | 155 | # 156 | # Application Level Tracing 157 | # 158 | CONFIG_ESP32_APPTRACE_DEST_TRAX= 159 | CONFIG_ESP32_APPTRACE_DEST_NONE=y 160 | CONFIG_ESP32_APPTRACE_ENABLE= 161 | CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y 162 | CONFIG_AWS_IOT_SDK= 163 | 164 | # 165 | # Bluetooth 166 | # 167 | CONFIG_BT_ENABLED=y 168 | 169 | # 170 | # Bluetooth controller 171 | # 172 | CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY=y 173 | CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY= 174 | CONFIG_BTDM_CONTROLLER_MODE_BTDM= 175 | CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN=3 176 | CONFIG_BTDM_CONTROLLER_BR_EDR_SCO_DATA_PATH_EFF=0 177 | CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF=3 178 | CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF=0 179 | CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF=0 180 | CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 181 | CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI=y 182 | CONFIG_BTDM_CONTROLLER_HCI_MODE_UART_H4= 183 | 184 | # 185 | # MODEM SLEEP Options 186 | # 187 | CONFIG_BTDM_CONTROLLER_MODEM_SLEEP=y 188 | CONFIG_BTDM_MODEM_SLEEP_MODE_ORIG=y 189 | CONFIG_BTDM_MODEM_SLEEP_MODE_EVED= 190 | CONFIG_BTDM_LPCLK_SEL_MAIN_XTAL=y 191 | CONFIG_BLE_SCAN_DUPLICATE=y 192 | CONFIG_SCAN_DUPLICATE_BY_DEVICE_ADDR=y 193 | CONFIG_SCAN_DUPLICATE_BY_ADV_DATA= 194 | CONFIG_SCAN_DUPLICATE_BY_ADV_DATA_AND_DEVICE_ADDR= 195 | CONFIG_SCAN_DUPLICATE_TYPE=0 196 | CONFIG_DUPLICATE_SCAN_CACHE_SIZE=200 197 | CONFIG_BLE_MESH_SCAN_DUPLICATE_EN= 198 | CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_SUPPORTED=y 199 | CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_NUM=100 200 | CONFIG_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 201 | CONFIG_BLUEDROID_ENABLED=y 202 | CONFIG_BLUEDROID_PINNED_TO_CORE=0 203 | CONFIG_BTC_TASK_STACK_SIZE=3072 204 | CONFIG_BLUEDROID_MEM_DEBUG= 205 | CONFIG_CLASSIC_BT_ENABLED= 206 | CONFIG_GATTS_ENABLE=y 207 | CONFIG_GATTS_SEND_SERVICE_CHANGE_MANUAL= 208 | CONFIG_GATTS_SEND_SERVICE_CHANGE_AUTO=y 209 | CONFIG_GATTS_SEND_SERVICE_CHANGE_MODE=0 210 | CONFIG_GATTC_ENABLE=y 211 | CONFIG_GATTC_CACHE_NVS_FLASH= 212 | CONFIG_BLE_SMP_ENABLE=y 213 | CONFIG_SMP_SLAVE_CON_PARAMS_UPD_ENABLE= 214 | CONFIG_BT_STACK_NO_LOG= 215 | 216 | # 217 | # BT DEBUG LOG LEVEL 218 | # 219 | CONFIG_HCI_TRACE_LEVEL_NONE= 220 | CONFIG_HCI_TRACE_LEVEL_ERROR= 221 | CONFIG_HCI_TRACE_LEVEL_WARNING=y 222 | CONFIG_HCI_TRACE_LEVEL_API= 223 | CONFIG_HCI_TRACE_LEVEL_EVENT= 224 | CONFIG_HCI_TRACE_LEVEL_DEBUG= 225 | CONFIG_HCI_TRACE_LEVEL_VERBOSE= 226 | CONFIG_HCI_INITIAL_TRACE_LEVEL=2 227 | CONFIG_BTM_TRACE_LEVEL_NONE= 228 | CONFIG_BTM_TRACE_LEVEL_ERROR= 229 | CONFIG_BTM_TRACE_LEVEL_WARNING=y 230 | CONFIG_BTM_TRACE_LEVEL_API= 231 | CONFIG_BTM_TRACE_LEVEL_EVENT= 232 | CONFIG_BTM_TRACE_LEVEL_DEBUG= 233 | CONFIG_BTM_TRACE_LEVEL_VERBOSE= 234 | CONFIG_BTM_INITIAL_TRACE_LEVEL=2 235 | CONFIG_L2CAP_TRACE_LEVEL_NONE= 236 | CONFIG_L2CAP_TRACE_LEVEL_ERROR= 237 | CONFIG_L2CAP_TRACE_LEVEL_WARNING=y 238 | CONFIG_L2CAP_TRACE_LEVEL_API= 239 | CONFIG_L2CAP_TRACE_LEVEL_EVENT= 240 | CONFIG_L2CAP_TRACE_LEVEL_DEBUG= 241 | CONFIG_L2CAP_TRACE_LEVEL_VERBOSE= 242 | CONFIG_L2CAP_INITIAL_TRACE_LEVEL=2 243 | CONFIG_RFCOMM_TRACE_LEVEL_NONE= 244 | CONFIG_RFCOMM_TRACE_LEVEL_ERROR= 245 | CONFIG_RFCOMM_TRACE_LEVEL_WARNING=y 246 | CONFIG_RFCOMM_TRACE_LEVEL_API= 247 | CONFIG_RFCOMM_TRACE_LEVEL_EVENT= 248 | CONFIG_RFCOMM_TRACE_LEVEL_DEBUG= 249 | CONFIG_RFCOMM_TRACE_LEVEL_VERBOSE= 250 | CONFIG_RFCOMM_INITIAL_TRACE_LEVEL=2 251 | CONFIG_SDP_TRACE_LEVEL_NONE= 252 | CONFIG_SDP_TRACE_LEVEL_ERROR= 253 | CONFIG_SDP_TRACE_LEVEL_WARNING=y 254 | CONFIG_SDP_TRACE_LEVEL_API= 255 | CONFIG_SDP_TRACE_LEVEL_EVENT= 256 | CONFIG_SDP_TRACE_LEVEL_DEBUG= 257 | CONFIG_SDP_TRACE_LEVEL_VERBOSE= 258 | CONFIG_SDP_INITIAL_TRACE_LEVEL=2 259 | CONFIG_GAP_TRACE_LEVEL_NONE= 260 | CONFIG_GAP_TRACE_LEVEL_ERROR= 261 | CONFIG_GAP_TRACE_LEVEL_WARNING=y 262 | CONFIG_GAP_TRACE_LEVEL_API= 263 | CONFIG_GAP_TRACE_LEVEL_EVENT= 264 | CONFIG_GAP_TRACE_LEVEL_DEBUG= 265 | CONFIG_GAP_TRACE_LEVEL_VERBOSE= 266 | CONFIG_GAP_INITIAL_TRACE_LEVEL=2 267 | CONFIG_BNEP_TRACE_LEVEL_NONE= 268 | CONFIG_BNEP_TRACE_LEVEL_ERROR= 269 | CONFIG_BNEP_TRACE_LEVEL_WARNING=y 270 | CONFIG_BNEP_TRACE_LEVEL_API= 271 | CONFIG_BNEP_TRACE_LEVEL_EVENT= 272 | CONFIG_BNEP_TRACE_LEVEL_DEBUG= 273 | CONFIG_BNEP_TRACE_LEVEL_VERBOSE= 274 | CONFIG_BNEP_INITIAL_TRACE_LEVEL=2 275 | CONFIG_PAN_TRACE_LEVEL_NONE= 276 | CONFIG_PAN_TRACE_LEVEL_ERROR= 277 | CONFIG_PAN_TRACE_LEVEL_WARNING=y 278 | CONFIG_PAN_TRACE_LEVEL_API= 279 | CONFIG_PAN_TRACE_LEVEL_EVENT= 280 | CONFIG_PAN_TRACE_LEVEL_DEBUG= 281 | CONFIG_PAN_TRACE_LEVEL_VERBOSE= 282 | CONFIG_PAN_INITIAL_TRACE_LEVEL=2 283 | CONFIG_A2D_TRACE_LEVEL_NONE= 284 | CONFIG_A2D_TRACE_LEVEL_ERROR= 285 | CONFIG_A2D_TRACE_LEVEL_WARNING=y 286 | CONFIG_A2D_TRACE_LEVEL_API= 287 | CONFIG_A2D_TRACE_LEVEL_EVENT= 288 | CONFIG_A2D_TRACE_LEVEL_DEBUG= 289 | CONFIG_A2D_TRACE_LEVEL_VERBOSE= 290 | CONFIG_A2D_INITIAL_TRACE_LEVEL=2 291 | CONFIG_AVDT_TRACE_LEVEL_NONE= 292 | CONFIG_AVDT_TRACE_LEVEL_ERROR= 293 | CONFIG_AVDT_TRACE_LEVEL_WARNING=y 294 | CONFIG_AVDT_TRACE_LEVEL_API= 295 | CONFIG_AVDT_TRACE_LEVEL_EVENT= 296 | CONFIG_AVDT_TRACE_LEVEL_DEBUG= 297 | CONFIG_AVDT_TRACE_LEVEL_VERBOSE= 298 | CONFIG_AVDT_INITIAL_TRACE_LEVEL=2 299 | CONFIG_AVCT_TRACE_LEVEL_NONE= 300 | CONFIG_AVCT_TRACE_LEVEL_ERROR= 301 | CONFIG_AVCT_TRACE_LEVEL_WARNING=y 302 | CONFIG_AVCT_TRACE_LEVEL_API= 303 | CONFIG_AVCT_TRACE_LEVEL_EVENT= 304 | CONFIG_AVCT_TRACE_LEVEL_DEBUG= 305 | CONFIG_AVCT_TRACE_LEVEL_VERBOSE= 306 | CONFIG_AVCT_INITIAL_TRACE_LEVEL=2 307 | CONFIG_AVRC_TRACE_LEVEL_NONE= 308 | CONFIG_AVRC_TRACE_LEVEL_ERROR= 309 | CONFIG_AVRC_TRACE_LEVEL_WARNING=y 310 | CONFIG_AVRC_TRACE_LEVEL_API= 311 | CONFIG_AVRC_TRACE_LEVEL_EVENT= 312 | CONFIG_AVRC_TRACE_LEVEL_DEBUG= 313 | CONFIG_AVRC_TRACE_LEVEL_VERBOSE= 314 | CONFIG_AVRC_INITIAL_TRACE_LEVEL=2 315 | CONFIG_MCA_TRACE_LEVEL_NONE= 316 | CONFIG_MCA_TRACE_LEVEL_ERROR= 317 | CONFIG_MCA_TRACE_LEVEL_WARNING=y 318 | CONFIG_MCA_TRACE_LEVEL_API= 319 | CONFIG_MCA_TRACE_LEVEL_EVENT= 320 | CONFIG_MCA_TRACE_LEVEL_DEBUG= 321 | CONFIG_MCA_TRACE_LEVEL_VERBOSE= 322 | CONFIG_MCA_INITIAL_TRACE_LEVEL=2 323 | CONFIG_HID_TRACE_LEVEL_NONE= 324 | CONFIG_HID_TRACE_LEVEL_ERROR= 325 | CONFIG_HID_TRACE_LEVEL_WARNING=y 326 | CONFIG_HID_TRACE_LEVEL_API= 327 | CONFIG_HID_TRACE_LEVEL_EVENT= 328 | CONFIG_HID_TRACE_LEVEL_DEBUG= 329 | CONFIG_HID_TRACE_LEVEL_VERBOSE= 330 | CONFIG_HID_INITIAL_TRACE_LEVEL=2 331 | CONFIG_APPL_TRACE_LEVEL_NONE= 332 | CONFIG_APPL_TRACE_LEVEL_ERROR= 333 | CONFIG_APPL_TRACE_LEVEL_WARNING=y 334 | CONFIG_APPL_TRACE_LEVEL_API= 335 | CONFIG_APPL_TRACE_LEVEL_EVENT= 336 | CONFIG_APPL_TRACE_LEVEL_DEBUG= 337 | CONFIG_APPL_TRACE_LEVEL_VERBOSE= 338 | CONFIG_APPL_INITIAL_TRACE_LEVEL=2 339 | CONFIG_GATT_TRACE_LEVEL_NONE= 340 | CONFIG_GATT_TRACE_LEVEL_ERROR= 341 | CONFIG_GATT_TRACE_LEVEL_WARNING=y 342 | CONFIG_GATT_TRACE_LEVEL_API= 343 | CONFIG_GATT_TRACE_LEVEL_EVENT= 344 | CONFIG_GATT_TRACE_LEVEL_DEBUG= 345 | CONFIG_GATT_TRACE_LEVEL_VERBOSE= 346 | CONFIG_GATT_INITIAL_TRACE_LEVEL=2 347 | CONFIG_SMP_TRACE_LEVEL_NONE= 348 | CONFIG_SMP_TRACE_LEVEL_ERROR= 349 | CONFIG_SMP_TRACE_LEVEL_WARNING=y 350 | CONFIG_SMP_TRACE_LEVEL_API= 351 | CONFIG_SMP_TRACE_LEVEL_EVENT= 352 | CONFIG_SMP_TRACE_LEVEL_DEBUG= 353 | CONFIG_SMP_TRACE_LEVEL_VERBOSE= 354 | CONFIG_SMP_INITIAL_TRACE_LEVEL=2 355 | CONFIG_BTIF_TRACE_LEVEL_NONE= 356 | CONFIG_BTIF_TRACE_LEVEL_ERROR= 357 | CONFIG_BTIF_TRACE_LEVEL_WARNING=y 358 | CONFIG_BTIF_TRACE_LEVEL_API= 359 | CONFIG_BTIF_TRACE_LEVEL_EVENT= 360 | CONFIG_BTIF_TRACE_LEVEL_DEBUG= 361 | CONFIG_BTIF_TRACE_LEVEL_VERBOSE= 362 | CONFIG_BTIF_INITIAL_TRACE_LEVEL=2 363 | CONFIG_BTC_TRACE_LEVEL_NONE= 364 | CONFIG_BTC_TRACE_LEVEL_ERROR= 365 | CONFIG_BTC_TRACE_LEVEL_WARNING=y 366 | CONFIG_BTC_TRACE_LEVEL_API= 367 | CONFIG_BTC_TRACE_LEVEL_EVENT= 368 | CONFIG_BTC_TRACE_LEVEL_DEBUG= 369 | CONFIG_BTC_TRACE_LEVEL_VERBOSE= 370 | CONFIG_BTC_INITIAL_TRACE_LEVEL=2 371 | CONFIG_OSI_TRACE_LEVEL_NONE= 372 | CONFIG_OSI_TRACE_LEVEL_ERROR= 373 | CONFIG_OSI_TRACE_LEVEL_WARNING=y 374 | CONFIG_OSI_TRACE_LEVEL_API= 375 | CONFIG_OSI_TRACE_LEVEL_EVENT= 376 | CONFIG_OSI_TRACE_LEVEL_DEBUG= 377 | CONFIG_OSI_TRACE_LEVEL_VERBOSE= 378 | CONFIG_OSI_INITIAL_TRACE_LEVEL=2 379 | CONFIG_BLUFI_TRACE_LEVEL_NONE= 380 | CONFIG_BLUFI_TRACE_LEVEL_ERROR= 381 | CONFIG_BLUFI_TRACE_LEVEL_WARNING=y 382 | CONFIG_BLUFI_TRACE_LEVEL_API= 383 | CONFIG_BLUFI_TRACE_LEVEL_EVENT= 384 | CONFIG_BLUFI_TRACE_LEVEL_DEBUG= 385 | CONFIG_BLUFI_TRACE_LEVEL_VERBOSE= 386 | CONFIG_BLUFI_INITIAL_TRACE_LEVEL=2 387 | CONFIG_BT_ACL_CONNECTIONS=4 388 | CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST= 389 | CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY= 390 | CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK= 391 | CONFIG_SMP_ENABLE=y 392 | CONFIG_BLE_ACTIVE_SCAN_REPORT_ADV_SCAN_RSP_INDIVIDUALLY= 393 | CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT=30 394 | CONFIG_BT_RESERVE_DRAM=0xdb5c 395 | 396 | # 397 | # Driver configurations 398 | # 399 | 400 | # 401 | # ADC configuration 402 | # 403 | CONFIG_ADC_FORCE_XPD_FSM= 404 | CONFIG_ADC2_DISABLE_DAC=y 405 | 406 | # 407 | # SPI configuration 408 | # 409 | CONFIG_SPI_MASTER_IN_IRAM= 410 | CONFIG_SPI_MASTER_ISR_IN_IRAM=y 411 | CONFIG_SPI_SLAVE_IN_IRAM= 412 | CONFIG_SPI_SLAVE_ISR_IN_IRAM=y 413 | 414 | # 415 | # ESP32-specific 416 | # 417 | CONFIG_ESP32_DEFAULT_CPU_FREQ_80= 418 | CONFIG_ESP32_DEFAULT_CPU_FREQ_160= 419 | CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y 420 | CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 421 | CONFIG_SPIRAM_SUPPORT= 422 | CONFIG_MEMMAP_TRACEMEM= 423 | CONFIG_MEMMAP_TRACEMEM_TWOBANKS= 424 | CONFIG_ESP32_TRAX= 425 | CONFIG_TRACEMEM_RESERVE_DRAM=0x0 426 | CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH= 427 | CONFIG_ESP32_ENABLE_COREDUMP_TO_UART= 428 | CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y 429 | CONFIG_ESP32_ENABLE_COREDUMP= 430 | CONFIG_TWO_UNIVERSAL_MAC_ADDRESS= 431 | CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y 432 | CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4 433 | CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 434 | CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2048 435 | CONFIG_MAIN_TASK_STACK_SIZE=4096 436 | CONFIG_IPC_TASK_STACK_SIZE=1024 437 | CONFIG_TIMER_TASK_STACK_SIZE=3584 438 | CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y 439 | CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF= 440 | CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR= 441 | CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF= 442 | CONFIG_NEWLIB_STDIN_LINE_ENDING_LF= 443 | CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y 444 | CONFIG_NEWLIB_NANO_FORMAT= 445 | CONFIG_CONSOLE_UART_DEFAULT=y 446 | CONFIG_CONSOLE_UART_CUSTOM= 447 | CONFIG_CONSOLE_UART_NONE= 448 | CONFIG_CONSOLE_UART_NUM=0 449 | CONFIG_CONSOLE_UART_BAUDRATE=115200 450 | CONFIG_ULP_COPROC_ENABLED= 451 | CONFIG_ULP_COPROC_RESERVE_MEM=0 452 | CONFIG_ESP32_PANIC_PRINT_HALT= 453 | CONFIG_ESP32_PANIC_PRINT_REBOOT=y 454 | CONFIG_ESP32_PANIC_SILENT_REBOOT= 455 | CONFIG_ESP32_PANIC_GDBSTUB= 456 | CONFIG_ESP32_DEBUG_OCDAWARE=y 457 | CONFIG_ESP32_DEBUG_STUBS_ENABLE=y 458 | CONFIG_INT_WDT=y 459 | CONFIG_INT_WDT_TIMEOUT_MS=300 460 | CONFIG_TASK_WDT=y 461 | CONFIG_TASK_WDT_PANIC= 462 | CONFIG_TASK_WDT_TIMEOUT_S=5 463 | CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y 464 | CONFIG_BROWNOUT_DET=y 465 | CONFIG_BROWNOUT_DET_LVL_SEL_0=y 466 | CONFIG_BROWNOUT_DET_LVL_SEL_1= 467 | CONFIG_BROWNOUT_DET_LVL_SEL_2= 468 | CONFIG_BROWNOUT_DET_LVL_SEL_3= 469 | CONFIG_BROWNOUT_DET_LVL_SEL_4= 470 | CONFIG_BROWNOUT_DET_LVL_SEL_5= 471 | CONFIG_BROWNOUT_DET_LVL_SEL_6= 472 | CONFIG_BROWNOUT_DET_LVL_SEL_7= 473 | CONFIG_BROWNOUT_DET_LVL=0 474 | CONFIG_REDUCE_PHY_TX_POWER=y 475 | CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y 476 | CONFIG_ESP32_TIME_SYSCALL_USE_RTC= 477 | CONFIG_ESP32_TIME_SYSCALL_USE_FRC1= 478 | CONFIG_ESP32_TIME_SYSCALL_USE_NONE= 479 | CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y 480 | CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL= 481 | CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC= 482 | CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256= 483 | CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024 484 | CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000 485 | CONFIG_ESP32_XTAL_FREQ_40=y 486 | CONFIG_ESP32_XTAL_FREQ_26= 487 | CONFIG_ESP32_XTAL_FREQ_AUTO= 488 | CONFIG_ESP32_XTAL_FREQ=40 489 | CONFIG_DISABLE_BASIC_ROM_CONSOLE= 490 | CONFIG_ESP_TIMER_PROFILING= 491 | CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS= 492 | CONFIG_ESP_ERR_TO_NAME_LOOKUP=y 493 | CONFIG_ESP32_RTCDATA_IN_FAST_MEM= 494 | 495 | # 496 | # Wi-Fi 497 | # 498 | CONFIG_SW_COEXIST_ENABLE=y 499 | CONFIG_SW_COEXIST_PREFERENCE_WIFI= 500 | CONFIG_SW_COEXIST_PREFERENCE_BT= 501 | CONFIG_SW_COEXIST_PREFERENCE_BALANCE=y 502 | CONFIG_SW_COEXIST_PREFERENCE_VALUE=2 503 | CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 504 | CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 505 | CONFIG_ESP32_WIFI_STATIC_TX_BUFFER= 506 | CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y 507 | CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 508 | CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 509 | CONFIG_ESP32_WIFI_CSI_ENABLED= 510 | CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y 511 | CONFIG_ESP32_WIFI_TX_BA_WIN=6 512 | CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y 513 | CONFIG_ESP32_WIFI_RX_BA_WIN=6 514 | CONFIG_ESP32_WIFI_NVS_ENABLED=y 515 | CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 516 | CONFIG_ESP32_WIFI_IRAM_OPT=y 517 | CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 518 | 519 | # 520 | # PHY 521 | # 522 | CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y 523 | CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION= 524 | CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 525 | CONFIG_ESP32_PHY_MAX_TX_POWER=20 526 | 527 | # 528 | # Power Management 529 | # 530 | CONFIG_PM_ENABLE= 531 | 532 | # 533 | # ADC-Calibration 534 | # 535 | CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y 536 | CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y 537 | CONFIG_ADC_CAL_LUT_ENABLE=y 538 | 539 | # 540 | # Event Loop Library 541 | # 542 | CONFIG_EVENT_LOOP_PROFILING= 543 | 544 | # 545 | # ESP HTTP client 546 | # 547 | CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y 548 | 549 | # 550 | # HTTP Server 551 | # 552 | CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 553 | CONFIG_HTTPD_MAX_URI_LEN=512 554 | CONFIG_HTTPD_PURGE_BUF_LEN=32 555 | CONFIG_HTTPD_LOG_PURGE_DATA= 556 | 557 | # 558 | # Ethernet 559 | # 560 | CONFIG_DMA_RX_BUF_NUM=10 561 | CONFIG_DMA_TX_BUF_NUM=10 562 | CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE= 563 | CONFIG_EMAC_CHECK_LINK_PERIOD_MS=2000 564 | CONFIG_EMAC_TASK_PRIORITY=20 565 | CONFIG_EMAC_TASK_STACK_SIZE=3072 566 | 567 | # 568 | # FAT Filesystem support 569 | # 570 | CONFIG_FATFS_CODEPAGE_DYNAMIC= 571 | CONFIG_FATFS_CODEPAGE_437=y 572 | CONFIG_FATFS_CODEPAGE_720= 573 | CONFIG_FATFS_CODEPAGE_737= 574 | CONFIG_FATFS_CODEPAGE_771= 575 | CONFIG_FATFS_CODEPAGE_775= 576 | CONFIG_FATFS_CODEPAGE_850= 577 | CONFIG_FATFS_CODEPAGE_852= 578 | CONFIG_FATFS_CODEPAGE_855= 579 | CONFIG_FATFS_CODEPAGE_857= 580 | CONFIG_FATFS_CODEPAGE_860= 581 | CONFIG_FATFS_CODEPAGE_861= 582 | CONFIG_FATFS_CODEPAGE_862= 583 | CONFIG_FATFS_CODEPAGE_863= 584 | CONFIG_FATFS_CODEPAGE_864= 585 | CONFIG_FATFS_CODEPAGE_865= 586 | CONFIG_FATFS_CODEPAGE_866= 587 | CONFIG_FATFS_CODEPAGE_869= 588 | CONFIG_FATFS_CODEPAGE_932= 589 | CONFIG_FATFS_CODEPAGE_936= 590 | CONFIG_FATFS_CODEPAGE_949= 591 | CONFIG_FATFS_CODEPAGE_950= 592 | CONFIG_FATFS_CODEPAGE=437 593 | CONFIG_FATFS_LFN_NONE=y 594 | CONFIG_FATFS_LFN_HEAP= 595 | CONFIG_FATFS_LFN_STACK= 596 | CONFIG_FATFS_FS_LOCK=0 597 | CONFIG_FATFS_TIMEOUT_MS=10000 598 | CONFIG_FATFS_PER_FILE_CACHE=y 599 | 600 | # 601 | # Modbus configuration 602 | # 603 | CONFIG_MB_QUEUE_LENGTH=20 604 | CONFIG_MB_SERIAL_TASK_STACK_SIZE=2048 605 | CONFIG_MB_SERIAL_BUF_SIZE=256 606 | CONFIG_MB_SERIAL_TASK_PRIO=10 607 | CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT= 608 | CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20 609 | CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 610 | CONFIG_MB_CONTROLLER_STACK_SIZE=4096 611 | CONFIG_MB_EVENT_QUEUE_TIMEOUT=20 612 | CONFIG_MB_TIMER_PORT_ENABLED=y 613 | CONFIG_MB_TIMER_GROUP=0 614 | CONFIG_MB_TIMER_INDEX=0 615 | 616 | # 617 | # FreeRTOS 618 | # 619 | CONFIG_FREERTOS_UNICORE=y 620 | CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF 621 | CONFIG_FREERTOS_CORETIMER_0=y 622 | CONFIG_FREERTOS_CORETIMER_1= 623 | CONFIG_FREERTOS_HZ=1000 624 | CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y 625 | CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE= 626 | CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL=y 627 | CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY= 628 | CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK= 629 | CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y 630 | CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=3 631 | CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y 632 | CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE= 633 | CONFIG_FREERTOS_ASSERT_DISABLE= 634 | CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1024 635 | CONFIG_FREERTOS_ISR_STACKSIZE=1536 636 | CONFIG_FREERTOS_LEGACY_HOOKS= 637 | CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 638 | CONFIG_SUPPORT_STATIC_ALLOCATION= 639 | CONFIG_TIMER_TASK_PRIORITY=1 640 | CONFIG_TIMER_TASK_STACK_DEPTH=2048 641 | CONFIG_TIMER_QUEUE_LENGTH=10 642 | CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 643 | CONFIG_FREERTOS_USE_TRACE_FACILITY= 644 | CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS= 645 | CONFIG_FREERTOS_DEBUG_INTERNALS= 646 | CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y 647 | 648 | # 649 | # Heap memory debugging 650 | # 651 | CONFIG_HEAP_POISONING_DISABLED=y 652 | CONFIG_HEAP_POISONING_LIGHT= 653 | CONFIG_HEAP_POISONING_COMPREHENSIVE= 654 | CONFIG_HEAP_TRACING= 655 | 656 | # 657 | # libsodium 658 | # 659 | 660 | # 661 | # Log output 662 | # 663 | CONFIG_LOG_DEFAULT_LEVEL_NONE= 664 | CONFIG_LOG_DEFAULT_LEVEL_ERROR= 665 | CONFIG_LOG_DEFAULT_LEVEL_WARN= 666 | CONFIG_LOG_DEFAULT_LEVEL_INFO=y 667 | CONFIG_LOG_DEFAULT_LEVEL_DEBUG= 668 | CONFIG_LOG_DEFAULT_LEVEL_VERBOSE= 669 | CONFIG_LOG_DEFAULT_LEVEL=3 670 | CONFIG_LOG_COLORS=y 671 | 672 | # 673 | # LWIP 674 | # 675 | CONFIG_L2_TO_L3_COPY= 676 | CONFIG_LWIP_IRAM_OPTIMIZATION= 677 | CONFIG_LWIP_MAX_SOCKETS=4 678 | CONFIG_USE_ONLY_LWIP_SELECT= 679 | CONFIG_LWIP_SO_REUSE= 680 | CONFIG_LWIP_SO_RCVBUF=y 681 | CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1 682 | CONFIG_LWIP_IP_FRAG= 683 | CONFIG_LWIP_IP_REASSEMBLY= 684 | CONFIG_LWIP_STATS= 685 | CONFIG_LWIP_ETHARP_TRUST_IP_MAC=y 686 | CONFIG_ESP_GRATUITOUS_ARP=y 687 | CONFIG_GARP_TMR_INTERVAL=60 688 | CONFIG_TCPIP_RECVMBOX_SIZE=32 689 | CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y 690 | CONFIG_LWIP_DHCP_RESTORE_LAST_IP= 691 | 692 | # 693 | # DHCP server 694 | # 695 | CONFIG_LWIP_DHCPS_LEASE_UNIT=60 696 | CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 697 | CONFIG_LWIP_AUTOIP= 698 | CONFIG_LWIP_NETIF_LOOPBACK=y 699 | CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 700 | 701 | # 702 | # TCP 703 | # 704 | CONFIG_LWIP_MAX_ACTIVE_TCP=16 705 | CONFIG_LWIP_MAX_LISTENING_TCP=16 706 | CONFIG_TCP_MAXRTX=12 707 | CONFIG_TCP_SYNMAXRTX=6 708 | CONFIG_TCP_MSS=1436 709 | CONFIG_TCP_MSL=60000 710 | CONFIG_TCP_SND_BUF_DEFAULT=5744 711 | CONFIG_TCP_WND_DEFAULT=5744 712 | CONFIG_TCP_RECVMBOX_SIZE=6 713 | CONFIG_TCP_QUEUE_OOSEQ=y 714 | CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES= 715 | CONFIG_TCP_OVERSIZE_MSS=y 716 | CONFIG_TCP_OVERSIZE_QUARTER_MSS= 717 | CONFIG_TCP_OVERSIZE_DISABLE= 718 | 719 | # 720 | # UDP 721 | # 722 | CONFIG_LWIP_MAX_UDP_PCBS=16 723 | CONFIG_UDP_RECVMBOX_SIZE=6 724 | CONFIG_TCPIP_TASK_STACK_SIZE=2560 725 | CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y 726 | CONFIG_TCPIP_TASK_AFFINITY_CPU0= 727 | CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF 728 | CONFIG_PPP_SUPPORT= 729 | 730 | # 731 | # ICMP 732 | # 733 | CONFIG_LWIP_MULTICAST_PING= 734 | CONFIG_LWIP_BROADCAST_PING= 735 | 736 | # 737 | # LWIP RAW API 738 | # 739 | CONFIG_LWIP_MAX_RAW_PCBS=16 740 | 741 | # 742 | # M5Stack 743 | # 744 | CONFIG_M5STICK= 745 | CONFIG_M5STACK_BASIC=y 746 | CONFIG_M5STACK_GRAY= 747 | CONFIG_M5STACK_FIRE= 748 | 749 | # 750 | # mbedTLS 751 | # 752 | CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y 753 | CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC= 754 | CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC= 755 | CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 756 | CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN= 757 | CONFIG_MBEDTLS_DEBUG= 758 | CONFIG_MBEDTLS_HARDWARE_AES=y 759 | CONFIG_MBEDTLS_HARDWARE_MPI=y 760 | CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y 761 | CONFIG_MBEDTLS_HARDWARE_SHA=y 762 | CONFIG_MBEDTLS_HAVE_TIME=y 763 | CONFIG_MBEDTLS_HAVE_TIME_DATE= 764 | CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y 765 | CONFIG_MBEDTLS_TLS_SERVER_ONLY= 766 | CONFIG_MBEDTLS_TLS_CLIENT_ONLY= 767 | CONFIG_MBEDTLS_TLS_DISABLED= 768 | CONFIG_MBEDTLS_TLS_SERVER=y 769 | CONFIG_MBEDTLS_TLS_CLIENT=y 770 | CONFIG_MBEDTLS_TLS_ENABLED=y 771 | 772 | # 773 | # TLS Key Exchange Methods 774 | # 775 | CONFIG_MBEDTLS_PSK_MODES=y 776 | CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y 777 | CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK=y 778 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK=y 779 | CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK=y 780 | CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y 781 | CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y 782 | CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y 783 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y 784 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y 785 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y 786 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y 787 | CONFIG_MBEDTLS_SSL_RENEGOTIATION=y 788 | CONFIG_MBEDTLS_SSL_PROTO_SSL3= 789 | CONFIG_MBEDTLS_SSL_PROTO_TLS1=y 790 | CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y 791 | CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y 792 | CONFIG_MBEDTLS_SSL_PROTO_DTLS= 793 | CONFIG_MBEDTLS_SSL_ALPN=y 794 | CONFIG_MBEDTLS_SSL_SESSION_TICKETS=y 795 | 796 | # 797 | # Symmetric Ciphers 798 | # 799 | CONFIG_MBEDTLS_AES_C=y 800 | CONFIG_MBEDTLS_CAMELLIA_C= 801 | CONFIG_MBEDTLS_DES_C= 802 | CONFIG_MBEDTLS_RC4_DISABLED=y 803 | CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT= 804 | CONFIG_MBEDTLS_RC4_ENABLED= 805 | CONFIG_MBEDTLS_BLOWFISH_C= 806 | CONFIG_MBEDTLS_XTEA_C= 807 | CONFIG_MBEDTLS_CCM_C=y 808 | CONFIG_MBEDTLS_GCM_C=y 809 | CONFIG_MBEDTLS_RIPEMD160_C= 810 | 811 | # 812 | # Certificates 813 | # 814 | CONFIG_MBEDTLS_PEM_PARSE_C=y 815 | CONFIG_MBEDTLS_PEM_WRITE_C=y 816 | CONFIG_MBEDTLS_X509_CRL_PARSE_C=y 817 | CONFIG_MBEDTLS_X509_CSR_PARSE_C=y 818 | CONFIG_MBEDTLS_ECP_C=y 819 | CONFIG_MBEDTLS_ECDH_C=y 820 | CONFIG_MBEDTLS_ECDSA_C=y 821 | CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y 822 | CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y 823 | CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y 824 | CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y 825 | CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y 826 | CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y 827 | CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y 828 | CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y 829 | CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y 830 | CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y 831 | CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y 832 | CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y 833 | CONFIG_MBEDTLS_ECP_NIST_OPTIM=y 834 | 835 | # 836 | # mDNS 837 | # 838 | CONFIG_MDNS_MAX_SERVICES=10 839 | 840 | # 841 | # ESP-MQTT Configurations 842 | # 843 | CONFIG_MQTT_PROTOCOL_311=y 844 | CONFIG_MQTT_TRANSPORT_SSL=y 845 | CONFIG_MQTT_TRANSPORT_WEBSOCKET=y 846 | CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y 847 | CONFIG_MQTT_USE_CUSTOM_CONFIG= 848 | CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED= 849 | CONFIG_MQTT_CUSTOM_OUTBOX= 850 | 851 | # 852 | # NVS 853 | # 854 | 855 | # 856 | # OpenSSL 857 | # 858 | CONFIG_OPENSSL_DEBUG= 859 | CONFIG_OPENSSL_ASSERT_DO_NOTHING=y 860 | CONFIG_OPENSSL_ASSERT_EXIT= 861 | 862 | # 863 | # PThreads 864 | # 865 | CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 866 | CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 867 | CONFIG_PTHREAD_STACK_MIN=768 868 | 869 | # 870 | # SPI Flash driver 871 | # 872 | CONFIG_SPI_FLASH_VERIFY_WRITE= 873 | CONFIG_SPI_FLASH_ENABLE_COUNTERS= 874 | CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y 875 | CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y 876 | CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS= 877 | CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED= 878 | CONFIG_SPI_FLASH_YIELD_DURING_ERASE= 879 | 880 | # 881 | # SPIFFS Configuration 882 | # 883 | CONFIG_SPIFFS_MAX_PARTITIONS=3 884 | 885 | # 886 | # SPIFFS Cache Configuration 887 | # 888 | CONFIG_SPIFFS_CACHE=y 889 | CONFIG_SPIFFS_CACHE_WR=y 890 | CONFIG_SPIFFS_CACHE_STATS= 891 | CONFIG_SPIFFS_PAGE_CHECK=y 892 | CONFIG_SPIFFS_GC_MAX_RUNS=10 893 | CONFIG_SPIFFS_GC_STATS= 894 | CONFIG_SPIFFS_PAGE_SIZE=256 895 | CONFIG_SPIFFS_OBJ_NAME_LEN=32 896 | CONFIG_SPIFFS_USE_MAGIC=y 897 | CONFIG_SPIFFS_USE_MAGIC_LENGTH=y 898 | CONFIG_SPIFFS_META_LENGTH=4 899 | CONFIG_SPIFFS_USE_MTIME=y 900 | 901 | # 902 | # Debug Configuration 903 | # 904 | CONFIG_SPIFFS_DBG= 905 | CONFIG_SPIFFS_API_DBG= 906 | CONFIG_SPIFFS_GC_DBG= 907 | CONFIG_SPIFFS_CACHE_DBG= 908 | CONFIG_SPIFFS_CHECK_DBG= 909 | CONFIG_SPIFFS_TEST_VISUALISATION= 910 | 911 | # 912 | # TCP/IP Adapter 913 | # 914 | CONFIG_IP_LOST_TIMER_INTERVAL=120 915 | CONFIG_TCPIP_LWIP=y 916 | 917 | # 918 | # Virtual file system 919 | # 920 | CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y 921 | CONFIG_SUPPORT_TERMIOS=y 922 | 923 | # 924 | # Wear Levelling 925 | # 926 | CONFIG_WL_SECTOR_SIZE_512= 927 | CONFIG_WL_SECTOR_SIZE_4096=y 928 | CONFIG_WL_SECTOR_SIZE=4096 929 | -------------------------------------------------------------------------------- /components/synth/src/ym2612.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Gens: Yamaha YM2612 FM synthesis chip emulator. * 3 | * * 4 | * Copyright (c) 1999-2002 by Stéphane Dallongeville * 5 | * Copyright (c) 2003-2004 by Stéphane Akhoun * 6 | * Copyright (c) 2008-2009 by David Korth * 7 | * * 8 | * This program is free software; you can redistribute it and/or modify it * 9 | * under the terms of the GNU General Public License as published by the * 10 | * Free Software Foundation; either version 2 of the License, or (at your * 11 | * option) any later version. * 12 | * * 13 | * This program is distributed in the hope that it will be useful, but * 14 | * WITHOUT ANY WARRANTY; without even the implied warranty of * 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 16 | * GNU General Public License for more details. * 17 | * * 18 | * You should have received a copy of the GNU General Public License along * 19 | * with this program; if not, write to the Free Software Foundation, Inc., * 20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 21 | ***************************************************************************/ 22 | 23 | /*********************************************************** 24 | * * 25 | * YM2612.C : YM2612 emulator * 26 | * * 27 | * Almost constantes are taken from the MAME core * 28 | * * 29 | * This source is a part of Gens project * 30 | * Written by Stéphane Dallongeville (gens@consolemul.com) * 31 | * Copyright (c) 2002 by Stéphane Dallongeville * 32 | * * 33 | ***********************************************************/ 34 | 35 | #include "ym2612.hpp" 36 | 37 | // C includes. 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #if ESP32_SYNTH 45 | #include 46 | #endif 47 | 48 | // // Message logging. 49 | // #include "macros/log_msg.h" 50 | 51 | // // GSX v7 savestate functionality. 52 | // #include "util/file/gsx_v7.h" 53 | // #include "libgsft/gsft_byteswap.h" 54 | 55 | 56 | /******************************************** 57 | * Partie définition * 58 | ********************************************/ 59 | 60 | #ifndef PI 61 | #define PI 3.14159265358979323846 62 | #endif 63 | 64 | #define ATTACK 0 65 | #define DECAY 1 66 | #define SUBSTAIN 2 67 | #define RELEASE 3 68 | 69 | // SIN_LBITS <= 16 70 | // LFO_HBITS <= 16 71 | // (SIN_LBITS + SIN_HBITS) <= 26 72 | // (ENV_LBITS + ENV_HBITS) <= 28 73 | // (LFO_LBITS + LFO_HBITS) <= 28 74 | 75 | #define SIN_HBITS 12 // Sinus phase counter int part 76 | #define SIN_LBITS (26 - SIN_HBITS) // Sinus phase counter float part (best setting) 77 | 78 | #if (SIN_LBITS > 16) 79 | #define SIN_LBITS 16 // Can't be greater than 16 bits 80 | #endif 81 | 82 | #define ENV_HBITS 12 // Env phase counter int part 83 | #define ENV_LBITS (28 - ENV_HBITS) // Env phase counter float part (best setting) 84 | 85 | #define LFO_HBITS 10 // LFO phase counter int part 86 | #define LFO_LBITS (28 - LFO_HBITS) // LFO phase counter float part (best setting) 87 | 88 | #define SIN_LENGTH (1 << SIN_HBITS) 89 | #define ENV_LENGTH (1 << ENV_HBITS) 90 | #define LFO_LENGTH (1 << LFO_HBITS) 91 | 92 | #define TL_LENGTH (ENV_LENGTH * 3) // Env + TL scaling + LFO 93 | 94 | #define SIN_MASK (SIN_LENGTH - 1) 95 | #define ENV_MASK (ENV_LENGTH - 1) 96 | #define LFO_MASK (LFO_LENGTH - 1) 97 | 98 | #define ENV_STEP (96.0 / ENV_LENGTH) // ENV_MAX = 96 dB 99 | 100 | #define ENV_ATTACK ((ENV_LENGTH * 0) << ENV_LBITS) 101 | #define ENV_DECAY ((ENV_LENGTH * 1) << ENV_LBITS) 102 | #define ENV_END ((ENV_LENGTH * 2) << ENV_LBITS) 103 | 104 | #define MAX_OUT_BITS (SIN_HBITS + SIN_LBITS + 2) // Modulation = -4 <--> +4 105 | #define MAX_OUT ((1 << MAX_OUT_BITS) - 1) 106 | 107 | //Just for tests stuff... 108 | // 109 | //#define COEF_MOD 0.5 110 | //#define MAX_OUT ((int) (((1 << MAX_OUT_BITS) - 1) * COEF_MOD)) 111 | 112 | #define OUT_BITS (OUTPUT_BITS - 2) 113 | #define OUT_SHIFT (MAX_OUT_BITS - OUT_BITS) 114 | #define LIMIT_CH_OUT ((int) (((1 << OUT_BITS) * 1.5) - 1)) 115 | 116 | #define PG_CUT_OFF ((int) (78.0 / ENV_STEP)) 117 | #define ENV_CUT_OFF ((int) (68.0 / ENV_STEP)) 118 | 119 | #define AR_RATE 399128 120 | #define DR_RATE 5514396 121 | 122 | //#define AR_RATE 426136 123 | //#define DR_RATE (AR_RATE * 12) 124 | 125 | #define LFO_FMS_LBITS 9 // FIXED (LFO_FMS_BASE gives somethink as 1) 126 | #define LFO_FMS_BASE ((int) (0.05946309436 * 0.0338 * (double) (1 << LFO_FMS_LBITS))) 127 | 128 | #define S0 0 // Stupid typo of the YM2612 129 | #define S1 2 130 | #define S2 1 131 | #define S3 3 132 | 133 | 134 | /******************************************** 135 | * Partie variables * 136 | ********************************************/ 137 | 138 | 139 | struct ym2612__ YM2612; 140 | 141 | static int *SIN_TAB[SIN_LENGTH]; // SINUS TABLE (pointer on TL TABLE) 142 | 143 | #ifdef ESP32_SYNTH 144 | static int *TL_TAB; // TOTAL LEVEL TABLE (positif and minus) 145 | static unsigned int *ENV_TAB; // ENV CURVE TABLE (attack & decay) 146 | #else 147 | static int TL_TAB[TL_LENGTH * 2]; // TOTAL LEVEL TABLE (positif and minus) 148 | static unsigned int ENV_TAB[2 * ENV_LENGTH + 8]; // ENV CURVE TABLE (attack & decay) 149 | #endif 150 | 151 | 152 | //static unsigned int ATTACK_TO_DECAY[ENV_LENGTH]; // Conversion from attack to decay phase 153 | static unsigned int DECAY_TO_ATTACK[ENV_LENGTH]; // Conversion from decay to attack phase 154 | 155 | static unsigned int FINC_TAB[2048]; // Frequency step table 156 | 157 | // Rate tables. 158 | // NOTE: This is needed in a struct because g++ reorders static 159 | // elements randomly, causing issues with the GSXv7 code. The 160 | // GSXv7 code stupidly depends on arrays being placed in the 161 | // correct order, but I can't really do anything about that 162 | // at the moment. 163 | static struct __attribute__ ((packed)) 164 | { 165 | unsigned int AR_TAB[128]; // Attack rate table 166 | unsigned int DR_TAB[96]; // Decay rate table 167 | unsigned int DT_TAB[8][32]; // Detune table 168 | unsigned int SL_TAB[16]; // Substain level table 169 | unsigned int NULL_RATE[32]; // Table for NULL rate 170 | } Rate_Tabs; 171 | 172 | static int LFO_ENV_TAB[LFO_LENGTH]; // LFO AMS TABLE (adjusted for 11.8 dB) 173 | static int LFO_FREQ_TAB[LFO_LENGTH]; // LFO FMS TABLE 174 | static int LFO_ENV_UP[MAX_UPDATE_LENGTH]; // Temporary calculated LFO AMS (adjusted for 11.8 dB) 175 | static int LFO_FREQ_UP[MAX_UPDATE_LENGTH]; // Temporary calculated LFO FMS 176 | 177 | // ESP32 178 | // static int INTER_TAB[MAX_UPDATE_LENGTH]; // Interpolation table 179 | 180 | static int LFO_INC_TAB[8]; // LFO step table 181 | 182 | static int in0, in1, in2, in3; // current phase calculation 183 | static int en0, en1, en2, en3; // current enveloppe calculation 184 | 185 | // Envelope function declarations 186 | static void Env_Attack_Next(slot_ *SL); 187 | static void Env_Decay_Next(slot_ *SL); 188 | static void Env_Substain_Next(slot_ *SL); 189 | static void Env_Release_Next(slot_ *SL); 190 | static void Env_NULL_Next(slot_ *SL); 191 | 192 | typedef void (*Env_Event)(slot_ * SL); 193 | 194 | // Next Enveloppe phase functions pointer table 195 | static const Env_Event ENV_NEXT_EVENT[8] = 196 | { 197 | Env_Attack_Next, 198 | Env_Decay_Next, 199 | Env_Substain_Next, 200 | Env_Release_Next, 201 | Env_NULL_Next, 202 | Env_NULL_Next, 203 | Env_NULL_Next, 204 | Env_NULL_Next 205 | }; 206 | 207 | // Default detune table. 208 | // FD == F number 209 | static const uint8_t DT_DEF_TAB[4][32] = 210 | { 211 | // FD = 0 212 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 214 | 215 | // FD = 1 216 | {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 217 | 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8}, 218 | 219 | // FD = 2 220 | {1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 221 | 5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 16, 16, 16, 16}, 222 | 223 | // FD = 3 224 | {2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 225 | 8, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 20, 22, 22, 22, 22} 226 | }; 227 | 228 | static const uint8_t FKEY_TAB[16] = 229 | { 230 | 0, 0, 0, 0, 231 | 0, 0, 0, 1, 232 | 2, 3, 3, 3, 233 | 3, 3, 3, 3 234 | }; 235 | 236 | static const uint8_t LFO_AMS_TAB[4] = 237 | { 238 | 31, 4, 1, 0 239 | }; 240 | 241 | static const unsigned int LFO_FMS_TAB[8] = 242 | { 243 | LFO_FMS_BASE * 0, LFO_FMS_BASE * 1, 244 | LFO_FMS_BASE * 2, LFO_FMS_BASE * 3, 245 | LFO_FMS_BASE * 4, LFO_FMS_BASE * 6, 246 | LFO_FMS_BASE * 12, LFO_FMS_BASE * 24 247 | }; 248 | 249 | static int int_cnt; // Interpolation calculation 250 | 251 | 252 | /** Gens-specific **/ 253 | 254 | // #include "audio/audio.h" 255 | // #include "util/sound/gym.hpp" 256 | 257 | // // Needed for VDP line number. 258 | // #include "gens_core/vdp/vdp_io.h" 259 | 260 | int YM2612_Enable; 261 | int YM2612_Improv; 262 | int DAC_Enable = 1; 263 | int *YM_Buf[2]; 264 | int YM_Len = 0; 265 | 266 | /** end **/ 267 | 268 | 269 | /*********************************************** 270 | * fonctions calcul param * 271 | ***********************************************/ 272 | 273 | 274 | static inline void CALC_FINC_SL(slot_ * SL, int finc, int kc) 275 | { 276 | int ksr; 277 | 278 | SL->Finc = (finc + SL->DT[kc]) * SL->MUL; 279 | ksr = kc >> SL->KSR_S; // keycode atténuation 280 | 281 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 282 | // "FINC = %d SL->Finc = %d", finc, SL->Finc); 283 | 284 | if (SL->KSR != ksr) // si le KSR a changé alors 285 | { // les différents taux pour l'enveloppe sont mis à jour 286 | SL->KSR = ksr; 287 | 288 | SL->EincA = SL->AR[ksr]; 289 | SL->EincD = SL->DR[ksr]; 290 | SL->EincS = SL->SR[ksr]; 291 | SL->EincR = SL->RR[ksr]; 292 | 293 | if (SL->Ecurp == ATTACK) 294 | SL->Einc = SL->EincA; 295 | else if (SL->Ecurp == DECAY) 296 | SL->Einc = SL->EincD; 297 | else if (SL->Ecnt < ENV_END) 298 | { 299 | if (SL->Ecurp == SUBSTAIN) 300 | SL->Einc = SL->EincS; 301 | else if (SL->Ecurp == RELEASE) 302 | SL->Einc = SL->EincR; 303 | } 304 | 305 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 306 | // "KSR = %.4X EincA = %.8X EincD = %.8X EincS = %.8X EincR = %.8X", 307 | // ksr, SL->EincA, SL->EincD, SL->EincS, SL->EincR); 308 | } 309 | } 310 | 311 | 312 | static inline void CALC_FINC_CH(channel_ *CH) 313 | { 314 | int finc, kc; 315 | 316 | finc = FINC_TAB[CH->FNUM[0]] >> (7 - CH->FOCT[0]); 317 | kc = CH->KC[0]; 318 | 319 | CALC_FINC_SL(&CH->SLOT[0], finc, kc); 320 | CALC_FINC_SL(&CH->SLOT[1], finc, kc); 321 | CALC_FINC_SL(&CH->SLOT[2], finc, kc); 322 | CALC_FINC_SL(&CH->SLOT[3], finc, kc); 323 | } 324 | 325 | 326 | 327 | /*********************************************** 328 | * fonctions setting * 329 | ***********************************************/ 330 | 331 | 332 | static inline void KEY_ON(channel_ *CH, int nsl) 333 | { 334 | slot_ *SL = &(CH->SLOT[nsl]); // on recupère le bon pointeur de slot 335 | 336 | if (SL->Ecurp == RELEASE) // la touche est-elle relâchée ? 337 | { 338 | SL->Fcnt = 0; 339 | 340 | // Fix Ecco 2 splash sound 341 | SL->Ecnt = (DECAY_TO_ATTACK[ENV_TAB[SL->Ecnt >> ENV_LBITS]] + ENV_ATTACK) & SL->ChgEnM; 342 | SL->ChgEnM = 0xFFFFFFFF; 343 | 344 | /* 345 | SL->Ecnt = DECAY_TO_ATTACK[ENV_TAB[SL->Ecnt >> ENV_LBITS]] + ENV_ATTACK; 346 | SL->Ecnt = 0; 347 | */ 348 | 349 | SL->Einc = SL->EincA; 350 | SL->Ecmp = ENV_DECAY; 351 | SL->Ecurp = ATTACK; 352 | } 353 | } 354 | 355 | 356 | static inline void KEY_OFF(channel_ *CH, int nsl) 357 | { 358 | slot_ *SL = &(CH->SLOT[nsl]); // on recupère le bon pointeur de slot 359 | 360 | if (SL->Ecurp != RELEASE) // la touche est-elle appuyée ? 361 | { 362 | if (SL->Ecnt < ENV_DECAY) // attack phase ? 363 | { 364 | SL->Ecnt = (ENV_TAB[SL->Ecnt >> ENV_LBITS] << ENV_LBITS) + ENV_DECAY; 365 | } 366 | 367 | SL->Einc = SL->EincR; 368 | SL->Ecmp = ENV_END; 369 | SL->Ecurp = RELEASE; 370 | } 371 | } 372 | 373 | 374 | static inline void CSM_Key_Control(void) 375 | { 376 | KEY_ON(&YM2612.CHANNEL[2], 0); 377 | KEY_ON(&YM2612.CHANNEL[2], 1); 378 | KEY_ON(&YM2612.CHANNEL[2], 2); 379 | KEY_ON(&YM2612.CHANNEL[2], 3); 380 | } 381 | 382 | 383 | static int SLOT_SET(int Adr, unsigned char data) 384 | { 385 | channel_ *CH; 386 | slot_ *SL; 387 | int nch, nsl; 388 | 389 | if ((nch = Adr & 3) == 3) 390 | return 1; 391 | nsl = (Adr >> 2) & 3; 392 | 393 | if (Adr & 0x100) 394 | nch += 3; 395 | 396 | CH = &(YM2612.CHANNEL[nch]); 397 | SL = &(CH->SLOT[nsl]); 398 | 399 | switch (Adr & 0xF0) 400 | { 401 | case 0x30: 402 | if ((SL->MUL = (data & 0x0F))) 403 | SL->MUL <<= 1; 404 | else 405 | SL->MUL = 1; 406 | 407 | SL->DT = Rate_Tabs.DT_TAB[(data >> 4) & 7]; 408 | 409 | CH->SLOT[0].Finc = -1; 410 | 411 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 412 | // "CHANNEL[%d], SLOT[%d] DTMUL = %.2X", nch, nsl, data & 0x7F); 413 | break; 414 | 415 | case 0x40: 416 | SL->TL = data & 0x7F; 417 | 418 | // SOR2 do a lot of TL adjustement and this fix R.Shinobi jump sound... 419 | YM2612_Special_Update(); 420 | 421 | #if ((ENV_HBITS - 7) < 0) 422 | SL->TLL = SL->TL >> (7 - ENV_HBITS); 423 | #else 424 | SL->TLL = SL->TL << (ENV_HBITS - 7); 425 | #endif 426 | 427 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 428 | // "CHANNEL[%d], SLOT[%d] TL = %.2X", nch, nsl, SL->TL); 429 | break; 430 | 431 | case 0x50: 432 | SL->KSR_S = 3 - (data >> 6); 433 | 434 | CH->SLOT[0].Finc = -1; 435 | 436 | if (data &= 0x1F) 437 | SL->AR = &Rate_Tabs.AR_TAB[data << 1]; 438 | else 439 | SL->AR = &Rate_Tabs.NULL_RATE[0]; 440 | 441 | SL->EincA = SL->AR[SL->KSR]; 442 | if (SL->Ecurp == ATTACK) 443 | SL->Einc = SL->EincA; 444 | 445 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 446 | // "CHANNEL[%d], SLOT[%d] AR = %.2X EincA = %.6X", nch, nsl, data, SL->EincA); 447 | break; 448 | 449 | case 0x60: 450 | if ((SL->AMSon = (data & 0x80))) 451 | SL->AMS = CH->AMS; 452 | else 453 | SL->AMS = 31; 454 | 455 | if (data &= 0x1F) 456 | SL->DR = &Rate_Tabs.DR_TAB[data << 1]; 457 | else 458 | SL->DR = &Rate_Tabs.NULL_RATE[0]; 459 | 460 | SL->EincD = SL->DR[SL->KSR]; 461 | if (SL->Ecurp == DECAY) 462 | SL->Einc = SL->EincD; 463 | 464 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 465 | // "CHANNEL[%d], SLOT[%d] AMS = %d DR = %.2X EincD = %.6X", 466 | // nch, nsl, SL->AMSon, data, SL->EincD); 467 | break; 468 | 469 | case 0x70: 470 | if (data &= 0x1F) 471 | SL->SR = &Rate_Tabs.DR_TAB[data << 1]; 472 | else 473 | SL->SR = &Rate_Tabs.NULL_RATE[0]; 474 | 475 | SL->EincS = SL->SR[SL->KSR]; 476 | if ((SL->Ecurp == SUBSTAIN) && (SL->Ecnt < ENV_END)) 477 | SL->Einc = SL->EincS; 478 | 479 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 480 | // "CHANNEL[%d], SLOT[%d] SR = %.2X EincS = %.6X", 481 | // nch, nsl, data, SL->EincS); 482 | break; 483 | 484 | case 0x80: 485 | SL->SLL = Rate_Tabs.SL_TAB[data >> 4]; 486 | 487 | SL->RR = &Rate_Tabs.DR_TAB[((data & 0xF) << 2) + 2]; 488 | 489 | SL->EincR = SL->RR[SL->KSR]; 490 | if ((SL->Ecurp == RELEASE) && (SL->Ecnt < ENV_END)) 491 | SL->Einc = SL->EincR; 492 | 493 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 494 | // "CHANNEL[%d], SLOT[%d] SL = %.8X", nch, nsl, SL->SLL); 495 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 496 | // "CHANNEL[%d], SLOT[%d] RR = %.2X EincR = %.2X", 497 | // nch, nsl, ((data & 0xF) << 1) | 2, SL->EincR); 498 | 499 | break; 500 | 501 | case 0x90: 502 | // SSG-EG envelope shapes : 503 | /* 504 | E At Al H 505 | 506 | 1 0 0 0 \\\\ 507 | 508 | 1 0 0 1 \___ 509 | 510 | 1 0 1 0 \/\/ 511 | ___ 512 | 1 0 1 1 \ 513 | 514 | 1 1 0 0 //// 515 | ___ 516 | 1 1 0 1 / 517 | 518 | 1 1 1 0 /\/\ 519 | 520 | 1 1 1 1 /___ 521 | 522 | E = SSG-EG enable 523 | At = Start negate 524 | Al = Altern 525 | H = Hold */ 526 | 527 | if (data & 0x08) 528 | SL->SEG = data & 0x0F; 529 | else 530 | SL->SEG = 0; 531 | 532 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 533 | // "CHANNEL[%d], SLOT[%d] SSG-EG = %.2X", nch, nsl, data); 534 | break; 535 | } 536 | 537 | return 0; 538 | } 539 | 540 | 541 | static int CHANNEL_SET(int Adr, unsigned char data) 542 | { 543 | channel_ *CH; 544 | int num; 545 | 546 | if ((num = Adr & 3) == 3) 547 | return 1; 548 | 549 | switch (Adr & 0xFC) 550 | { 551 | case 0xA0: 552 | if (Adr & 0x100) 553 | num += 3; 554 | CH = &(YM2612.CHANNEL[num]); 555 | 556 | YM2612_Special_Update(); 557 | 558 | CH->FNUM[0] = (CH->FNUM[0] & 0x700) + data; 559 | CH->KC[0] = (CH->FOCT[0] << 2) | FKEY_TAB[CH->FNUM[0] >> 7]; 560 | 561 | CH->SLOT[0].Finc = -1; 562 | 563 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 564 | // "CHANNEL[%d] part1 FNUM = %d KC = %d", 565 | // num, CH->FNUM[0], CH->KC[0]); 566 | break; 567 | 568 | case 0xA4: 569 | if (Adr & 0x100) 570 | num += 3; 571 | CH = &(YM2612.CHANNEL[num]); 572 | 573 | YM2612_Special_Update(); 574 | 575 | CH->FNUM[0] = (CH->FNUM[0] & 0x0FF) + ((int) (data & 0x07) << 8); 576 | CH->FOCT[0] = (data & 0x38) >> 3; 577 | CH->KC[0] = (CH->FOCT[0] << 2) | FKEY_TAB[CH->FNUM[0] >> 7]; 578 | 579 | CH->SLOT[0].Finc = -1; 580 | 581 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 582 | // "CHANNEL[%d] part2 FNUM = %d FOCT = %d KC = %d", 583 | // num, CH->FNUM[0], CH->FOCT[0], CH->KC[0]); 584 | break; 585 | 586 | case 0xA8: 587 | if (Adr < 0x100) 588 | { 589 | num++; 590 | 591 | YM2612_Special_Update(); 592 | 593 | YM2612.CHANNEL[2].FNUM[num] = (YM2612.CHANNEL[2].FNUM[num] & 0x700) + data; 594 | YM2612.CHANNEL[2].KC[num] = (YM2612.CHANNEL[2].FOCT[num] << 2) | 595 | FKEY_TAB[YM2612.CHANNEL[2].FNUM[num] >> 7]; 596 | 597 | YM2612.CHANNEL[2].SLOT[0].Finc = -1; 598 | 599 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 600 | // "CHANNEL[2] part1 FNUM[%d] = %d KC[%d] = %d", 601 | // num, YM2612.CHANNEL[2].FNUM[num], 602 | // num, YM2612.CHANNEL[2].KC[num]); 603 | } 604 | break; 605 | 606 | case 0xAC: 607 | if (Adr < 0x100) 608 | { 609 | num++; 610 | 611 | YM2612_Special_Update(); 612 | 613 | YM2612.CHANNEL[2].FNUM[num] = (YM2612.CHANNEL[2].FNUM[num] & 0x0FF) + 614 | ((int) (data & 0x07) << 8); 615 | YM2612.CHANNEL[2].FOCT[num] = (data & 0x38) >> 3; 616 | YM2612.CHANNEL[2].KC[num] = (YM2612.CHANNEL[2].FOCT[num] << 2) | 617 | FKEY_TAB[YM2612.CHANNEL[2].FNUM[num] >> 7]; 618 | 619 | YM2612.CHANNEL[2].SLOT[0].Finc = -1; 620 | 621 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 622 | // "CHANNEL[2] part2 FNUM[%d] = %d FOCT[%d] = %d KC[%d] = %d", 623 | // num, YM2612.CHANNEL[2].FNUM[num], 624 | // num, YM2612.CHANNEL[2].FOCT[num], 625 | // num, YM2612.CHANNEL[2].KC[num]); 626 | } 627 | break; 628 | 629 | case 0xB0: 630 | if (Adr & 0x100) 631 | num += 3; 632 | CH = &(YM2612.CHANNEL[num]); 633 | 634 | if (CH->ALGO != (data & 7)) 635 | { 636 | // Fix VectorMan 2 heli sound (level 1) 637 | YM2612_Special_Update(); 638 | 639 | CH->ALGO = data & 7; 640 | 641 | CH->SLOT[0].ChgEnM = 0; 642 | CH->SLOT[1].ChgEnM = 0; 643 | CH->SLOT[2].ChgEnM = 0; 644 | CH->SLOT[3].ChgEnM = 0; 645 | } 646 | 647 | CH->FB = 9 - ((data >> 3) & 7); // Real thing ? 648 | 649 | /* 650 | if (CH->FB = ((data >> 3) & 7)) 651 | CH->FB = 9 - CH->FB; // Thunder force 4 (music stage 8), Gynoug, Aladdin bug sound... 652 | else 653 | CH->FB = 31; 654 | */ 655 | 656 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 657 | // "CHANNEL[%d] ALGO = %d FB = %d", num, CH->ALGO, CH->FB); 658 | break; 659 | 660 | case 0xB4: 661 | if (Adr & 0x100) 662 | num += 3; 663 | CH = &(YM2612.CHANNEL[num]); 664 | 665 | YM2612_Special_Update(); 666 | 667 | if (data & 0x80) 668 | CH->LEFT = 0xFFFFFFFF; 669 | else 670 | CH->LEFT = 0; 671 | 672 | if (data & 0x40) 673 | CH->RIGHT = 0xFFFFFFFF; 674 | else 675 | CH->RIGHT = 0; 676 | 677 | CH->AMS = LFO_AMS_TAB[(data >> 4) & 3]; 678 | CH->FMS = LFO_FMS_TAB[data & 7]; 679 | 680 | if (CH->SLOT[0].AMSon) 681 | CH->SLOT[0].AMS = CH->AMS; 682 | else 683 | CH->SLOT[0].AMS = 31; 684 | if (CH->SLOT[1].AMSon) 685 | CH->SLOT[1].AMS = CH->AMS; 686 | else 687 | CH->SLOT[1].AMS = 31; 688 | if (CH->SLOT[2].AMSon) 689 | CH->SLOT[2].AMS = CH->AMS; 690 | else 691 | CH->SLOT[2].AMS = 31; 692 | if (CH->SLOT[3].AMSon) 693 | CH->SLOT[3].AMS = CH->AMS; 694 | else 695 | CH->SLOT[3].AMS = 31; 696 | 697 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG1, 698 | // "CHANNEL[%d] AMS = %d FMS = %d", num, CH->AMS, CH->FMS); 699 | break; 700 | } 701 | 702 | return 0; 703 | } 704 | 705 | 706 | static int YM_SET(int Adr, unsigned char data) 707 | { 708 | channel_ *CH; 709 | int nch; 710 | 711 | switch (Adr) 712 | { 713 | case 0x22: 714 | if (data & 8) 715 | { 716 | // Cool Spot music 1, LFO modified severals time which 717 | // distord the sound, have to check that on a real genesis... 718 | 719 | YM2612.LFOinc = LFO_INC_TAB[data & 7]; 720 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG1, 721 | // "LFO Enable, LFOinc = %.8X %d", YM2612.LFOinc, data & 7); 722 | } 723 | else 724 | { 725 | YM2612.LFOinc = YM2612.LFOcnt = 0; 726 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG1, 727 | // "LFO Disable"); 728 | } 729 | break; 730 | 731 | case 0x24: 732 | YM2612.TimerA = (YM2612.TimerA & 0x003) | (((int) data) << 2); 733 | 734 | if (YM2612.TimerAL != (1024 - YM2612.TimerA) << 12) 735 | { 736 | YM2612.TimerAcnt = YM2612.TimerAL = (1024 - YM2612.TimerA) << 12; 737 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 738 | // "Timer A Set = %.8X", YM2612.TimerAcnt); 739 | } 740 | break; 741 | 742 | case 0x25: 743 | YM2612.TimerA = (YM2612.TimerA & 0x3fc) | (data & 3); 744 | 745 | if (YM2612.TimerAL != (1024 - YM2612.TimerA) << 12) 746 | { 747 | YM2612.TimerAcnt = YM2612.TimerAL = (1024 - YM2612.TimerA) << 12; 748 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 749 | // "Timer A Set = %.8X", YM2612.TimerAcnt); 750 | } 751 | break; 752 | 753 | case 0x26: 754 | YM2612.TimerB = data; 755 | 756 | if (YM2612.TimerBL != (256 - YM2612.TimerB) << (4 + 12)) 757 | { 758 | YM2612.TimerBcnt = YM2612.TimerBL = (256 - YM2612.TimerB) << (4 + 12); 759 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 760 | // "Timer B Set = %.8X", YM2612.TimerBcnt); 761 | } 762 | break; 763 | 764 | case 0x27: 765 | // Paramètre divers 766 | // b7 = CSM MODE 767 | // b6 = 3 slot mode 768 | // b5 = reset b 769 | // b4 = reset a 770 | // b3 = timer enable b 771 | // b2 = timer enable a 772 | // b1 = load b 773 | // b0 = load a 774 | 775 | if ((data ^ YM2612.Mode) & 0x40) 776 | { 777 | // We changed the channel 2 mode, so recalculate phase step 778 | // This fix the punch sound in Street of Rage 2 779 | 780 | YM2612_Special_Update(); 781 | 782 | YM2612.CHANNEL[2].SLOT[0].Finc = -1; // recalculate phase step 783 | } 784 | 785 | /* 786 | if ((data & 2) && (YM2612.Status & 2)) 787 | YM2612.TimerBcnt = YM2612.TimerBL; 788 | if ((data & 1) && (YM2612.Status & 1)) 789 | YM2612.TimerAcnt = YM2612.TimerAL; 790 | */ 791 | 792 | //YM2612.Status &= (~data >> 4); // Reset du Status au cas ou c'est demandé 793 | YM2612.status &= (~data >> 4) & (data >> 2); // Reset Status 794 | 795 | YM2612.Mode = data; 796 | 797 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG1, 798 | // "Mode reg = %.2X", data); 799 | break; 800 | 801 | case 0x28: 802 | if ((nch = data & 3) == 3) 803 | return 1; 804 | 805 | if (data & 4) 806 | nch += 3; 807 | CH = &(YM2612.CHANNEL[nch]); 808 | 809 | YM2612_Special_Update(); 810 | 811 | if (data & 0x10) 812 | KEY_ON (CH, S0); // On appuie sur la touche pour le slot 1 813 | else 814 | KEY_OFF (CH, S0); // On relâche la touche pour le slot 1 815 | if (data & 0x20) 816 | KEY_ON (CH, S1); // On appuie sur la touche pour le slot 3 817 | else 818 | KEY_OFF (CH, S1); // On relâche la touche pour le slot 3 819 | if (data & 0x40) 820 | KEY_ON (CH, S2); // On appuie sur la touche pour le slot 2 821 | else 822 | KEY_OFF (CH, S2); // On relâche la touche pour le slot 2 823 | if (data & 0x80) 824 | KEY_ON (CH, S3); // On appuie sur la touche pour le slot 4 825 | else 826 | KEY_OFF (CH, S3); // On relâche la touche pour le slot 4 827 | 828 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG1, 829 | // "CHANNEL[%d] KEY %.1X", nch, ((data & 0xf0) >> 4)); 830 | break; 831 | 832 | case 0x2A: 833 | YM2612.DACdata = ((int)data - 0x80) << 7; // donnée du DAC 834 | break; 835 | 836 | case 0x2B: 837 | if (YM2612.DAC ^ (data & 0x80)) 838 | YM2612_Special_Update(); 839 | 840 | YM2612.DAC = data & 0x80; // Activate / Deactivate the DAC. 841 | break; 842 | } 843 | 844 | return 0; 845 | } 846 | 847 | 848 | 849 | /*********************************************** 850 | * fonctions de génération * 851 | ***********************************************/ 852 | 853 | 854 | static void Env_NULL_Next(slot_ * SL) 855 | { 856 | } 857 | 858 | 859 | static void Env_Attack_Next(slot_ * SL) 860 | { 861 | // Verified with Gynoug even in HQ (explode SFX) 862 | SL->Ecnt = ENV_DECAY; 863 | 864 | SL->Einc = SL->EincD; 865 | SL->Ecmp = SL->SLL; 866 | SL->Ecurp = DECAY; 867 | } 868 | 869 | 870 | static void Env_Decay_Next(slot_ * SL) 871 | { 872 | // Verified with Gynoug even in HQ (explode SFX) 873 | SL->Ecnt = SL->SLL; 874 | 875 | SL->Einc = SL->EincS; 876 | SL->Ecmp = ENV_END; 877 | SL->Ecurp = SUBSTAIN; 878 | } 879 | 880 | 881 | static void Env_Substain_Next (slot_ * SL) 882 | { 883 | if (SL->SEG & 8) // SSG envelope type 884 | { 885 | if (SL->SEG & 1) 886 | { 887 | SL->Ecnt = ENV_END; 888 | SL->Einc = 0; 889 | SL->Ecmp = ENV_END + 1; 890 | } 891 | else 892 | { 893 | // re KEY ON 894 | 895 | // SL->Fcnt = 0; 896 | // SL->ChgEnM = 0xFFFFFFFF; 897 | 898 | SL->Ecnt = 0; 899 | SL->Einc = SL->EincA; 900 | SL->Ecmp = ENV_DECAY; 901 | SL->Ecurp = ATTACK; 902 | } 903 | 904 | SL->SEG ^= (SL->SEG & 2) << 1; 905 | } 906 | else 907 | { 908 | SL->Ecnt = ENV_END; 909 | SL->Einc = 0; 910 | SL->Ecmp = ENV_END + 1; 911 | } 912 | } 913 | 914 | 915 | static void Env_Release_Next(slot_ * SL) 916 | { 917 | SL->Ecnt = ENV_END; 918 | SL->Einc = 0; 919 | SL->Ecmp = ENV_END + 1; 920 | } 921 | 922 | 923 | 924 | #define GET_CURRENT_PHASE \ 925 | { \ 926 | in0 = CH->SLOT[S0].Fcnt; \ 927 | in1 = CH->SLOT[S1].Fcnt; \ 928 | in2 = CH->SLOT[S2].Fcnt; \ 929 | in3 = CH->SLOT[S3].Fcnt; \ 930 | } 931 | 932 | 933 | #define UPDATE_PHASE \ 934 | { \ 935 | CH->SLOT[S0].Fcnt += CH->SLOT[S0].Finc; \ 936 | CH->SLOT[S1].Fcnt += CH->SLOT[S1].Finc; \ 937 | CH->SLOT[S2].Fcnt += CH->SLOT[S2].Finc; \ 938 | CH->SLOT[S3].Fcnt += CH->SLOT[S3].Finc; \ 939 | } 940 | 941 | 942 | #define UPDATE_PHASE_LFO \ 943 | if ((freq_LFO = (CH->FMS * LFO_FREQ_UP[i]) >> (LFO_HBITS - 1))) \ 944 | { \ 945 | CH->SLOT[S0].Fcnt += CH->SLOT[S0].Finc + ((CH->SLOT[S0].Finc * freq_LFO) >> LFO_FMS_LBITS); \ 946 | CH->SLOT[S1].Fcnt += CH->SLOT[S1].Finc + ((CH->SLOT[S1].Finc * freq_LFO) >> LFO_FMS_LBITS); \ 947 | CH->SLOT[S2].Fcnt += CH->SLOT[S2].Finc + ((CH->SLOT[S2].Finc * freq_LFO) >> LFO_FMS_LBITS); \ 948 | CH->SLOT[S3].Fcnt += CH->SLOT[S3].Finc + ((CH->SLOT[S3].Finc * freq_LFO) >> LFO_FMS_LBITS); \ 949 | } \ 950 | else \ 951 | { \ 952 | CH->SLOT[S0].Fcnt += CH->SLOT[S0].Finc; \ 953 | CH->SLOT[S1].Fcnt += CH->SLOT[S1].Finc; \ 954 | CH->SLOT[S2].Fcnt += CH->SLOT[S2].Finc; \ 955 | CH->SLOT[S3].Fcnt += CH->SLOT[S3].Finc; \ 956 | } 957 | 958 | 959 | // Commented out from Gens Rerecording 960 | /* 961 | #define GET_CURRENT_ENV \ 962 | if (CH->SLOT[S0].SEG & 4) \ 963 | { \ 964 | if ((en0 = ENV_TAB[(CH->SLOT[S0].Ecnt >> ENV_LBITS)] + CH->SLOT[S0].TLL) > ENV_MASK) en0 = 0; \ 965 | else en0 ^= ENV_MASK; \ 966 | } \ 967 | else en0 = ENV_TAB[(CH->SLOT[S0].Ecnt >> ENV_LBITS)] + CH->SLOT[S0].TLL; \ 968 | if (CH->SLOT[S1].SEG & 4) \ 969 | { \ 970 | if ((en1 = ENV_TAB[(CH->SLOT[S1].Ecnt >> ENV_LBITS)] + CH->SLOT[S1].TLL) > ENV_MASK) en1 = 0; \ 971 | else en1 ^= ENV_MASK; \ 972 | } \ 973 | else en1 = ENV_TAB[(CH->SLOT[S1].Ecnt >> ENV_LBITS)] + CH->SLOT[S1].TLL; \ 974 | if (CH->SLOT[S2].SEG & 4) \ 975 | { \ 976 | if ((en2 = ENV_TAB[(CH->SLOT[S2].Ecnt >> ENV_LBITS)] + CH->SLOT[S2].TLL) > ENV_MASK) en2 = 0; \ 977 | else en2 ^= ENV_MASK; \ 978 | } \ 979 | else en2 = ENV_TAB[(CH->SLOT[S2].Ecnt >> ENV_LBITS)] + CH->SLOT[S2].TLL; \ 980 | if (CH->SLOT[S3].SEG & 4) \ 981 | { \ 982 | if ((en3 = ENV_TAB[(CH->SLOT[S3].Ecnt >> ENV_LBITS)] + CH->SLOT[S3].TLL) > ENV_MASK) en3 = 0; \ 983 | else en3 ^= ENV_MASK; \ 984 | } \ 985 | else en3 = ENV_TAB[(CH->SLOT[S3].Ecnt >> ENV_LBITS)] + CH->SLOT[S3].TLL; 986 | */ 987 | 988 | // New version from Gens Rerecording 989 | #define GET_CURRENT_ENV \ 990 | en0 = ENV_TAB[(CH->SLOT[S0].Ecnt >> ENV_LBITS)] + CH->SLOT[S0].TLL; \ 991 | en1 = ENV_TAB[(CH->SLOT[S1].Ecnt >> ENV_LBITS)] + CH->SLOT[S1].TLL; \ 992 | en2 = ENV_TAB[(CH->SLOT[S2].Ecnt >> ENV_LBITS)] + CH->SLOT[S2].TLL; \ 993 | en3 = ENV_TAB[(CH->SLOT[S3].Ecnt >> ENV_LBITS)] + CH->SLOT[S3].TLL; 994 | 995 | // Commented out from Gens Rerecording 996 | /* 997 | #define GET_CURRENT_ENV_LFO \ 998 | env_LFO = LFO_ENV_UP[i]; \ 999 | \ 1000 | if (CH->SLOT[S0].SEG & 4) \ 1001 | { \ 1002 | if ((en0 = ENV_TAB[(CH->SLOT[S0].Ecnt >> ENV_LBITS)] + CH->SLOT[S0].TLL) > ENV_MASK) en0 = 0; \ 1003 | else en0 = (en0 ^ ENV_MASK) + (env_LFO >> CH->SLOT[S0].AMS); \ 1004 | } \ 1005 | else en0 = ENV_TAB[(CH->SLOT[S0].Ecnt >> ENV_LBITS)] + CH->SLOT[S0].TLL + (env_LFO >> CH->SLOT[S0].AMS); \ 1006 | if (CH->SLOT[S1].SEG & 4) \ 1007 | { \ 1008 | if ((en1 = ENV_TAB[(CH->SLOT[S1].Ecnt >> ENV_LBITS)] + CH->SLOT[S1].TLL) > ENV_MASK) en1 = 0; \ 1009 | else en1 = (en1 ^ ENV_MASK) + (env_LFO >> CH->SLOT[S1].AMS); \ 1010 | } \ 1011 | else en1 = ENV_TAB[(CH->SLOT[S1].Ecnt >> ENV_LBITS)] + CH->SLOT[S1].TLL + (env_LFO >> CH->SLOT[S1].AMS); \ 1012 | if (CH->SLOT[S2].SEG & 4) \ 1013 | { \ 1014 | if ((en2 = ENV_TAB[(CH->SLOT[S2].Ecnt >> ENV_LBITS)] + CH->SLOT[S2].TLL) > ENV_MASK) en2 = 0; \ 1015 | else en2 = (en2 ^ ENV_MASK) + (env_LFO >> CH->SLOT[S2].AMS); \ 1016 | } \ 1017 | else en2 = ENV_TAB[(CH->SLOT[S2].Ecnt >> ENV_LBITS)] + CH->SLOT[S2].TLL + (env_LFO >> CH->SLOT[S2].AMS); \ 1018 | if (CH->SLOT[S3].SEG & 4) \ 1019 | { \ 1020 | if ((en3 = ENV_TAB[(CH->SLOT[S3].Ecnt >> ENV_LBITS)] + CH->SLOT[S3].TLL) > ENV_MASK) en3 = 0; \ 1021 | else en3 = (en3 ^ ENV_MASK) + (env_LFO >> CH->SLOT[S3].AMS); \ 1022 | } \ 1023 | else en3 = ENV_TAB[(CH->SLOT[S3].Ecnt >> ENV_LBITS)] + CH->SLOT[S3].TLL + (env_LFO >> CH->SLOT[S3].AMS); 1024 | */ 1025 | 1026 | // New version from Gens Rerecording 1027 | #define GET_CURRENT_ENV_LFO \ 1028 | env_LFO = LFO_ENV_UP[i]; \ 1029 | en0 = ENV_TAB[(CH->SLOT[S0].Ecnt >> ENV_LBITS)] + CH->SLOT[S0].TLL + (env_LFO >> CH->SLOT[S0].AMS); \ 1030 | en1 = ENV_TAB[(CH->SLOT[S1].Ecnt >> ENV_LBITS)] + CH->SLOT[S1].TLL + (env_LFO >> CH->SLOT[S1].AMS); \ 1031 | en2 = ENV_TAB[(CH->SLOT[S2].Ecnt >> ENV_LBITS)] + CH->SLOT[S2].TLL + (env_LFO >> CH->SLOT[S2].AMS); \ 1032 | en3 = ENV_TAB[(CH->SLOT[S3].Ecnt >> ENV_LBITS)] + CH->SLOT[S3].TLL + (env_LFO >> CH->SLOT[S3].AMS); 1033 | 1034 | 1035 | #define UPDATE_ENV \ 1036 | { \ 1037 | if ((CH->SLOT[S0].Ecnt += CH->SLOT[S0].Einc) >= CH->SLOT[S0].Ecmp) \ 1038 | ENV_NEXT_EVENT[CH->SLOT[S0].Ecurp](&(CH->SLOT[S0])); \ 1039 | if ((CH->SLOT[S1].Ecnt += CH->SLOT[S1].Einc) >= CH->SLOT[S1].Ecmp) \ 1040 | ENV_NEXT_EVENT[CH->SLOT[S1].Ecurp](&(CH->SLOT[S1])); \ 1041 | if ((CH->SLOT[S2].Ecnt += CH->SLOT[S2].Einc) >= CH->SLOT[S2].Ecmp) \ 1042 | ENV_NEXT_EVENT[CH->SLOT[S2].Ecurp](&(CH->SLOT[S2])); \ 1043 | if ((CH->SLOT[S3].Ecnt += CH->SLOT[S3].Einc) >= CH->SLOT[S3].Ecmp) \ 1044 | ENV_NEXT_EVENT[CH->SLOT[S3].Ecurp](&(CH->SLOT[S3])); \ 1045 | } 1046 | 1047 | #define DO_LIMIT \ 1048 | { \ 1049 | if (CH->OUTd > LIMIT_CH_OUT) \ 1050 | CH->OUTd = LIMIT_CH_OUT; \ 1051 | else if (CH->OUTd < -LIMIT_CH_OUT) \ 1052 | CH->OUTd = -LIMIT_CH_OUT; \ 1053 | } 1054 | 1055 | 1056 | #define DO_FEEDBACK0 \ 1057 | { \ 1058 | in0 += CH->S0_OUT[0] >> CH->FB; \ 1059 | CH->S0_OUT[0] = SIN_TAB[(in0 >> SIN_LBITS) & SIN_MASK][en0]; \ 1060 | } 1061 | 1062 | #define DO_FEEDBACK \ 1063 | { \ 1064 | in0 += (CH->S0_OUT[0] + CH->S0_OUT[1]) >> CH->FB; \ 1065 | CH->S0_OUT[1] = CH->S0_OUT[0]; \ 1066 | CH->S0_OUT[0] = SIN_TAB[(in0 >> SIN_LBITS) & SIN_MASK][en0]; \ 1067 | } 1068 | 1069 | #define DO_FEEDBACK2 \ 1070 | { \ 1071 | in0 += (CH->S0_OUT[0] + (CH->S0_OUT[0] >> 2) + CH->S0_OUT[1]) >> CH->FB; \ 1072 | CH->S0_OUT[1] = CH->S0_OUT[0] >> 2; \ 1073 | CH->S0_OUT[0] = SIN_TAB[(in0 >> SIN_LBITS) & SIN_MASK][en0]; \ 1074 | } 1075 | 1076 | #define DO_FEEDBACK3 \ 1077 | { \ 1078 | in0 += (CH->S0_OUT[0] + CH->S0_OUT[1] + CH->S0_OUT[2] + CH->S0_OUT[3]) >> CH->FB; \ 1079 | CH->S0_OUT[3] = CH->S0_OUT[2] >> 1; \ 1080 | CH->S0_OUT[2] = CH->S0_OUT[1] >> 1; \ 1081 | CH->S0_OUT[1] = CH->S0_OUT[0] >> 1; \ 1082 | CH->S0_OUT[0] = SIN_TAB[(in0 >> SIN_LBITS) & SIN_MASK][en0]; \ 1083 | } 1084 | 1085 | 1086 | #define DO_ALGO_0 \ 1087 | { \ 1088 | DO_FEEDBACK \ 1089 | in1 += CH->S0_OUT[0]; \ 1090 | in2 += SIN_TAB[(in1 >> SIN_LBITS) & SIN_MASK][en1]; \ 1091 | in3 += SIN_TAB[(in2 >> SIN_LBITS) & SIN_MASK][en2]; \ 1092 | CH->OUTd = (SIN_TAB[(in3 >> SIN_LBITS) & SIN_MASK][en3]) >> OUT_SHIFT; \ 1093 | } 1094 | 1095 | #define DO_ALGO_1 \ 1096 | { \ 1097 | DO_FEEDBACK \ 1098 | in2 += CH->S0_OUT[0] + SIN_TAB[(in1 >> SIN_LBITS) & SIN_MASK][en1]; \ 1099 | in3 += SIN_TAB[(in2 >> SIN_LBITS) & SIN_MASK][en2]; \ 1100 | CH->OUTd = (SIN_TAB[(in3 >> SIN_LBITS) & SIN_MASK][en3]) >> OUT_SHIFT; \ 1101 | } 1102 | 1103 | #define DO_ALGO_2 \ 1104 | { \ 1105 | DO_FEEDBACK \ 1106 | in2 += SIN_TAB[(in1 >> SIN_LBITS) & SIN_MASK][en1]; \ 1107 | in3 += CH->S0_OUT[0] + SIN_TAB[(in2 >> SIN_LBITS) & SIN_MASK][en2]; \ 1108 | CH->OUTd = (SIN_TAB[(in3 >> SIN_LBITS) & SIN_MASK][en3]) >> OUT_SHIFT; \ 1109 | } 1110 | 1111 | #define DO_ALGO_3 \ 1112 | { \ 1113 | DO_FEEDBACK \ 1114 | in1 += CH->S0_OUT[0]; \ 1115 | in3 += SIN_TAB[(in1 >> SIN_LBITS) & SIN_MASK][en1] + \ 1116 | SIN_TAB[(in2 >> SIN_LBITS) & SIN_MASK][en2]; \ 1117 | CH->OUTd = (SIN_TAB[(in3 >> SIN_LBITS) & SIN_MASK][en3]) >> OUT_SHIFT; \ 1118 | } 1119 | 1120 | #define DO_ALGO_4 \ 1121 | { \ 1122 | DO_FEEDBACK \ 1123 | in1 += CH->S0_OUT[0]; \ 1124 | in3 += SIN_TAB[(in2 >> SIN_LBITS) & SIN_MASK][en2]; \ 1125 | CH->OUTd = ((int)SIN_TAB[(in3 >> SIN_LBITS) & SIN_MASK][en3] + \ 1126 | (int)SIN_TAB[(in1 >> SIN_LBITS) & SIN_MASK][en1]) >> OUT_SHIFT; \ 1127 | DO_LIMIT \ 1128 | } 1129 | 1130 | #define DO_ALGO_5 \ 1131 | { \ 1132 | DO_FEEDBACK \ 1133 | in1 += CH->S0_OUT[0]; \ 1134 | in2 += CH->S0_OUT[0]; \ 1135 | in3 += CH->S0_OUT[0]; \ 1136 | CH->OUTd = ((int)SIN_TAB[(in3 >> SIN_LBITS) & SIN_MASK][en3] + \ 1137 | (int)SIN_TAB[(in1 >> SIN_LBITS) & SIN_MASK][en1] + \ 1138 | (int)SIN_TAB[(in2 >> SIN_LBITS) & SIN_MASK][en2]) >> OUT_SHIFT; \ 1139 | DO_LIMIT \ 1140 | } 1141 | 1142 | #define DO_ALGO_6 \ 1143 | { \ 1144 | DO_FEEDBACK \ 1145 | in1 += CH->S0_OUT[0]; \ 1146 | CH->OUTd = ((int)SIN_TAB[(in3 >> SIN_LBITS) & SIN_MASK][en3] + \ 1147 | (int)SIN_TAB[(in1 >> SIN_LBITS) & SIN_MASK][en1] + \ 1148 | (int)SIN_TAB[(in2 >> SIN_LBITS) & SIN_MASK][en2]) >> OUT_SHIFT; \ 1149 | DO_LIMIT \ 1150 | } 1151 | 1152 | #define DO_ALGO_7 \ 1153 | { \ 1154 | DO_FEEDBACK \ 1155 | CH->OUTd = ((int)SIN_TAB[(in3 >> SIN_LBITS) & SIN_MASK][en3] + \ 1156 | (int)SIN_TAB[(in1 >> SIN_LBITS) & SIN_MASK][en1] + \ 1157 | (int)SIN_TAB[(in2 >> SIN_LBITS) & SIN_MASK][en2] + \ 1158 | CH->S0_OUT[0]) >> OUT_SHIFT; \ 1159 | DO_LIMIT \ 1160 | } 1161 | 1162 | 1163 | #define DO_OUTPUT \ 1164 | { \ 1165 | buf[0][i] += (int)(CH->OUTd & CH->LEFT); \ 1166 | buf[1][i] += (int)(CH->OUTd & CH->RIGHT); \ 1167 | } 1168 | 1169 | #define DO_OUTPUT_INT0 \ 1170 | { \ 1171 | if ((int_cnt += YM2612.Inter_Step) & 0x04000) \ 1172 | { \ 1173 | int_cnt &= 0x3FFF; \ 1174 | buf[0][i] += (int)(CH->OUTd & CH->LEFT); \ 1175 | buf[1][i] += (int)(CH->OUTd & CH->RIGHT); \ 1176 | } \ 1177 | else i--; \ 1178 | } 1179 | 1180 | #define DO_OUTPUT_INT1 \ 1181 | { \ 1182 | CH->Old_OUTd = (CH->OUTd + CH->Old_OUTd) >> 1; \ 1183 | if ((int_cnt += YM2612.Inter_Step) & 0x04000) \ 1184 | { \ 1185 | int_cnt &= 0x3FFF; \ 1186 | buf[0][i] += (int)(CH->Old_OUTd & CH->LEFT); \ 1187 | buf[1][i] += (int)(CH->Old_OUTd & CH->RIGHT); \ 1188 | } \ 1189 | else i--; \ 1190 | } 1191 | 1192 | #define DO_OUTPUT_INT2 \ 1193 | { \ 1194 | if ((int_cnt += YM2612.Inter_Step) & 0x04000) \ 1195 | { \ 1196 | int_cnt &= 0x3FFF; \ 1197 | CH->Old_OUTd = (CH->OUTd + CH->Old_OUTd) >> 1; \ 1198 | buf[0][i] += (int)(CH->Old_OUTd & CH->LEFT); \ 1199 | buf[1][i] += (int)(CH->Old_OUTd & CH->RIGHT); \ 1200 | } \ 1201 | else i--; \ 1202 | CH->Old_OUTd = CH->OUTd; \ 1203 | } 1204 | 1205 | #define DO_OUTPUT_INT \ 1206 | { \ 1207 | if ((int_cnt += YM2612.Inter_Step) & 0x04000) \ 1208 | { \ 1209 | int_cnt &= 0x3FFF; \ 1210 | CH->Old_OUTd = (((int_cnt ^ 0x3FFF) * CH->OUTd) + \ 1211 | (int_cnt * CH->Old_OUTd)) >> 14; \ 1212 | buf[0][i] += (int)(CH->Old_OUTd & CH->LEFT); \ 1213 | buf[1][i] += (int)(CH->Old_OUTd & CH->RIGHT); \ 1214 | } \ 1215 | else i--; \ 1216 | CH->Old_OUTd = CH->OUTd; \ 1217 | } 1218 | 1219 | 1220 | template 1221 | static void T_Update_Chan(channel_ *CH, int **buf, int length) 1222 | { 1223 | // Check if the channel has reached the end of the update. 1224 | { 1225 | int not_end = (CH->SLOT[S3].Ecnt - ENV_END); 1226 | 1227 | // Special cases. 1228 | // Copied from Game_Music_Emu v0.5.2. 1229 | if (algo == 7) 1230 | not_end |= (CH->SLOT[S0].Ecnt - ENV_END); 1231 | if (algo >= 5) 1232 | not_end |= (CH->SLOT[S2].Ecnt - ENV_END); 1233 | if (algo >= 4) 1234 | not_end |= (CH->SLOT[S1].Ecnt - ENV_END); 1235 | 1236 | if (not_end == 0) 1237 | return; 1238 | } 1239 | 1240 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 1241 | // "Algo %d len = %d", algo, length); 1242 | 1243 | for (int i = 0; i < length; i++) 1244 | { 1245 | GET_CURRENT_PHASE; 1246 | UPDATE_PHASE; 1247 | GET_CURRENT_ENV; 1248 | UPDATE_ENV; 1249 | 1250 | switch (algo) 1251 | { 1252 | case 0: 1253 | DO_ALGO_0; 1254 | break; 1255 | case 1: 1256 | DO_ALGO_1; 1257 | break; 1258 | case 2: 1259 | DO_ALGO_2; 1260 | break; 1261 | case 3: 1262 | DO_ALGO_3; 1263 | break; 1264 | case 4: 1265 | DO_ALGO_4; 1266 | break; 1267 | case 5: 1268 | DO_ALGO_5; 1269 | break; 1270 | case 6: 1271 | DO_ALGO_6; 1272 | break; 1273 | case 7: 1274 | DO_ALGO_7; 1275 | break; 1276 | default: 1277 | assert(algo >= 0 && algo <= 7); 1278 | break; 1279 | } 1280 | 1281 | DO_OUTPUT; 1282 | } 1283 | } 1284 | 1285 | 1286 | template 1287 | static void T_Update_Chan_LFO(channel_ *CH, int **buf, int length) 1288 | { 1289 | // Check if the channel has reached the end of the update. 1290 | { 1291 | int not_end = (CH->SLOT[S3].Ecnt - ENV_END); 1292 | 1293 | // Special cases. 1294 | // Copied from Game_Music_Emu v0.5.2. 1295 | if (algo == 7) 1296 | not_end |= (CH->SLOT[S0].Ecnt - ENV_END); 1297 | if (algo >= 5) 1298 | not_end |= (CH->SLOT[S2].Ecnt - ENV_END); 1299 | if (algo >= 4) 1300 | not_end |= (CH->SLOT[S1].Ecnt - ENV_END); 1301 | 1302 | if (not_end == 0) 1303 | return; 1304 | } 1305 | 1306 | int env_LFO, freq_LFO; 1307 | 1308 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 1309 | // "Algo %d LFO len = %d", algo, length); 1310 | 1311 | for (int i = 0; i < length; i++) 1312 | { 1313 | GET_CURRENT_PHASE; 1314 | UPDATE_PHASE_LFO; 1315 | GET_CURRENT_ENV_LFO; 1316 | UPDATE_ENV; 1317 | 1318 | switch (algo) 1319 | { 1320 | case 0: 1321 | DO_ALGO_0; 1322 | break; 1323 | case 1: 1324 | DO_ALGO_1; 1325 | break; 1326 | case 2: 1327 | DO_ALGO_2; 1328 | break; 1329 | case 3: 1330 | DO_ALGO_3; 1331 | break; 1332 | case 4: 1333 | DO_ALGO_4; 1334 | break; 1335 | case 5: 1336 | DO_ALGO_5; 1337 | break; 1338 | case 6: 1339 | DO_ALGO_6; 1340 | break; 1341 | case 7: 1342 | DO_ALGO_7; 1343 | break; 1344 | default: 1345 | assert(algo >= 0 && algo <= 7); 1346 | break; 1347 | } 1348 | 1349 | DO_OUTPUT; 1350 | } 1351 | } 1352 | 1353 | 1354 | /****************************************************** 1355 | * Interpolated output * 1356 | *****************************************************/ 1357 | 1358 | 1359 | template 1360 | static void T_Update_Chan_Int(channel_ *CH, int **buf, int length) 1361 | { 1362 | // Check if the channel has reached the end of the update. 1363 | { 1364 | int not_end = (CH->SLOT[S3].Ecnt - ENV_END); 1365 | 1366 | // Special cases. 1367 | // Copied from Game_Music_Emu v0.5.2. 1368 | if (algo == 7) 1369 | not_end |= (CH->SLOT[S0].Ecnt - ENV_END); 1370 | if (algo >= 5) 1371 | not_end |= (CH->SLOT[S2].Ecnt - ENV_END); 1372 | if (algo >= 4) 1373 | not_end |= (CH->SLOT[S1].Ecnt - ENV_END); 1374 | 1375 | if (not_end == 0) 1376 | return; 1377 | } 1378 | 1379 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 1380 | // "Algo %d Int len = %d", algo, length); 1381 | 1382 | int_cnt = YM2612.Inter_Cnt; 1383 | 1384 | for (int i = 0; i < length; i++) 1385 | { 1386 | GET_CURRENT_PHASE; 1387 | UPDATE_PHASE; 1388 | GET_CURRENT_ENV; 1389 | UPDATE_ENV; 1390 | 1391 | switch (algo) 1392 | { 1393 | case 0: 1394 | DO_ALGO_0; 1395 | break; 1396 | case 1: 1397 | DO_ALGO_1; 1398 | break; 1399 | case 2: 1400 | DO_ALGO_2; 1401 | break; 1402 | case 3: 1403 | DO_ALGO_3; 1404 | break; 1405 | case 4: 1406 | DO_ALGO_4; 1407 | break; 1408 | case 5: 1409 | DO_ALGO_5; 1410 | break; 1411 | case 6: 1412 | DO_ALGO_6; 1413 | break; 1414 | case 7: 1415 | DO_ALGO_7; 1416 | break; 1417 | default: 1418 | assert(algo >= 0 && algo <= 7); 1419 | break; 1420 | } 1421 | 1422 | DO_OUTPUT_INT; 1423 | } 1424 | } 1425 | 1426 | 1427 | template 1428 | static void T_Update_Chan_LFO_Int(channel_ *CH, int **buf, int length) 1429 | { 1430 | // Check if the channel has reached the end of the update. 1431 | { 1432 | int not_end = (CH->SLOT[S3].Ecnt - ENV_END); 1433 | 1434 | // Special cases. 1435 | // Copied from Game_Music_Emu v0.5.2. 1436 | if (algo == 7) 1437 | not_end |= (CH->SLOT[S0].Ecnt - ENV_END); 1438 | if (algo >= 5) 1439 | not_end |= (CH->SLOT[S2].Ecnt - ENV_END); 1440 | if (algo >= 4) 1441 | not_end |= (CH->SLOT[S1].Ecnt - ENV_END); 1442 | 1443 | if (not_end == 0) 1444 | return; 1445 | } 1446 | 1447 | int_cnt = YM2612.Inter_Cnt; 1448 | int env_LFO, freq_LFO; 1449 | 1450 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 1451 | // "Algo %d LFO Int len = %d", algo, length); 1452 | 1453 | for (int i = 0; i < length; i++) 1454 | { 1455 | GET_CURRENT_PHASE; 1456 | UPDATE_PHASE_LFO; 1457 | GET_CURRENT_ENV_LFO; 1458 | UPDATE_ENV; 1459 | 1460 | switch (algo) 1461 | { 1462 | case 0: 1463 | DO_ALGO_0; 1464 | break; 1465 | case 1: 1466 | DO_ALGO_1; 1467 | break; 1468 | case 2: 1469 | DO_ALGO_2; 1470 | break; 1471 | case 3: 1472 | DO_ALGO_3; 1473 | break; 1474 | case 4: 1475 | DO_ALGO_4; 1476 | break; 1477 | case 5: 1478 | DO_ALGO_5; 1479 | break; 1480 | case 6: 1481 | DO_ALGO_6; 1482 | break; 1483 | case 7: 1484 | DO_ALGO_7; 1485 | break; 1486 | default: 1487 | assert(algo >= 0 && algo <= 7); 1488 | break; 1489 | } 1490 | 1491 | DO_OUTPUT_INT; 1492 | } 1493 | } 1494 | 1495 | 1496 | // Update Channel functions pointer table 1497 | typedef void (*Update_Chan_Fn)(channel_ *CH, int **buf, int length); 1498 | 1499 | static const Update_Chan_Fn UPDATE_CHAN[8*8] = 1500 | { 1501 | T_Update_Chan<0>, 1502 | T_Update_Chan<1>, 1503 | T_Update_Chan<2>, 1504 | T_Update_Chan<3>, 1505 | T_Update_Chan<4>, 1506 | T_Update_Chan<5>, 1507 | T_Update_Chan<6>, 1508 | T_Update_Chan<7>, 1509 | 1510 | T_Update_Chan_LFO<0>, 1511 | T_Update_Chan_LFO<1>, 1512 | T_Update_Chan_LFO<2>, 1513 | T_Update_Chan_LFO<3>, 1514 | T_Update_Chan_LFO<4>, 1515 | T_Update_Chan_LFO<5>, 1516 | T_Update_Chan_LFO<6>, 1517 | T_Update_Chan_LFO<7>, 1518 | 1519 | T_Update_Chan_Int<0>, 1520 | T_Update_Chan_Int<1>, 1521 | T_Update_Chan_Int<2>, 1522 | T_Update_Chan_Int<3>, 1523 | T_Update_Chan_Int<4>, 1524 | T_Update_Chan_Int<5>, 1525 | T_Update_Chan_Int<6>, 1526 | T_Update_Chan_Int<7>, 1527 | 1528 | T_Update_Chan_LFO_Int<0>, 1529 | T_Update_Chan_LFO_Int<1>, 1530 | T_Update_Chan_LFO_Int<2>, 1531 | T_Update_Chan_LFO_Int<3>, 1532 | T_Update_Chan_LFO_Int<4>, 1533 | T_Update_Chan_LFO_Int<5>, 1534 | T_Update_Chan_LFO_Int<6>, 1535 | T_Update_Chan_LFO_Int<7>, 1536 | }; 1537 | 1538 | 1539 | /*********************************************** 1540 | * Public functions. * 1541 | ***********************************************/ 1542 | 1543 | 1544 | /** 1545 | * YM2612_Init(): Initialize the YM2612. 1546 | * @param Clock YM2612 clock frequency. 1547 | * @param Rate Sound rate. 1548 | * @param Interpolation Enable YM2612 Interpolation, ("Improved" YM2612 emulation.) 1549 | */ 1550 | // Initialisation de l'émulateur YM2612 1551 | int YM2612_Init(int Clock, int Rate, int Interpolation) 1552 | { 1553 | int i, j; 1554 | double x; 1555 | 1556 | if ((Rate == 0) || (Clock == 0)) 1557 | return 1; 1558 | 1559 | // Clear the YM2612 struct. 1560 | memset(&YM2612, 0x00, sizeof(YM2612)); 1561 | 1562 | YM2612.Clock = Clock; 1563 | YM2612.Rate = Rate; 1564 | 1565 | // 144 = 12 * (prescale * 2) = 12 * 6 * 2 1566 | // prescale set to 6 by default 1567 | 1568 | YM2612.Frequence = ((double)(YM2612.Clock) / (double)(YM2612.Rate)) / 144.0; 1569 | YM2612.TimerBase = (int)(YM2612.Frequence * 4096.0); 1570 | 1571 | if ((Interpolation) && (YM2612.Frequence > 1.0)) 1572 | { 1573 | YM2612.Inter_Step = (unsigned int)((1.0 / YM2612.Frequence) * (double)(0x4000)); 1574 | YM2612.Inter_Cnt = 0; 1575 | 1576 | // We recalculate rate and frequence after interpolation 1577 | 1578 | YM2612.Rate = YM2612.Clock / 144.0; 1579 | YM2612.Frequence = 1.0; 1580 | } 1581 | else 1582 | { 1583 | YM2612.Inter_Step = 0x4000; 1584 | YM2612.Inter_Cnt = 0; 1585 | } 1586 | 1587 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG2, 1588 | // "YM2612 frequency = %g, rate = %d, interp step = %.8X", 1589 | // YM2612.Frequence, YM2612.Rate, YM2612.Inter_Step); 1590 | 1591 | // Tableau TL : 1592 | // [0 - 4095] = +output [4095 - ...] = +output overflow (fill with 0) 1593 | // [12288 - 16383] = -output [16384 - ...] = -output overflow (fill with 0) 1594 | 1595 | #ifdef ESP32_SYNTH 1596 | TL_TAB = (int *)heap_caps_malloc(TL_LENGTH * 2 * sizeof(int), MALLOC_CAP_8BIT); 1597 | if(TL_TAB == NULL) printf("TL_TAB alloc error!\n"); 1598 | memset(TL_TAB, 0x00, TL_LENGTH * 2 * sizeof(int)); 1599 | #endif 1600 | 1601 | for (i = 0; i < TL_LENGTH; i++) 1602 | { 1603 | if (i >= PG_CUT_OFF) // YM2612 cut off sound after 78 dB (14 bits output ?) 1604 | { 1605 | TL_TAB[TL_LENGTH + i] = TL_TAB[i] = 0; 1606 | } 1607 | else 1608 | { 1609 | x = MAX_OUT; // Max output 1610 | x /= pow(10, (ENV_STEP * i) / 20); // Decibel -> Voltage 1611 | 1612 | TL_TAB[i] = (int) x; 1613 | TL_TAB[TL_LENGTH + i] = -TL_TAB[i]; 1614 | } 1615 | 1616 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG3, 1617 | // "TL_TAB[%d] = %.8X TL_TAB[%d] = %.8X", 1618 | // i, TL_TAB[i], TL_LENGTH + i, TL_TAB[TL_LENGTH + i]); 1619 | } 1620 | 1621 | // Tableau SIN : 1622 | // SIN_TAB[x][y] = sin(x) * y; 1623 | // x = phase and y = volume 1624 | 1625 | SIN_TAB[0] = SIN_TAB[SIN_LENGTH / 2] = &TL_TAB[(int) PG_CUT_OFF]; 1626 | 1627 | for (i = 1; i <= SIN_LENGTH / 4; i++) 1628 | { 1629 | x = sin(2.0 * PI * (double) (i) / (double) (SIN_LENGTH)); // Sinus 1630 | x = 20 * log10(1 / x); // convert to dB 1631 | 1632 | j = (int) (x / ENV_STEP); // Get TL range 1633 | 1634 | if (j > PG_CUT_OFF) 1635 | j = (int) PG_CUT_OFF; 1636 | 1637 | SIN_TAB[i] = SIN_TAB[(SIN_LENGTH / 2) - i] = &TL_TAB[j]; 1638 | SIN_TAB[(SIN_LENGTH / 2) + i] = SIN_TAB[SIN_LENGTH - i] = &TL_TAB[TL_LENGTH + j]; 1639 | 1640 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG3, 1641 | // "SIN[%d][0] = %.8X SIN[%d][0] = %.8X SIN[%d][0] = %.8X SIN[%d][0] = %.8X", 1642 | // i, SIN_TAB[i][0], (SIN_LENGTH / 2) - i, 1643 | // SIN_TAB[(SIN_LENGTH / 2) - i][0], (SIN_LENGTH / 2) + i, 1644 | // SIN_TAB[(SIN_LENGTH / 2) + i][0], SIN_LENGTH - i, 1645 | // SIN_TAB[SIN_LENGTH - i][0]); 1646 | } 1647 | 1648 | // Tableau LFO (LFO wav) : 1649 | 1650 | for (i = 0; i < LFO_LENGTH; i++) 1651 | { 1652 | x = sin (2.0 * PI * (double) (i) / (double) (LFO_LENGTH)); // Sinus 1653 | x += 1.0; 1654 | x /= 2.0; // positive only 1655 | x *= 11.8 / ENV_STEP; // ajusted to MAX enveloppe modulation 1656 | 1657 | LFO_ENV_TAB[i] = (int) x; 1658 | 1659 | x = sin(2.0 * PI * (double) (i) / (double) (LFO_LENGTH)); // Sinus 1660 | x *= (double) ((1 << (LFO_HBITS - 1)) - 1); 1661 | 1662 | LFO_FREQ_TAB[i] = (int) x; 1663 | 1664 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG3, 1665 | // "LFO[%d] = %.8X", i, LFO_ENV_TAB[i]); 1666 | } 1667 | 1668 | // Tableau Enveloppe : 1669 | // ENV_TAB[0] -> ENV_TAB[ENV_LENGTH - 1] = attack curve 1670 | // ENV_TAB[ENV_LENGTH] -> ENV_TAB[2 * ENV_LENGTH - 1] = decay curve 1671 | 1672 | #ifdef ESP32_SYNTH 1673 | ENV_TAB = (unsigned int *)heap_caps_malloc((2 * ENV_LENGTH + 8) * sizeof(unsigned int), MALLOC_CAP_8BIT); 1674 | if(ENV_TAB == NULL) printf("ENV_TAB alloc error!\n"); 1675 | memset(ENV_TAB, 0x00, (2 * ENV_LENGTH + 8) * sizeof(unsigned int)); 1676 | #endif 1677 | for (i = 0; i < ENV_LENGTH; i++) 1678 | { 1679 | // Attack curve (x^8 - music level 2 Vectorman 2) 1680 | x = pow(((double) ((ENV_LENGTH - 1) - i) / (double) (ENV_LENGTH)), 8); 1681 | x *= ENV_LENGTH; 1682 | 1683 | ENV_TAB[i] = (int) x; 1684 | 1685 | // Decay curve (just linear) 1686 | x = pow(((double) (i) / (double) (ENV_LENGTH)), 1); 1687 | x *= ENV_LENGTH; 1688 | 1689 | ENV_TAB[ENV_LENGTH + i] = (int) x; 1690 | 1691 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG3, 1692 | // "ATTACK[%d] = %d DECAY[%d] = %d", 1693 | // i, ENV_TAB[i], i, ENV_TAB[ENV_LENGTH + i]); 1694 | } 1695 | 1696 | ENV_TAB[ENV_END >> ENV_LBITS] = ENV_LENGTH - 1; // for the stopped state 1697 | 1698 | // Tableau pour la conversion Attack -> Decay and Decay -> Attack 1699 | 1700 | for (i = 0, j = ENV_LENGTH - 1; i < ENV_LENGTH; i++) 1701 | { 1702 | while (j && (ENV_TAB[j] < (unsigned) i)) 1703 | j--; 1704 | 1705 | DECAY_TO_ATTACK[i] = j << ENV_LBITS; 1706 | } 1707 | 1708 | // Tableau pour le Substain Level 1709 | 1710 | for (i = 0; i < 15; i++) 1711 | { 1712 | x = i * 3; // 3 and not 6 (Mickey Mania first music for test) 1713 | x /= ENV_STEP; 1714 | 1715 | j = (int) x; 1716 | j <<= ENV_LBITS; 1717 | 1718 | Rate_Tabs.SL_TAB[i] = j + ENV_DECAY; 1719 | } 1720 | 1721 | j = ENV_LENGTH - 1; // special case : volume off 1722 | j <<= ENV_LBITS; 1723 | Rate_Tabs.SL_TAB[15] = j + ENV_DECAY; 1724 | 1725 | // Tableau Frequency Step 1726 | 1727 | for (i = 0; i < 2048; i++) 1728 | { 1729 | x = (double) (i) * YM2612.Frequence; 1730 | 1731 | #if ((SIN_LBITS + SIN_HBITS - (21 - 7)) < 0) 1732 | x /= (double) (1 << ((21 - 7) - SIN_LBITS - SIN_HBITS)); 1733 | #else 1734 | x *= (double) (1 << (SIN_LBITS + SIN_HBITS - (21 - 7))); 1735 | #endif 1736 | 1737 | x /= 2.0; // because MUL = value * 2 1738 | 1739 | FINC_TAB[i] = (unsigned int) x; 1740 | } 1741 | 1742 | // Tableaux Attack & Decay Rate 1743 | 1744 | for (i = 0; i < 4; i++) 1745 | { 1746 | Rate_Tabs.AR_TAB[i] = 0; 1747 | Rate_Tabs.DR_TAB[i] = 0; 1748 | } 1749 | 1750 | for (i = 0; i < 60; i++) 1751 | { 1752 | x = YM2612.Frequence; 1753 | 1754 | x *= 1.0 + ((i & 3) * 0.25); // bits 0-1 : x1.00, x1.25, x1.50, x1.75 1755 | x *= (double) (1 << ((i >> 2))); // bits 2-5 : shift bits (x2^0 - x2^15) 1756 | x *= (double) (ENV_LENGTH << ENV_LBITS); // on ajuste pour le tableau ENV_TAB 1757 | 1758 | Rate_Tabs.AR_TAB[i + 4] = (unsigned int) (x / AR_RATE); 1759 | Rate_Tabs.DR_TAB[i + 4] = (unsigned int) (x / DR_RATE); 1760 | } 1761 | 1762 | for (i = 64; i < 96; i++) 1763 | { 1764 | Rate_Tabs.AR_TAB[i] = Rate_Tabs.AR_TAB[63]; 1765 | Rate_Tabs.DR_TAB[i] = Rate_Tabs.DR_TAB[63]; 1766 | 1767 | Rate_Tabs.NULL_RATE[i - 64] = 0; 1768 | } 1769 | 1770 | // Tableau Detune 1771 | 1772 | for (i = 0; i < 4; i++) 1773 | { 1774 | for (j = 0; j < 32; j++) 1775 | { 1776 | #if ((SIN_LBITS + SIN_HBITS - 21) < 0) 1777 | x = (double)DT_DEF_TAB[i][j] * YM2612.Frequence / 1778 | (double)(1 << (21 - SIN_LBITS - SIN_HBITS)); 1779 | #else 1780 | x = (double)DT_DEF_TAB[i][j] * YM2612.Frequence * 1781 | (double)(1 << (SIN_LBITS + SIN_HBITS - 21)); 1782 | #endif 1783 | 1784 | Rate_Tabs.DT_TAB[i + 0][j] = (int) x; 1785 | Rate_Tabs.DT_TAB[i + 4][j] = (int) -x; 1786 | } 1787 | } 1788 | 1789 | // Tableau LFO 1790 | 1791 | j = (YM2612.Rate * YM2612.Inter_Step) / 0x4000; 1792 | 1793 | LFO_INC_TAB[0] = (unsigned int) (3.98 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / j); 1794 | LFO_INC_TAB[1] = (unsigned int) (5.56 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / j); 1795 | LFO_INC_TAB[2] = (unsigned int) (6.02 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / j); 1796 | LFO_INC_TAB[3] = (unsigned int) (6.37 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / j); 1797 | LFO_INC_TAB[4] = (unsigned int) (6.88 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / j); 1798 | LFO_INC_TAB[5] = (unsigned int) (9.63 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / j); 1799 | LFO_INC_TAB[6] = (unsigned int) (48.1 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / j); 1800 | LFO_INC_TAB[7] = (unsigned int) (72.2 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / j); 1801 | 1802 | YM2612_Reset(); 1803 | 1804 | return 0; 1805 | } 1806 | 1807 | 1808 | int YM2612_End(void) 1809 | { 1810 | return 0; 1811 | } 1812 | 1813 | 1814 | int YM2612_Reset(void) 1815 | { 1816 | int i, j; 1817 | 1818 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG1, 1819 | // "Starting reseting YM2612 ..."); 1820 | 1821 | YM2612.LFOcnt = 0; 1822 | YM2612.TimerA = 0; 1823 | YM2612.TimerAL = 0; 1824 | YM2612.TimerAcnt = 0; 1825 | YM2612.TimerB = 0; 1826 | YM2612.TimerBL = 0; 1827 | YM2612.TimerBcnt = 0; 1828 | YM2612.DAC = 0; 1829 | YM2612.DACdata = 0; 1830 | 1831 | YM2612.status = 0; 1832 | 1833 | YM2612.OPNAadr = 0; 1834 | YM2612.OPNBadr = 0; 1835 | YM2612.Inter_Cnt = 0; 1836 | 1837 | for (i = 0; i < 6; i++) 1838 | { 1839 | YM2612.CHANNEL[i].Old_OUTd = 0; 1840 | YM2612.CHANNEL[i].OUTd = 0; 1841 | YM2612.CHANNEL[i].LEFT = 0xFFFFFFFF; 1842 | YM2612.CHANNEL[i].RIGHT = 0xFFFFFFFF; 1843 | YM2612.CHANNEL[i].ALGO = 0;; 1844 | YM2612.CHANNEL[i].FB = 31; 1845 | YM2612.CHANNEL[i].FMS = 0; 1846 | YM2612.CHANNEL[i].AMS = 0; 1847 | 1848 | for (j = 0; j < 4; j++) 1849 | { 1850 | YM2612.CHANNEL[i].S0_OUT[j] = 0; 1851 | YM2612.CHANNEL[i].FNUM[j] = 0; 1852 | YM2612.CHANNEL[i].FOCT[j] = 0; 1853 | YM2612.CHANNEL[i].KC[j] = 0; 1854 | 1855 | YM2612.CHANNEL[i].SLOT[j].Fcnt = 0; 1856 | YM2612.CHANNEL[i].SLOT[j].Finc = 0; 1857 | YM2612.CHANNEL[i].SLOT[j].Ecnt = ENV_END; // Put it at the end of Decay phase... 1858 | YM2612.CHANNEL[i].SLOT[j].Einc = 0; 1859 | YM2612.CHANNEL[i].SLOT[j].Ecmp = 0; 1860 | YM2612.CHANNEL[i].SLOT[j].Ecurp = RELEASE; 1861 | 1862 | YM2612.CHANNEL[i].SLOT[j].ChgEnM = 0; 1863 | } 1864 | } 1865 | 1866 | for (i = 0; i < 0x100; i++) 1867 | { 1868 | YM2612.REG[0][i] = -1; 1869 | YM2612.REG[1][i] = -1; 1870 | } 1871 | 1872 | for (i = 0xB6; i >= 0xB4; i--) 1873 | { 1874 | YM2612_Write(0, (unsigned char) i); 1875 | YM2612_Write(2, (unsigned char) i); 1876 | YM2612_Write(1, 0xC0); 1877 | YM2612_Write(3, 0xC0); 1878 | } 1879 | 1880 | for (i = 0xB2; i >= 0x22; i--) 1881 | { 1882 | YM2612_Write(0, (unsigned char) i); 1883 | YM2612_Write(2, (unsigned char) i); 1884 | YM2612_Write(1, 0); 1885 | YM2612_Write(3, 0); 1886 | } 1887 | 1888 | YM2612_Write(0, 0x2A); 1889 | YM2612_Write(1, 0x80); 1890 | 1891 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG1, 1892 | // "Finishing reseting YM2612 ..."); 1893 | 1894 | return 0; 1895 | } 1896 | 1897 | 1898 | uint8_t YM2612_Read(void) 1899 | { 1900 | #if 0 1901 | static int cnt = 0; 1902 | 1903 | if (cnt++ == 50) 1904 | { 1905 | cnt = 0; 1906 | return YM2612.Status; 1907 | } 1908 | else return YM2612.Status | 0x80; 1909 | #endif 1910 | 1911 | /** 1912 | * READ DATA is the same for all four addresses. 1913 | * Format: [BUSY X X X X X OVRA OVRB] 1914 | * BUSY: If 1, YM2612 is busy and cannot accept new data. 1915 | * OVRA: If 1, timer A has overflowed. 1916 | * OVRB: If 1, timer B has overflowed. 1917 | */ 1918 | return (uint8_t)YM2612.status; 1919 | } 1920 | 1921 | 1922 | /** 1923 | * YM2612_Write(): Write to a YM2612 register. 1924 | * @param adr Address. 1925 | * @param data Data. 1926 | * @return 0 on success; non-zero on error. (TODO: This isn't used by anything!) 1927 | */ 1928 | int YM2612_Write(unsigned int adr, uint8_t data) 1929 | { 1930 | /** 1931 | * Possible addresses: 1932 | * - 0: Part 1 register number. 1933 | * - 1: Part 1 data. 1934 | * - 2: Part 2 register number. 1935 | * - 3: Part 2 data. 1936 | */ 1937 | 1938 | int d; 1939 | switch (adr & 0x03) 1940 | { 1941 | case 0: 1942 | YM2612.OPNAadr = data; 1943 | break; 1944 | 1945 | case 1: 1946 | // Trivial optimisation 1947 | 1948 | if (YM2612.OPNAadr == 0x2A) 1949 | { 1950 | YM2612.DACdata = ((int)data - 0x80) << 7; 1951 | return 0; 1952 | } 1953 | 1954 | d = YM2612.OPNAadr & 0xF0; 1955 | 1956 | if (d >= 0x30) 1957 | { 1958 | if (YM2612.REG[0][YM2612.OPNAadr] == data) 1959 | return 2; 1960 | YM2612.REG[0][YM2612.OPNAadr] = data; 1961 | 1962 | // if (GYM_Dumping) 1963 | // gym_dump_update(1, (uint8_t)YM2612.OPNAadr, data); 1964 | 1965 | if (d < 0xA0) // SLOT 1966 | { 1967 | SLOT_SET(YM2612.OPNAadr, data); 1968 | } 1969 | else // CHANNEL 1970 | { 1971 | CHANNEL_SET(YM2612.OPNAadr, data); 1972 | } 1973 | } 1974 | else // YM2612 1975 | { 1976 | YM2612.REG[0][YM2612.OPNAadr] = data; 1977 | 1978 | // if ((GYM_Dumping) && 1979 | // ((YM2612.OPNAadr == 0x22) || 1980 | // (YM2612.OPNAadr == 0x27) || 1981 | // (YM2612.OPNAadr == 0x28))) 1982 | // { 1983 | // gym_dump_update(1, (uint8_t)YM2612.OPNAadr, data); 1984 | // } 1985 | 1986 | YM_SET(YM2612.OPNAadr, data); 1987 | } 1988 | break; 1989 | 1990 | case 2: 1991 | YM2612.OPNBadr = data; 1992 | break; 1993 | 1994 | case 3: 1995 | d = YM2612.OPNBadr & 0xF0; 1996 | 1997 | if (d >= 0x30) 1998 | { 1999 | if (YM2612.REG[1][YM2612.OPNBadr] == data) 2000 | return 2; 2001 | YM2612.REG[1][YM2612.OPNBadr] = data; 2002 | 2003 | // if (GYM_Dumping) 2004 | // gym_dump_update(2, (uint8_t)YM2612.OPNBadr, data); 2005 | 2006 | if (d < 0xA0) // SLOT 2007 | { 2008 | SLOT_SET(YM2612.OPNBadr + 0x100, data); 2009 | } 2010 | else // CHANNEL 2011 | { 2012 | CHANNEL_SET(YM2612.OPNBadr + 0x100, data); 2013 | } 2014 | } 2015 | else 2016 | return 1; 2017 | break; 2018 | } 2019 | 2020 | return 0; 2021 | } 2022 | 2023 | 2024 | void YM2612_Update(int **buf, int length) 2025 | { 2026 | int i, j, algo_type; 2027 | 2028 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG4, 2029 | // "Starting generating sound..."); 2030 | 2031 | // Mise à jour des pas des compteurs-fréquences s'ils ont été modifiés 2032 | 2033 | if (YM2612.CHANNEL[0].SLOT[0].Finc == -1) 2034 | CALC_FINC_CH(&YM2612.CHANNEL[0]); 2035 | if (YM2612.CHANNEL[1].SLOT[0].Finc == -1) 2036 | CALC_FINC_CH(&YM2612.CHANNEL[1]); 2037 | if (YM2612.CHANNEL[2].SLOT[0].Finc == -1) 2038 | { 2039 | if (YM2612.Mode & 0x40) 2040 | { 2041 | CALC_FINC_SL(&(YM2612.CHANNEL[2].SLOT[S0]), 2042 | FINC_TAB[YM2612.CHANNEL[2].FNUM[2]] >> (7 - YM2612.CHANNEL[2].FOCT[2]), 2043 | YM2612.CHANNEL[2].KC[2]); 2044 | CALC_FINC_SL(&(YM2612.CHANNEL[2].SLOT[S1]), 2045 | FINC_TAB[YM2612.CHANNEL[2].FNUM[3]] >> (7 - YM2612.CHANNEL[2].FOCT[3]), 2046 | YM2612.CHANNEL[2].KC[3]); 2047 | CALC_FINC_SL(&(YM2612.CHANNEL[2].SLOT[S2]), 2048 | FINC_TAB[YM2612.CHANNEL[2].FNUM[1]] >> (7 - YM2612.CHANNEL[2].FOCT[1]), 2049 | YM2612.CHANNEL[2].KC[1]); 2050 | CALC_FINC_SL(&(YM2612.CHANNEL[2].SLOT[S3]), 2051 | FINC_TAB[YM2612.CHANNEL[2].FNUM[0]] >> (7 - YM2612.CHANNEL[2].FOCT[0]), 2052 | YM2612.CHANNEL[2].KC[0]); 2053 | } 2054 | else 2055 | { 2056 | CALC_FINC_CH(&YM2612.CHANNEL[2]); 2057 | } 2058 | } 2059 | if (YM2612.CHANNEL[3].SLOT[0].Finc == -1) 2060 | CALC_FINC_CH(&YM2612.CHANNEL[3]); 2061 | if (YM2612.CHANNEL[4].SLOT[0].Finc == -1) 2062 | CALC_FINC_CH(&YM2612.CHANNEL[4]); 2063 | if (YM2612.CHANNEL[5].SLOT[0].Finc == -1) 2064 | CALC_FINC_CH(&YM2612.CHANNEL[5]); 2065 | 2066 | /* 2067 | CALC_FINC_CH(&YM2612.CHANNEL[0]); 2068 | CALC_FINC_CH(&YM2612.CHANNEL[1]); 2069 | if (YM2612.Mode & 0x40) 2070 | { 2071 | CALC_FINC_SL(&(YM2612.CHANNEL[2].SLOT[0]), FINC_TAB[YM2612.CHANNEL[2].FNUM[2]] >> (7 - YM2612.CHANNEL[2].FOCT[2]), YM2612.CHANNEL[2].KC[2]); 2072 | CALC_FINC_SL(&(YM2612.CHANNEL[2].SLOT[1]), FINC_TAB[YM2612.CHANNEL[2].FNUM[3]] >> (7 - YM2612.CHANNEL[2].FOCT[3]), YM2612.CHANNEL[2].KC[3]); 2073 | CALC_FINC_SL(&(YM2612.CHANNEL[2].SLOT[2]), FINC_TAB[YM2612.CHANNEL[2].FNUM[1]] >> (7 - YM2612.CHANNEL[2].FOCT[1]), YM2612.CHANNEL[2].KC[1]); 2074 | CALC_FINC_SL(&(YM2612.CHANNEL[2].SLOT[3]), FINC_TAB[YM2612.CHANNEL[2].FNUM[0]] >> (7 - YM2612.CHANNEL[2].FOCT[0]), YM2612.CHANNEL[2].KC[0]); 2075 | } 2076 | else 2077 | { 2078 | CALC_FINC_CH(&YM2612.CHANNEL[2]); 2079 | } 2080 | CALC_FINC_CH(&YM2612.CHANNEL[3]); 2081 | CALC_FINC_CH(&YM2612.CHANNEL[4]); 2082 | CALC_FINC_CH(&YM2612.CHANNEL[5]); 2083 | */ 2084 | 2085 | if (YM2612.Inter_Step & 0x04000) 2086 | algo_type = 0; 2087 | else 2088 | algo_type = 16; 2089 | 2090 | if (YM2612.LFOinc) 2091 | { 2092 | // Precalcul LFO wav 2093 | 2094 | for (i = 0; i < length; i++) 2095 | { 2096 | j = ((YM2612.LFOcnt += YM2612.LFOinc) >> LFO_LBITS) & LFO_MASK; 2097 | 2098 | LFO_ENV_UP[i] = LFO_ENV_TAB[j]; 2099 | LFO_FREQ_UP[i] = LFO_FREQ_TAB[j]; 2100 | 2101 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG4, 2102 | // "LFO_ENV_UP[%d] = %d LFO_FREQ_UP[%d] = %d", 2103 | // i, LFO_ENV_UP[i], i, LFO_FREQ_UP[i]); 2104 | } 2105 | 2106 | algo_type |= 8; 2107 | } 2108 | 2109 | UPDATE_CHAN[YM2612.CHANNEL[0].ALGO + algo_type](&(YM2612.CHANNEL[0]), buf, length); 2110 | UPDATE_CHAN[YM2612.CHANNEL[1].ALGO + algo_type](&(YM2612.CHANNEL[1]), buf, length); 2111 | UPDATE_CHAN[YM2612.CHANNEL[2].ALGO + algo_type](&(YM2612.CHANNEL[2]), buf, length); 2112 | UPDATE_CHAN[YM2612.CHANNEL[3].ALGO + algo_type](&(YM2612.CHANNEL[3]), buf, length); 2113 | UPDATE_CHAN[YM2612.CHANNEL[4].ALGO + algo_type](&(YM2612.CHANNEL[4]), buf, length); 2114 | if (!(YM2612.DAC)) 2115 | UPDATE_CHAN[YM2612.CHANNEL[5].ALGO + algo_type](&(YM2612.CHANNEL[5]), buf, length); 2116 | 2117 | YM2612.Inter_Cnt = int_cnt; 2118 | 2119 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG4, 2120 | // "Finishing generating sound..."); 2121 | 2122 | } 2123 | 2124 | 2125 | int YM2612_Save(unsigned char SAVE[0x200]) 2126 | { 2127 | int i; 2128 | 2129 | for (i = 0; i < 0x100; i++) 2130 | { 2131 | SAVE[0x000 + i] = YM2612.REG[0][i]; 2132 | SAVE[0x100 + i] = YM2612.REG[1][i]; 2133 | } 2134 | 2135 | return 0; 2136 | } 2137 | 2138 | 2139 | int YM2612_Restore(unsigned char SAVE[0x200]) 2140 | { 2141 | int i; 2142 | 2143 | YM2612_Reset(); 2144 | 2145 | for (i = 0; i < 0x100; i++) 2146 | { 2147 | YM2612_Write(0, (unsigned char) i); 2148 | YM2612_Write(1, SAVE[0x000 + i]); 2149 | YM2612_Write(2, (unsigned char) i); 2150 | YM2612_Write(3, SAVE[0x100 + i]); 2151 | } 2152 | 2153 | return 0; 2154 | } 2155 | 2156 | #if 0 2157 | /** 2158 | * YM2612_Save_Full(): Save the entire contents of the YM2612's registers. (Gens Rerecording) 2159 | * @param save GSX v7 YM2612 struct to save the registers in. 2160 | * @return 0 on success. 2161 | */ 2162 | int YM2612_Save_Full(gsx_v7_ym2612 *save) 2163 | { 2164 | // Copy the main YM2612 data. 2165 | save->clock_freq = cpu_to_le32(YM2612.Clock); 2166 | save->sample_rate = cpu_to_le32(YM2612.Rate); 2167 | save->timer_base = cpu_to_le32(YM2612.TimerBase); 2168 | save->status = cpu_to_le32(YM2612.status); 2169 | save->OPNA_addr = cpu_to_le32(YM2612.OPNAadr); 2170 | save->OPNB_addr = cpu_to_le32(YM2612.OPNBadr); 2171 | save->LFOcnt = cpu_to_le32(YM2612.LFOcnt); 2172 | save->LFOinc = cpu_to_le32(YM2612.LFOinc); 2173 | 2174 | save->timerA = cpu_to_le32(YM2612.TimerA); 2175 | save->timerAL = cpu_to_le32(YM2612.TimerAL); 2176 | save->timerAcnt = cpu_to_le32(YM2612.TimerAcnt); 2177 | save->timerB = cpu_to_le32(YM2612.TimerB); 2178 | save->timerBL = cpu_to_le32(YM2612.TimerBL); 2179 | save->timerBcnt = cpu_to_le32(YM2612.TimerBcnt); 2180 | save->mode = cpu_to_le32(YM2612.Mode); 2181 | save->dac_enabled = cpu_to_le32(YM2612.DAC); 2182 | save->dac_data = cpu_to_le32(YM2612.DACdata); 2183 | 2184 | save->reserved1 = cpu_to_le32(YM2612.dummy); 2185 | save->frequency_base = YM2612.Frequence; // TODO: Figure out endian conversion for floating-point. 2186 | 2187 | save->interp_cnt = cpu_to_le32(YM2612.Inter_Cnt); 2188 | save->interp_step = cpu_to_le32(YM2612.Inter_Step); 2189 | 2190 | // Registers. 2191 | int bank, reg; 2192 | for (bank = 0; bank < 2; bank++) 2193 | { 2194 | for (reg = 0; reg < 0x100; reg++) 2195 | { 2196 | save->reg[bank][reg] = cpu_to_le32(YM2612.REG[bank][reg]); 2197 | } 2198 | } 2199 | 2200 | // Channels. 2201 | int channel; 2202 | for (channel = 0; channel < 6; channel++) 2203 | { 2204 | gsx_v7_ym2612_channel *chanGSX = &save->channels[channel]; 2205 | channel_ *chanYM = &YM2612.CHANNEL[channel]; 2206 | 2207 | chanGSX->S0_OUT[0] = cpu_to_le32(chanYM->S0_OUT[0]); 2208 | chanGSX->S0_OUT[1] = cpu_to_le32(chanYM->S0_OUT[1]); 2209 | chanGSX->S0_OUT[2] = cpu_to_le32(chanYM->S0_OUT[2]); 2210 | chanGSX->S0_OUT[3] = cpu_to_le32(chanYM->S0_OUT[3]); 2211 | 2212 | chanGSX->Old_OUTd = cpu_to_le32(chanYM->Old_OUTd); 2213 | chanGSX->OUTd = cpu_to_le32(chanYM->OUTd); 2214 | chanGSX->LEFT = cpu_to_le32(chanYM->LEFT); 2215 | chanGSX->RIGHT = cpu_to_le32(chanYM->RIGHT); 2216 | chanGSX->ALGO = cpu_to_le32(chanYM->ALGO); 2217 | chanGSX->FB = cpu_to_le32(chanYM->FB); 2218 | chanGSX->FMS = cpu_to_le32(chanYM->FMS); 2219 | chanGSX->AMS = cpu_to_le32(chanYM->AMS); 2220 | 2221 | chanGSX->FNUM[0] = cpu_to_le32(chanYM->FNUM[0]); 2222 | chanGSX->FNUM[1] = cpu_to_le32(chanYM->FNUM[1]); 2223 | chanGSX->FNUM[2] = cpu_to_le32(chanYM->FNUM[2]); 2224 | chanGSX->FNUM[3] = cpu_to_le32(chanYM->FNUM[3]); 2225 | 2226 | chanGSX->FOCT[0] = cpu_to_le32(chanYM->FOCT[0]); 2227 | chanGSX->FOCT[1] = cpu_to_le32(chanYM->FOCT[1]); 2228 | chanGSX->FOCT[2] = cpu_to_le32(chanYM->FOCT[2]); 2229 | chanGSX->FOCT[3] = cpu_to_le32(chanYM->FOCT[3]); 2230 | 2231 | chanGSX->KC[0] = cpu_to_le32(chanYM->KC[0]); 2232 | chanGSX->KC[1] = cpu_to_le32(chanYM->KC[1]); 2233 | chanGSX->KC[2] = cpu_to_le32(chanYM->KC[2]); 2234 | chanGSX->KC[3] = cpu_to_le32(chanYM->KC[3]); 2235 | 2236 | chanGSX->FFlag = cpu_to_le32(chanYM->FFlag); 2237 | 2238 | // Slots. 2239 | int slot; 2240 | for (slot = 0; slot < 4; slot++) 2241 | { 2242 | gsx_v7_ym2612_slot *slotGSX = &chanGSX->slot[slot]; 2243 | slot_ *slotYM = &chanYM->SLOT[slot]; 2244 | 2245 | // DT is a pointer, so it needs to be normalized to an offset. 2246 | slotGSX->DT = cpu_to_le32((uint32_t)(slotYM->DT - (unsigned int*)&Rate_Tabs.DT_TAB[0][0])); 2247 | 2248 | // Regular ints. 2249 | slotGSX->MUL = cpu_to_le32(slotYM->MUL); 2250 | slotGSX->TL = cpu_to_le32(slotYM->TL); 2251 | slotGSX->TLL = cpu_to_le32(slotYM->TLL); 2252 | slotGSX->SLL = cpu_to_le32(slotYM->SLL); 2253 | slotGSX->KSR_S = cpu_to_le32(slotYM->KSR_S); 2254 | slotGSX->KSR = cpu_to_le32(slotYM->KSR); 2255 | slotGSX->SEG = cpu_to_le32(slotYM->SEG); 2256 | 2257 | // The following four values are pointers, so they 2258 | // need to be normalized to offsets. 2259 | slotGSX->AR = cpu_to_le32((uint32_t)(slotYM->AR - (unsigned int*)&Rate_Tabs.AR_TAB[0])); 2260 | slotGSX->DR = cpu_to_le32((uint32_t)(slotYM->DR - (unsigned int*)&Rate_Tabs.DR_TAB[0])); 2261 | slotGSX->SR = cpu_to_le32((uint32_t)(slotYM->SR - (unsigned int*)&Rate_Tabs.DR_TAB[0])); 2262 | slotGSX->RR = cpu_to_le32((uint32_t)(slotYM->RR - (unsigned int*)&Rate_Tabs.DR_TAB[0])); 2263 | 2264 | // Regular ints. 2265 | slotGSX->Fcnt = cpu_to_le32(slotYM->Fcnt); 2266 | slotGSX->Finc = cpu_to_le32(slotYM->Finc); 2267 | 2268 | slotGSX->Ecurp = cpu_to_le32(slotYM->Ecurp); 2269 | slotGSX->Einc = cpu_to_le32(slotYM->Einc); 2270 | slotGSX->Ecnt = cpu_to_le32(slotYM->Ecnt); 2271 | slotGSX->Ecmp = cpu_to_le32(slotYM->Ecmp); 2272 | 2273 | slotGSX->EincA = cpu_to_le32(slotYM->EincA); 2274 | slotGSX->EincD = cpu_to_le32(slotYM->EincD); 2275 | slotGSX->EincS = cpu_to_le32(slotYM->EincS); 2276 | slotGSX->EincR = cpu_to_le32(slotYM->EincR); 2277 | 2278 | // NOTE: This seems to be unused... 2279 | slotGSX->OUTp = cpu_to_le32((int)(slotYM->OUTp)); 2280 | 2281 | slotGSX->INd = cpu_to_le32(slotYM->INd); 2282 | slotGSX->ChgEnM = cpu_to_le32(slotYM->ChgEnM); 2283 | slotGSX->AMS = cpu_to_le32(slotYM->AMS); 2284 | slotGSX->AMSon = cpu_to_le32(slotYM->AMSon); 2285 | } 2286 | } 2287 | 2288 | return 0; 2289 | } 2290 | 2291 | 2292 | /** 2293 | * YM2612_Restore_Full(): Restore the entire contents of the YM2612's registers. (Gens Rerecording) 2294 | * @param SAVE Buffer containing the registers to restore. 2295 | * @return 0 on success. 2296 | */ 2297 | int YM2612_Restore_Full(gsx_v7_ym2612 *save) 2298 | { 2299 | // Copy the main YM2612 data. 2300 | YM2612.Clock = le32_to_cpu(save->clock_freq); 2301 | YM2612.Rate = le32_to_cpu(save->sample_rate); 2302 | YM2612.TimerBase = le32_to_cpu(save->timer_base); 2303 | YM2612.status = le32_to_cpu(save->status); 2304 | YM2612.OPNAadr = le32_to_cpu(save->OPNA_addr); 2305 | YM2612.OPNBadr = le32_to_cpu(save->OPNB_addr); 2306 | YM2612.LFOcnt = le32_to_cpu(save->LFOcnt); 2307 | YM2612.LFOinc = le32_to_cpu(save->LFOinc); 2308 | 2309 | YM2612.TimerA = le32_to_cpu(save->timerA); 2310 | YM2612.TimerAL = le32_to_cpu(save->timerAL); 2311 | YM2612.TimerAcnt = le32_to_cpu(save->timerAcnt); 2312 | YM2612.TimerB = le32_to_cpu(save->timerB); 2313 | YM2612.TimerBL = le32_to_cpu(save->timerBL); 2314 | YM2612.TimerBcnt = le32_to_cpu(save->timerBcnt); 2315 | YM2612.Mode = le32_to_cpu(save->mode); 2316 | YM2612.DAC = le32_to_cpu(save->dac_enabled); 2317 | YM2612.DACdata = le32_to_cpu(save->dac_data); 2318 | 2319 | YM2612.dummy = le32_to_cpu(save->reserved1); 2320 | YM2612.Frequence = save->frequency_base; // TODO: Figure out endian conversion for floating-point. 2321 | 2322 | YM2612.Inter_Cnt = le32_to_cpu(save->interp_cnt); 2323 | YM2612.Inter_Step = le32_to_cpu(save->interp_step); 2324 | 2325 | // Registers. 2326 | int bank, reg; 2327 | for (bank = 0; bank < 2; bank++) 2328 | { 2329 | for (reg = 0; reg < 0x100; reg++) 2330 | { 2331 | YM2612.REG[bank][reg] = le32_to_cpu(save->reg[bank][reg]); 2332 | } 2333 | } 2334 | 2335 | // Channels. 2336 | int channel; 2337 | for (channel = 0; channel < 6; channel++) 2338 | { 2339 | gsx_v7_ym2612_channel *chanGSX = &save->channels[channel]; 2340 | channel_ *chanYM = &YM2612.CHANNEL[channel]; 2341 | 2342 | chanYM->S0_OUT[0] = le32_to_cpu(chanGSX->S0_OUT[0]); 2343 | chanYM->S0_OUT[1] = le32_to_cpu(chanGSX->S0_OUT[1]); 2344 | chanYM->S0_OUT[2] = le32_to_cpu(chanGSX->S0_OUT[2]); 2345 | chanYM->S0_OUT[3] = le32_to_cpu(chanGSX->S0_OUT[3]); 2346 | 2347 | chanYM->Old_OUTd = le32_to_cpu(chanGSX->Old_OUTd); 2348 | chanYM->OUTd = le32_to_cpu(chanGSX->OUTd); 2349 | chanYM->LEFT = le32_to_cpu(chanGSX->LEFT); 2350 | chanYM->RIGHT = le32_to_cpu(chanGSX->RIGHT); 2351 | chanYM->ALGO = le32_to_cpu(chanGSX->ALGO); 2352 | chanYM->FB = le32_to_cpu(chanGSX->FB); 2353 | chanYM->FMS = le32_to_cpu(chanGSX->FMS); 2354 | chanYM->AMS = le32_to_cpu(chanGSX->AMS); 2355 | 2356 | chanYM->FNUM[0] = le32_to_cpu(chanGSX->FNUM[0]); 2357 | chanYM->FNUM[1] = le32_to_cpu(chanGSX->FNUM[1]); 2358 | chanYM->FNUM[2] = le32_to_cpu(chanGSX->FNUM[2]); 2359 | chanYM->FNUM[3] = le32_to_cpu(chanGSX->FNUM[3]); 2360 | 2361 | chanYM->FOCT[0] = le32_to_cpu(chanGSX->FOCT[0]); 2362 | chanYM->FOCT[1] = le32_to_cpu(chanGSX->FOCT[1]); 2363 | chanYM->FOCT[2] = le32_to_cpu(chanGSX->FOCT[2]); 2364 | chanYM->FOCT[3] = le32_to_cpu(chanGSX->FOCT[3]); 2365 | 2366 | chanYM->KC[0] = le32_to_cpu(chanGSX->KC[0]); 2367 | chanYM->KC[1] = le32_to_cpu(chanGSX->KC[1]); 2368 | chanYM->KC[2] = le32_to_cpu(chanGSX->KC[2]); 2369 | chanYM->KC[3] = le32_to_cpu(chanGSX->KC[3]); 2370 | 2371 | chanYM->FFlag = le32_to_cpu(chanGSX->FFlag); 2372 | 2373 | // Slots. 2374 | int slot; 2375 | for (slot = 0; slot < 4; slot++) 2376 | { 2377 | gsx_v7_ym2612_slot *slotGSX = &chanGSX->slot[slot]; 2378 | slot_ *slotYM = &chanYM->SLOT[slot]; 2379 | 2380 | // DT is a pointer, so it needs to be converted from an offset. 2381 | slotYM->DT = le32_to_cpu(slotGSX->DT) + (unsigned int*)&Rate_Tabs.DT_TAB[0][0]; 2382 | 2383 | // Regular ints. 2384 | slotYM->MUL = le32_to_cpu(slotGSX->MUL); 2385 | slotYM->TL = le32_to_cpu(slotGSX->TL); 2386 | slotYM->TLL = le32_to_cpu(slotGSX->TLL); 2387 | slotYM->SLL = le32_to_cpu(slotGSX->SLL); 2388 | slotYM->KSR_S = le32_to_cpu(slotGSX->KSR_S); 2389 | slotYM->KSR = le32_to_cpu(slotGSX->KSR); 2390 | slotYM->SEG = le32_to_cpu(slotGSX->SEG); 2391 | 2392 | // The following four values are pointers, so they 2393 | // need to be normalized to offsets. 2394 | slotYM->AR = le32_to_cpu(slotGSX->AR) + (unsigned int*)&Rate_Tabs.AR_TAB[0]; 2395 | slotYM->DR = le32_to_cpu(slotGSX->DR) + (unsigned int*)&Rate_Tabs.DR_TAB[0]; 2396 | slotYM->SR = le32_to_cpu(slotGSX->SR) + (unsigned int*)&Rate_Tabs.DR_TAB[0]; 2397 | slotYM->RR = le32_to_cpu(slotGSX->RR) + (unsigned int*)&Rate_Tabs.DR_TAB[0]; 2398 | 2399 | // Regular ints. 2400 | slotYM->Fcnt = le32_to_cpu(slotGSX->Fcnt); 2401 | slotYM->Finc = le32_to_cpu(slotGSX->Finc); 2402 | 2403 | slotYM->Ecurp = le32_to_cpu(slotGSX->Ecurp); 2404 | slotYM->Einc = le32_to_cpu(slotGSX->Einc); 2405 | slotYM->Ecnt = le32_to_cpu(slotGSX->Ecnt); 2406 | slotYM->Ecmp = le32_to_cpu(slotGSX->Ecmp); 2407 | 2408 | slotYM->EincA = le32_to_cpu(slotGSX->EincA); 2409 | slotYM->EincD = le32_to_cpu(slotGSX->EincD); 2410 | slotYM->EincS = le32_to_cpu(slotGSX->EincS); 2411 | slotYM->EincR = le32_to_cpu(slotGSX->EincR); 2412 | 2413 | // NOTE: This seems to be unused... 2414 | slotYM->OUTp = (int*)(le32_to_cpu((int)(slotGSX->OUTp))); 2415 | 2416 | slotYM->INd = le32_to_cpu(slotGSX->INd); 2417 | slotYM->ChgEnM = le32_to_cpu(slotGSX->ChgEnM); 2418 | slotYM->AMS = le32_to_cpu(slotGSX->AMS); 2419 | slotYM->AMSon = le32_to_cpu(slotGSX->AMSon); 2420 | } 2421 | } 2422 | 2423 | return 0; 2424 | } 2425 | 2426 | /* Gens */ 2427 | 2428 | #endif 2429 | void YM2612_DacAndTimers_Update(int **buffer, int length) 2430 | { 2431 | int *bufL, *bufR; 2432 | int i; 2433 | 2434 | if (YM2612.DAC && YM2612.DACdata && DAC_Enable) 2435 | { 2436 | bufL = buffer[0]; 2437 | bufR = buffer[1]; 2438 | 2439 | for (i = 0; i < length; i++) 2440 | { 2441 | bufL[i] += YM2612.DACdata & YM2612.CHANNEL[5].LEFT; 2442 | bufR[i] += YM2612.DACdata & YM2612.CHANNEL[5].RIGHT; 2443 | } 2444 | } 2445 | 2446 | i = YM2612.TimerBase * length; 2447 | 2448 | if (YM2612.Mode & 1) // Timer A ON ? 2449 | { 2450 | //if ((YM2612.TimerAcnt -= 14073) <= 0) // 13879=NTSC (old: 14475=NTSC 14586=PAL) 2451 | if ((YM2612.TimerAcnt -= i) <= 0) 2452 | { 2453 | YM2612.status |= (YM2612.Mode & 0x04) >> 2; 2454 | YM2612.TimerAcnt += YM2612.TimerAL; 2455 | 2456 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG1, 2457 | // "Counter A overflow"); 2458 | 2459 | if (YM2612.Mode & 0x80) 2460 | CSM_Key_Control(); 2461 | } 2462 | } 2463 | 2464 | if (YM2612.Mode & 2) // Timer B ON ? 2465 | { 2466 | //if ((YM2612.TimerBcnt -= 14073) <= 0) // 13879=NTSC (old: 14475=NTSC 14586=PAL) 2467 | if ((YM2612.TimerBcnt -= i) <= 0) 2468 | { 2469 | YM2612.status |= (YM2612.Mode & 0x08) >> 2; 2470 | YM2612.TimerBcnt += YM2612.TimerBL; 2471 | 2472 | // LOG_MSG(ym2612, LOG_MSG_LEVEL_DEBUG1, 2473 | // "Counter B overflow"); 2474 | } 2475 | } 2476 | } 2477 | 2478 | 2479 | void YM2612_Special_Update(void) 2480 | { 2481 | #if 0 2482 | if (YM_Len && YM2612_Enable) 2483 | { 2484 | YM2612_Update(YM_Buf, YM_Len); 2485 | 2486 | YM_Buf[0] = Seg_L + Sound_Extrapol[VDP_Lines.Display.Current + 1][0]; 2487 | YM_Buf[1] = Seg_R + Sound_Extrapol[VDP_Lines.Display.Current + 1][0]; 2488 | YM_Len = 0; 2489 | } 2490 | #endif 2491 | } 2492 | 2493 | int YM2612_Get_Reg(int regID) 2494 | { 2495 | if (regID < 0 || regID >= 0x200) 2496 | return -1; 2497 | 2498 | return YM2612.REG[(regID >> 8) & 1][regID & 0xFF]; 2499 | } 2500 | 2501 | void YM2612_ClearBuffer(int **buffer, int length) 2502 | { 2503 | // the MAME core does this before updating, 2504 | // but the Gens core does this before mixing 2505 | int *bufL, *bufR; 2506 | int i; 2507 | 2508 | bufL = buffer[0]; 2509 | bufR = buffer[1]; 2510 | 2511 | for(i = 0; i < length; i++) 2512 | { 2513 | bufL[i] = 0x0000; 2514 | bufR[i] = 0x0000; 2515 | } 2516 | } 2517 | /* end */ 2518 | --------------------------------------------------------------------------------